Compare commits

...

33 Commits

Author SHA1 Message Date
胡尧
4615f1576f 解决采购申请创建的采购单取消后导致后续单据无法就绪的问题 2025-07-02 17:31:43 +08:00
胡尧
c8f1676de9 解决采购申请创建的采购单取消后导致调拨单不能就绪的问题 2025-07-01 17:55:07 +08:00
胡尧
f165bec662 待完工工单明细,控制时间为大于48小时,小于当前时间 2025-06-25 09:42:53 +08:00
胡尧
133eac4a5c 日计划量对工单id去重 2025-06-25 08:43:59 +08:00
胡尧
9922402b3b 修复明细接口bug 2025-06-24 15:56:33 +08:00
胡尧
0a79a4e336 修改未完成订单明细的判断逻辑 2025-06-24 15:50:45 +08:00
胡尧
00922e3674 修改工单状态对应名字 2025-06-24 15:35:19 +08:00
胡尧
2a330a4bd8 修改大屏获取订单详情接口 2025-06-24 14:52:03 +08:00
胡尧
33647fa3e0 修改明细接口 2025-06-24 14:18:27 +08:00
胡尧
a2a652eea4 解决大屏bug 2025-06-23 17:54:38 +08:00
胡尧
05c5c0ef81 修复时间显示问题 2025-06-23 09:22:37 +08:00
胡尧
35e80266d7 修改日产量时间 2025-06-23 08:59:02 +08:00
胡尧
13d33488dc 修改计划量字段为–qty_production 2025-06-20 15:39:11 +08:00
胡尧
2c2fa87719 修改产量接口bug 2025-06-20 11:26:48 +08:00
胡尧
e7b312fb22 去掉多余代码 2025-06-20 10:53:31 +08:00
胡尧
55cc4906ef 修改大屏数据接口,日完成量统计,获取产线产量相关,获取工单明细 2025-06-19 15:02:55 +08:00
胡尧
d21e0c7fd9 修改大屏数据接口,支持线下数据 2025-06-19 10:54:33 +08:00
胡尧
61034c3424 调整数据获取逻辑 2025-06-16 17:33:55 +08:00
胡尧
10e995ec7f 修改获取产量相关接口 2025-06-16 16:25:01 +08:00
胡尧
5c7e6e969f Accept Merge Request #2199: (feature/修改产品名称 -> develop)
Merge Request: 客供料的制造订单,不显示采购申请的智能按钮

Created By: @胡尧
Accepted By: @胡尧
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/2199
2025-06-16 15:00:42 +08:00
管欢
fb3bb8f1c0 Accept Merge Request #2198: (feature/齐套检查与下达生产 -> develop)
Merge Request: 人工线下加工最后一个工单完工后未记录时间完工时间

Created By: @管欢
Reviewed By: @胡尧
Approved By: @胡尧 
Accepted By: @管欢
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/2198
2025-06-16 14:44:40 +08:00
guanhuan
9123aeaee8 人工线下加工最后一个工单完工后未记录时间完工时间 2025-06-16 14:35:28 +08:00
胡尧
e3af0bea3c Accept Merge Request #2197: (feature/修改产品名称 -> develop)
Merge Request: 在调拨单验证前,先进行设置数量

Created By: @胡尧
Accepted By: @胡尧
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/2197?initial=true
2025-06-16 14:25:27 +08:00
guanhuan
2febc369bb 确认工艺路线新增表面工艺参数需要同步到产品的加工参数中 2025-06-16 13:44:55 +08:00
胡尧
6ee1c5f9a9 Accept Merge Request #2196: (feature/修改产品名称 -> develop)
Merge Request: 修改migrate脚本,解决更新慢的问题

Created By: @胡尧
Accepted By: @胡尧
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/2196?initial=true
2025-06-16 13:42:42 +08:00
guanhuan
fa03b562a2 确认工艺路线新增表面工艺参数需要同步到产品的加工参数中 2025-06-16 11:52:22 +08:00
guanhuan
5f55c954d1 确认工艺路线新增表面工艺参数需要同步到产品的加工参数中 2025-06-16 11:42:21 +08:00
胡尧
e0ca13b5b7 Accept Merge Request #2195: (feature/修改产品名称 -> develop)
Merge Request: 修改产品名称

Created By: @胡尧
Accepted By: @胡尧
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/2195?initial=true
2025-06-16 10:51:28 +08:00
胡尧
ceb7a02209 Accept Merge Request #2194: (feature/修改产品名称 -> develop)
Merge Request: 解决修改产品名称带来的影响

Created By: @胡尧
Accepted By: @胡尧
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/2194?initial=true
2025-06-16 09:36:16 +08:00
胡尧
1c1d1a74ad Accept Merge Request #2193: (feature/修改产品名称 -> develop)
Merge Request: 修改产品名称生成规则

Created By: @胡尧
Accepted By: @胡尧
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/2193?initial=true
2025-06-16 09:21:06 +08:00
管欢
7d46d00fd7 Accept Merge Request #2192: (feature/齐套检查与下达生产 -> develop)
Merge Request: 下发时修改需求计划的总预计加工时间

Created By: @管欢
Reviewed By: @胡尧
Approved By: @胡尧 
Accepted By: @管欢
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/2192
2025-06-16 08:53:35 +08:00
胡尧
5a22402e7a Accept Merge Request #2191: (feature/修改产品名称 -> develop)
Merge Request: 修改接口授权后,没有赋予用户的bug,导致无法获取公司,增加替换sf销售订单行产品名称的模块

Created By: @胡尧
Accepted By: @胡尧
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/2191?initial=true
2025-06-13 17:55:13 +08:00
guanhuan
e145e8a3a4 下发时修改需求计划的总预计加工时间 2025-06-13 15:40:02 +08:00
8 changed files with 319 additions and 194 deletions

View File

@@ -31,12 +31,20 @@ class PurchaseOrder(models.Model):
def button_cancel(self):
"""
将取消的采购订单关联的库存移动撤销
1. 先将采购订单行与目标库存移动断开链接避免采购单取消后调拨单被调整为mts的问题
2. 取消采购订单
3. 将采购订单行与目标库存移动重新建立链接
"""
created_purchase_request_line_ids = {}
if self.order_line.move_dest_ids.created_purchase_request_line_id:
move_ids = self.order_line.move_dest_ids.filtered(lambda move: move.state != 'done' and not move.scrapped)
created_purchase_request_line_ids = {move.id: move.created_purchase_request_line_id for move in move_ids}
self.order_line.write({'move_dest_ids': [(5, 0, 0)]})
res =super(PurchaseOrder, self).button_cancel()
if move_ids.mapped('created_purchase_request_line_id'):
move_ids.write({'state': 'waiting', 'is_done': False})
for move_id, created_purchase_request_line_id in created_purchase_request_line_ids.items():
self.env['stock.move'].browse(move_id).created_purchase_request_line_id = created_purchase_request_line_id
# if move_ids.mapped('created_purchase_request_line_id'):
# move_ids.write({'state': 'waiting', 'is_done': False})
return res
def write(self, vals):

View File

@@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
from . import controllers
from . import models
from . import wizard

View File

@@ -1 +0,0 @@
from . import controllers

View File

@@ -1,37 +0,0 @@
# -*- coding: utf-8 -*-
import logging
import json
from odoo import http, fields, models
from odoo.http import request
from odoo.addons.sf_base.controllers.controllers import MultiInheritController
class SfPlanMrsConnect(http.Controller, MultiInheritController):
@http.route('/api/demand_plan/update_processing_time', type='json', auth='sf_token', methods=['GET', 'POST'],
csrf=False,
cors="*")
def update_processing_time(self, **kw):
"""
根据模型id修改程序工时
:param kw:
:return:
"""
try:
res = {'status': 1, 'message': '成功'}
datas = request.httprequest.data
ret = json.loads(datas)
ret = json.loads(ret['result'])
logging.info('根据模型id修改程序工时:%s' % ret)
demand_plan = request.env['sf.production.demand.plan'].sudo().search(
[('model_id', '=', ret['model_id'])])
if demand_plan:
demand_plan.write(
{'processing_time': ret['total_estimated_time']})
else:
res = {'status': 0, 'message': '未查到该需求计划'}
except Exception as e:
logging.info('update_demand_paln error:%s' % e)
res['status'] = -1
res['message'] = '系统解析错误!'
return json.JSONEncoder().encode(res)

View File

@@ -259,7 +259,9 @@ class SfProductionDemandPlan(models.Model):
manufacturing_orders = record.sale_order_id.mrp_production_ids.filtered(
lambda mo: mo.product_id == record.product_id)
finished_orders = manufacturing_orders.filtered(lambda mo: mo.state == 'done')
if len(finished_orders) >= record.product_uom_qty:
sum_product_qty = sum(finished_orders.mapped('product_qty'))
if finished_orders and float_compare(sum_product_qty, record.product_uom_qty,
precision_rounding=record.product_id.uom_id.rounding) >= 0:
end_dates = [
workorder.date_finished for mo in finished_orders
for workorder in mo.workorder_ids if workorder.date_finished
@@ -361,7 +363,8 @@ class SfProductionDemandPlan(models.Model):
)
for order in purchase_orders
)
if total_purchase_quantity < record.product_uom_qty:
if float_compare(total_purchase_quantity, record.product_uom_qty,
precision_rounding=record.product_id.uom_id.rounding) == -1:
pr_ids = self.env['purchase.request'].sudo().search(
[('line_ids.product_id', 'in', raw_materials.ids), ('state', '!=', 'done')])
outsourcing_purchase_request.extend(pr_ids.ids)
@@ -378,7 +381,9 @@ class SfProductionDemandPlan(models.Model):
)
for order in purchase_orders
)
if total_purchase_quantity < record.product_uom_qty:
if float_compare(total_purchase_quantity, record.product_uom_qty,
precision_rounding=record.product_id.uom_id.rounding) == -1:
pr_ids = self.env['purchase.request'].sudo().search(
[('origin', 'like', record.sale_order_id.name), ('state', '!=', 'done')])
outsourcing_purchase_request.extend(pr_ids.ids)
@@ -400,7 +405,9 @@ class SfProductionDemandPlan(models.Model):
)
for order in product_purchase_orders
)
if total_outsourcing_purchase_quantity / total_product_qty < record.product_uom_qty:
quantity = total_outsourcing_purchase_quantity / total_product_qty
if float_compare(quantity, record.product_uom_qty,
precision_rounding=record.product_id.uom_id.rounding) == -1:
purchase_request = self.env['purchase.request'].sudo().search(
[('line_ids.product_id', 'in', bom_product_ids.ids),
('line_ids.purchase_state', 'not in', ('purchase', 'done')), ('state', '!=', 'done')])

View File

@@ -377,7 +377,11 @@ class Sf_Dashboard_Connect(http.Controller):
line_list_obj = request.env['sf.production.line'].sudo().search([('name', 'ilike', 'CNC')])
line_list = list(map(lambda x: x.name, line_list_obj))
# print('line_list: %s' % line_list)
res['LineList'] = line_list
res['LineList'] = ['业绩总览']
res['LineList'] += line_list
res['LineList'].append('人工线下加工中心')
# 增加“业绩总览”与“人工线下加工中心”
except Exception as e:
res = {'Succeed': False, 'ErrorCode': 202, 'Error': e}
@@ -401,37 +405,55 @@ class Sf_Dashboard_Connect(http.Controller):
try:
plan_obj = request.env['sf.production.plan'].sudo()
production_obj = request.env['mrp.production'].sudo()
# production_obj = request.env['mrp.production'].sudo()
work_order_obj = request.env['mrp.workorder'].sudo()
line_list = ast.literal_eval(kw['line_list'])
line_list_obj = request.env['sf.production.line'].sudo().search([('name', 'ilike', 'CNC')])
cnc_line_list = list(map(lambda x: x.name, line_list_obj))
# print('line_list: %s' % line_list)
for line in line_list:
if line == '业绩总览':
work_order_domain = [('routing_type', 'in', ['人工线下加工', 'CNC加工'])]
plan_domain = []
elif line == '人工线下加工中心':
work_order_domain = [('routing_type', '=', '人工线下加工')]
plan_domain = [('production_type', '=', '人工线下加工')]
else:
work_order_domain = [
('production_line_id.name', '=', line),
('routing_type', '=', 'CNC加工')
]
plan_domain = [('production_line_id.name', '=', line)]
# # 工单计划量
# plan_data_total_counts = production_obj.search_count(
# [('production_line_id.name', '=', line), ('state', 'not in', ['cancel']),
# ('active', '=', True)])
# 工单计划量切换为CNC工单
plan_data_total_counts = work_order_obj.search_count(
[('production_line_id.name', '=', line), ('id', '!=', 8061),
('state', 'in', ['ready', 'progress', 'done']), ('routing_type', '=', 'CNC加工')])
plan_data_total = work_order_obj.search(work_order_domain + [
('id', '!=', 8061),
('state', 'in', ['ready', 'progress', 'done'])
])
plan_data_total_counts = sum(plan_data_total.mapped('qty_production'))
# # 工单完成量
# plan_data_finish_counts = plan_obj.search_count(
# [('production_line_id.name', '=', line), ('state', 'in', ['finished'])])
# 工单完成量切换为CNC工单
plan_data_finish_counts = work_order_obj.search_count(
[('production_line_id.name', '=', line),
('state', 'in', ['done']), ('routing_type', '=', 'CNC加工')])
plan_data_finish = work_order_obj.search(work_order_domain + [
('state', 'in', ['done'])
])
plan_data_finish_counts = sum(plan_data_finish.mapped('qty_produced'))
# 超期完成量
# 搜索所有已经完成的工单
plan_data_overtime = work_order_obj.search([
('production_line_id.name', '=', line),
('state', 'in', ['done']),
('routing_type', '=', 'CNC加工')
plan_data_overtime = work_order_obj.search(work_order_domain + [
('state', 'in', ['done'])
])
# 使用 filtered 进行字段比较
@@ -440,36 +462,38 @@ class Sf_Dashboard_Connect(http.Controller):
)
# 获取数量
plan_data_overtime_counts = len(plan_data_overtime_counts)
# plan_data_overtime_counts = len(plan_data_overtime_counts)
plan_data_overtime_counts = sum(plan_data_overtime_counts.mapped('qty_produced'))
# 查找符合条件的生产计划记录
plan_data = plan_obj.search([
('production_line_id.name', '=', line),
])
# plan_data = plan_obj.search(plan_domain)
# 过滤出那些检测结果状态为 '返工' 或 '报废' 的记录
# faulty_plans = plan_data.filtered(lambda p: any(
# result.test_results in ['返工', '报废'] for result in p.production_id.detection_result_ids
# ))
faulty_plans = request.env['quality.check'].sudo().search([
('operation_id.name', '=', 'CNC加工'),
('quality_state', 'in', ['fail'])
faulty_plans = work_order_obj.search(work_order_domain + [
('state', 'in', ['scrap', 'rework'])
])
# 查找制造订单取消与归档的数量
cancel_order_count = production_obj.search_count(
[('production_line_id.name', '=', line), ('state', 'in', ['cancel']),
('active', '=', False)])
# cancel_order_count = production_obj.search_count(
# [('production_line_id.name', '=', line), ('state', 'in', ['cancel']),
# ('active', '=', False)])
# 计算符合条件的记录数量
# plan_data_fault_counts = len(faulty_plans) + cancel_order_count
plan_data_fault_counts = len(faulty_plans)
# plan_data_fault_counts = len(faulty_plans)
plan_data_fault_counts = sum(faulty_plans.mapped('qty_produced'))
# 工单返工数量
plan_data_rework_counts = plan_obj.search_count(
[('production_line_id.name', '=', line), ('production_id.state', 'in', ['rework'])])
plan_data_rework = work_order_obj.search(work_order_domain + [
('state', 'in', ['rework'])
])
plan_data_rework_counts = sum(plan_data_rework.mapped('qty_produced'))
# 工单完成率
finishe_rate = round(
@@ -479,8 +503,9 @@ class Sf_Dashboard_Connect(http.Controller):
plan_data_progress_deviation = plan_data_total_counts - plan_data_finish_counts - plan_data_fault_counts
# 完成记录
plan_data_finish_orders = plan_obj.search(
[('production_line_id.name', '=', line), ('state', 'in', ['finished'])])
plan_data_finish_orders = plan_obj.search(plan_domain + [
('state', 'in', ['finished'])
])
# # 检测量
# detection_nums = 0
@@ -534,7 +559,7 @@ class Sf_Dashboard_Connect(http.Controller):
delay_rate = round((delay_num / plan_data_finish_counts if plan_data_finish_counts > 0 else 0), 3)
on_time_rate = 1 - delay_rate
if plan_data:
# if plan_data:
data = {
'plan_data_total_counts': plan_data_total_counts,
'plan_data_finish_counts': plan_data_finish_counts,
@@ -576,8 +601,11 @@ class Sf_Dashboard_Connect(http.Controller):
line_list = ast.literal_eval(kw['line_list'])
begin_time_str = kw['begin_time'].strip('"')
end_time_str = kw['end_time'].strip('"')
begin_time = datetime.strptime(begin_time_str, '%Y-%m-%d %H:%M:%S')
end_time = datetime.strptime(end_time_str, '%Y-%m-%d %H:%M:%S')
# 将时间减去8小时UTC+8转UTC
begin_time = (datetime.strptime(begin_time_str, '%Y-%m-%d %H:%M:%S') - timedelta(hours=8))
end_time = (datetime.strptime(end_time_str, '%Y-%m-%d %H:%M:%S') - timedelta(hours=8))
# begin_time = datetime.strptime(begin_time_str, '%Y-%m-%d %H:%M:%S')
# end_time = datetime.strptime(end_time_str, '%Y-%m-%d %H:%M:%S')
# print('line_list: %s' % line_list)
print('kw', kw)
time_unit = kw.get('time_unit', 'day').strip('"') # 默认单位为天
@@ -609,15 +637,42 @@ class Sf_Dashboard_Connect(http.Controller):
current_date += timedelta(days=1)
return date_list
if time_unit == 'hour':
# 计划量目前只能从mail.message中筛选出
plan_order_messages = request.env['mail.message'].sudo().search([
('model', '=', 'mrp.workorder'),
('create_date', '>=', begin_time.strftime('%Y-%m-%d %H:%M:%S')),
('create_date', '<=', end_time.strftime('%Y-%m-%d %H:%M:%S')),
('tracking_value_ids.field_desc', '=', '状态'),
('tracking_value_ids.new_value_char', '=', '就绪')
])
for line in line_list:
date_field_name = 'date_finished' # 替换为你模型中的实际字段名
order_counts = []
if time_unit == 'hour':
if line == '业绩总览':
work_order_domain = [('routing_type', 'in', ['人工线下加工', 'CNC加工'])]
elif line == '人工线下加工中心':
work_order_domain = [('routing_type', '=', '人工线下加工')]
else:
work_order_domain = [
('production_line_id.name', '=', line),
('routing_type', '=', 'CNC加工')
]
time_intervals = get_time_intervals(begin_time, end_time, time_unit)
print('============================= %s' % time_intervals)
time_count_dict = {}
plan_count_dict = {}
orders = request.env['mrp.workorder'].sudo().search(work_order_domain + [
('state', 'in', ['done']),
(date_field_name, '>=', begin_time.strftime('%Y-%m-%d %H:%M:%S')),
(date_field_name, '<=', end_time.strftime('%Y-%m-%d %H:%M:%S'))
])
for time_interval in time_intervals:
start_time, end_time = time_interval
@@ -629,52 +684,92 @@ class Sf_Dashboard_Connect(http.Controller):
# (date_field_name, '<=', end_time.strftime('%Y-%m-%d %H:%M:%S')) # 包括结束时间
# ])
orders = request.env['mrp.workorder'].sudo().search([
('routing_type', '=', 'CNC加工'), # 将第一个条件合并进来
('production_line_id.name', '=', line),
('state', 'in', ['done']),
(date_field_name, '>=', start_time.strftime('%Y-%m-%d %H:%M:%S')),
(date_field_name, '<=', end_time.strftime('%Y-%m-%d %H:%M:%S'))
])
interval_orders = orders.filtered(
lambda o: o[date_field_name] >= start_time
and o[date_field_name] <= end_time
)
# 使用小时和分钟作为键,确保每个小时的数据有独立的键
key = start_time.strftime('%H:%M:%S') # 只取小时:分钟:秒作为键
time_count_dict[key] = len(orders)
key = (start_time + timedelta(hours=8)).strftime('%H:%M:%S') # 只取小时:分钟:秒作为键
# time_count_dict[key] = len(orders)
time_count_dict[key] = sum(interval_orders.mapped('qty_produced'))
for time_interval in time_intervals:
start_time, end_time = time_interval
# orders = plan_obj.search([
# ('production_line_id.name', '=', line),
# ('state', 'in', ['done']),
# (date_field_name, '>=', start_time.strftime('%Y-%m-%d %H:%M:%S')),
# (date_field_name, '<=', end_time.strftime('%Y-%m-%d %H:%M:%S')) # 包括结束时间
# ])
interval_plan_orders = plan_order_messages.filtered(
lambda o: o.create_date >= start_time
and o.create_date <= end_time
)
interval_order_ids = set(interval_plan_orders.mapped('res_id'))
interval_orders = request.env['mrp.workorder'].sudo().browse(interval_order_ids)
if line == '业绩总览':
interval_orders = interval_orders.filtered(lambda o: o.routing_type in ['人工线下加工', 'CNC加工'])
elif line == '人工线下加工中心':
interval_orders = interval_orders.filtered(lambda o: o.routing_type == '人工线下加工')
else:
interval_orders = interval_orders.filtered(lambda o: o.routing_type == 'CNC加工' and o.production_line_id.name == line)
# 使用小时和分钟作为键,确保每个小时的数据有独立的键
key = (start_time + timedelta(hours=8)).strftime('%H:%M:%S') # 只取小时:分钟:秒作为键
# time_count_dict[key] = len(orders)
plan_count_dict[key] = sum(interval_orders.mapped('qty_production'))
# order_counts.append()
res['data'][line] = {
'finish_order_nums': time_count_dict,
'plan_order_nums': 28
'plan_order_nums': plan_count_dict
}
return json.dumps(res)
else:
for line in line_list:
date_field_name = 'date_finished' # 替换为你模型中的实际字段名
order_counts = []
if line == '业绩总览':
work_order_domain = [('routing_type', 'in', ['人工线下加工', 'CNC加工'])]
elif line == '人工线下加工中心':
work_order_domain = [('routing_type', '=', '人工线下加工')]
else:
work_order_domain = [
('production_line_id.name', '=', line),
('routing_type', '=', 'CNC加工')
]
date_list = get_date_list(begin_time, end_time)
for date in date_list:
next_day = date + timedelta(days=1)
orders = request.env['mrp.workorder'].sudo().search(
[('production_id.production_line_id.name', '=', line), ('state', 'in', ['done']),
('routing_type', '=', 'CNC加工'),
orders = request.env['mrp.workorder'].sudo().search(work_order_domain + [
('state', 'in', ['done']),
(date_field_name, '>=', date.strftime('%Y-%m-%d 00:00:00')),
(date_field_name, '<', next_day.strftime('%Y-%m-%d 00:00:00'))
])
rework_orders = request.env['mrp.workorder'].sudo().search(
[('production_id.production_line_id.name', '=', line), ('state', 'in', ['rework']),
('routing_type', '=', 'CNC加工'),
rework_orders = request.env['mrp.workorder'].sudo().search(work_order_domain + [
('state', 'in', ['rework']),
(date_field_name, '>=', date.strftime('%Y-%m-%d 00:00:00')),
(date_field_name, '<', next_day.strftime('%Y-%m-%d 00:00:00'))
])
not_passed_orders = request.env['mrp.workorder'].sudo().search(
[('production_id.production_line_id.name', '=', line), ('state', 'in', ['scrap', 'cancel']),
('routing_type', '=', 'CNC加工'),
not_passed_orders = request.env['mrp.workorder'].sudo().search(work_order_domain + [
('state', 'in', ['scrap', 'cancel']),
(date_field_name, '>=', date.strftime('%Y-%m-%d 00:00:00')),
(date_field_name, '<', next_day.strftime('%Y-%m-%d 00:00:00'))
])
order_counts.append({
'date': date.strftime('%Y-%m-%d'),
'order_count': len(orders),
'rework_orders': len(rework_orders),
'not_passed_orders': len(not_passed_orders)
'order_count': sum(orders.mapped('qty_produced')),
'rework_orders': sum(rework_orders.mapped('qty_produced')),
'not_passed_orders': sum(not_passed_orders.mapped('qty_produced'))
})
# 外面包一层没什么是包一层不能解决的包一层就能区分了类似于包一层div
# 外面包一层的好处是,可以把多个数据结构打包在一起,方便前端处理
@@ -688,7 +783,7 @@ class Sf_Dashboard_Connect(http.Controller):
@http.route('/api/RealTimeProduct', type='http', auth='public', methods=['GET', 'POST'], csrf=False, cors="*")
def RealTimeProduct(self, **kw):
"""
获取实时产量
获取实时产量(作废)
:param kw:
:return:
"""
@@ -711,6 +806,21 @@ class Sf_Dashboard_Connect(http.Controller):
# 当班计划量
for line in line_list:
if line == '业绩总览':
work_order_domain = [('routing_type', 'in', ['人工线下加工', 'CNC加工'])]
plan_domain = []
elif line == '人工线下加工中心':
work_order_domain = [('routing_type', '=', '人工线下加工')]
plan_domain = [('production_type', '=', '人工线下加工')]
else:
work_order_domain = [
('production_line_id.name', '=', line),
('routing_type', '=', 'CNC加工')
]
plan_domain = [('production_line_id.name', '=', line)]
plan_order_nums = plan_obj.search_count(
[('production_line_id.name', '=', line), ('state', 'not in', ['draft']),
('date_planned_start', '>=', begin_time),
@@ -752,42 +862,72 @@ class Sf_Dashboard_Connect(http.Controller):
:param kw:
:return:
"""
# res = {'status': 1, 'message': '成功', 'not_done_data': [], 'done_data': []}
res = {'status': 1, 'message': '成功', 'data': {}}
# 解决产品名称取到英文的问题
request.update_context(lang='zh_CN')
plan_obj = request.env['sf.production.plan'].sudo()
work_order_obj = request.env['mrp.workorder'].sudo()
# 获取mrp.workorder的state字段的selection内容
state_dict = dict(request.env['mrp.workorder'].sudo()._fields['state'].selection)
line_list = ast.literal_eval(kw['line_list'])
begin_time_str = kw['begin_time'].strip('"')
end_time_str = kw['end_time'].strip('"')
begin_time = datetime.strptime(begin_time_str, '%Y-%m-%d %H:%M:%S')
end_time = datetime.strptime(end_time_str, '%Y-%m-%d %H:%M:%S')
# print('line_list: %s' % line_list)
not_done_data = []
done_data = []
final_data = {}
# 获取当前时间并计算24小时前的时间
current_time = datetime.now()
time_48_hours_ago = current_time - timedelta(hours=48)
# # 计划量目前只能从mail.message中筛选出
# plan_order_messages = request.env['mail.message'].sudo().search([
# ('model', '=', 'mrp.workorder'),
# ('create_date', '>=', time_48_hours_ago.strftime('%Y-%m-%d %H:%M:%S')),
# ('tracking_value_ids.field_desc', '=', '状态'),
# ('tracking_value_ids.new_value_char', 'in', ['就绪', '生产中'])
# ])
for line in line_list:
not_done_data = []
done_data = []
not_done_index = 1
done_index = 1
if line == '业绩总览':
work_order_domain = [('routing_type', 'in', ['人工线下加工', 'CNC加工'])]
elif line == '人工线下加工中心':
work_order_domain = [('routing_type', '=', '人工线下加工')]
else:
work_order_domain = [
('production_line_id.name', '=', line),
('routing_type', '=', 'CNC加工')
]
# 未完成订单
# not_done_orders = plan_obj.search(
# [('production_line_id.name', '=', line), ('state', 'not in', ['finished']),
# ('production_id.state', 'not in', ['cancel', 'done']), ('active', '=', True)
# ])
not_done_orders = request.env['mrp.workorder'].sudo().search(
[('production_line_id.name', '=', line), ('state', 'in', ['ready', 'progress']),
('routing_type', '=', 'CNC加工')
])
not_done_orders = work_order_obj.search(work_order_domain + [
('state', 'in', ['ready', 'progress']),
('date_planned_start', '>=', time_48_hours_ago),
('date_planned_start', '<=', current_time)
], order='id asc'
)
# 完成订单
# 获取当前时间并计算24小时前的时间
current_time = datetime.now()
time_24_hours_ago = current_time - timedelta(hours=24)
# current_time = datetime.now()
# time_24_hours_ago = current_time - timedelta(hours=24)
finish_orders = plan_obj.search([
('production_line_id.name', '=', line), ('state', 'in', ['finished']),
('production_id.state', 'not in', ['cancel']), ('active', '=', True),
('actual_end_time', '>=', time_24_hours_ago)
])
# print(finish_orders)
finish_orders = work_order_obj.search(work_order_domain + [
('state', 'in', ['done']),
('production_id.state', 'not in', ['cancel']),
('date_finished', '>=', time_48_hours_ago)
], order='id asc')
# logging.info('完成订单: %s' % finish_orders)
# 获取所有未完成订单的ID列表
order_ids = [order.id for order in not_done_orders]
@@ -795,14 +935,14 @@ class Sf_Dashboard_Connect(http.Controller):
finish_order_ids = [order.id for order in finish_orders]
# 对ID进行排序
sorted_order_ids = sorted(order_ids)
# sorted_order_ids = sorted(order_ids)
finish_sorted_order_ids = sorted(finish_order_ids)
# finish_sorted_order_ids = sorted(finish_order_ids)
# 创建ID与序号的对应关系
id_to_sequence = {order_id: index + 1 for index, order_id in enumerate(sorted_order_ids)}
# id_to_sequence = {order_id: index + 1 for index, order_id in enumerate(sorted_order_ids)}
finish_id_to_sequence = {order_id: index + 1 for index, order_id in enumerate(finish_sorted_order_ids)}
# finish_id_to_sequence = {order_id: index + 1 for index, order_id in enumerate(finish_sorted_order_ids)}
# # 输出结果或进一步处理
# for order_id, sequence in id_to_sequence.items():
@@ -823,30 +963,21 @@ class Sf_Dashboard_Connect(http.Controller):
material_match = re.search(material_pattern, blank_name)
material = material_match.group(1) if material_match else 'No match found'
state_dict = {
'draft': '待排程',
'done': '已排程',
'processing': '生产中',
'finished': '已完成',
'ready': '待加工',
'progress': '生产中',
}
line_dict = {
'sequence': id_to_sequence[order.id],
'sequence': not_done_index,
'workorder_name': order.production_id.name,
'blank_name': blank_name,
'material': material,
'dimensions': dimensions,
'order_qty': 1,
'order_qty': order.qty_production,
'state': state_dict[order.state],
}
not_done_data.append(line_dict)
not_done_index += 1
for finish_order in finish_orders:
if not finish_order.actual_end_time:
continue
blank_name = ''
try:
blank_name = finish_order.production_id.move_raw_ids[0].product_id.name
@@ -861,17 +992,18 @@ class Sf_Dashboard_Connect(http.Controller):
material = material_match.group(1) if material_match else 'No match found'
line_dict = {
'sequence': finish_id_to_sequence[finish_order.id],
'workorder_name': finish_order.name,
'sequence': done_index,
'workorder_name': finish_order.production_id.name,
'blank_name': blank_name,
'material': material,
'dimensions': dimensions,
'order_qty': finish_order.product_qty,
'finish_time': finish_order.actual_end_time.strftime(
'%Y-%m-%d %H:%M:%S') if finish_order.actual_end_time else ' '
'order_qty': finish_order.qty_produced,
'finish_time': finish_order.date_finished.strftime(
'%Y-%m-%d %H:%M:%S') if finish_order.date_finished else ' '
}
done_data.append(line_dict)
done_index += 1
# 开始包一层
res['data'][line] = {'not_done_data': not_done_data, 'done_data': done_data}

View File

@@ -23,7 +23,6 @@ class sf_technology_design(models.Model):
# def _compute_group_uniq_id(self):
# for record in self:
def json_technology_design_str(self, k, route, i, process_parameter):
workorders_values_str = [0, '', {
'route_id': route.id if route.routing_type in ['表面工艺'] else route.route_workcenter_id.id,
@@ -36,11 +35,19 @@ class sf_technology_design(models.Model):
return workorders_values_str
def write(self, vals):
return super(sf_technology_design, self).write(vals)
res = super(sf_technology_design, self).write(vals)
if 'group_uniq_id' in vals or 'process_parameters_id' in vals or 'active' in vals:
if self.production_id:
process_parameters_id = self.production_id.technology_design_ids.mapped('process_parameters_id')
if process_parameters_id.ids:
self.production_id.product_id.model_process_parameters_ids = process_parameters_id.ids
else:
self.production_id.product_id.model_process_parameters_ids = None
return res
def unlink_technology_design(self):
self.active = False
@api.model_create_multi
def create(self, vals_list):
for vals in vals_list:
@@ -48,10 +55,12 @@ class sf_technology_design(models.Model):
raise ValidationError(_("工序不能为空"))
result = super(sf_technology_design, self).create(vals_list)
for res in result:
record = self.search([('production_id', '=', res.production_id.id), ('active', 'in', [True, False])], order='group_uniq_id desc', limit=1)
res.group_uniq_id=record.group_uniq_id + 1
record = self.search([('production_id', '=', res.production_id.id), ('active', 'in', [True, False])],
order='group_uniq_id desc', limit=1)
res.group_uniq_id = record.group_uniq_id + 1
return result
def get_duplicates_with_inactive(self,technology_designs):
def get_duplicates_with_inactive(self, technology_designs):
# 统计每个 'sequence' 出现的次数
sequence_count = Counter(technology_design.sequence for technology_design in technology_designs)
@@ -62,6 +71,7 @@ class sf_technology_design(models.Model):
]
return result
# def rearrange_numbering(self,self_technology_designs):
# inactive_designs = self.get_duplicates_with_inactive(self_technology_designs)
# if inactive_designs:
@@ -75,7 +85,7 @@ class sf_technology_design(models.Model):
def get_technology_design(self):
return {
'sequence':self.sequence,
'sequence': self.sequence,
'route_id': self.route_id.id,
'process_parameters_id': self.process_parameters_id.id,
'panel': self.panel,
@@ -83,17 +93,19 @@ class sf_technology_design(models.Model):
'time_cycle_manual': self.time_cycle_manual,
'is_auto': self.is_auto,
'active': self.active,
'group_uniq_id':self.group_uniq_id,
'group_uniq_id': self.group_uniq_id,
}
def sync_technology_designs(self,production_technology_designs, self_technology_designs):
def sync_technology_designs(self, production_technology_designs, self_technology_designs):
production_id = production_technology_designs[0].production_id.id
self_technology_design_dict = {item.group_uniq_id:item for item in self_technology_designs}
production_technology_designs_dict = {item.group_uniq_id:item for item in production_technology_designs}
self_technology_design_dict = {item.group_uniq_id: item for item in self_technology_designs}
production_technology_designs_dict = {item.group_uniq_id: item for item in production_technology_designs}
for technology_design in production_technology_designs:
if not self_technology_design_dict.get(technology_design.group_uniq_id):
technology_design.write({'production_id': False})
else:
technology_design.write(self_technology_design_dict.get(technology_design.group_uniq_id).get_technology_design())
technology_design.write(
self_technology_design_dict.get(technology_design.group_uniq_id).get_technology_design())
for technology_design in self_technology_designs:
if not production_technology_designs_dict.get(technology_design.group_uniq_id):
technology_design = technology_design.get_technology_design()
@@ -101,9 +113,8 @@ class sf_technology_design(models.Model):
technology_design.pop('group_uniq_id')
self.env['sf.technology.design'].create(technology_design)
def unified_procedure_multiple_work_orders(self,self_technology_designs,production_item):
def unified_procedure_multiple_work_orders(self, self_technology_designs, production_item):
technology_designs = self.env['sf.technology.design'].sudo().search(
[('production_id', '=', production_item.id), ('active', 'in', [True, False])])
self.sync_technology_designs(self_technology_designs=self_technology_designs,production_technology_designs=technology_designs)
self.sync_technology_designs(self_technology_designs=self_technology_designs,
production_technology_designs=technology_designs)

View File

@@ -42,6 +42,12 @@ class Sf_Mrs_Connect(http.Controller, MultiInheritController):
res = {'status': -2, 'message': '查询到待工艺确认的制造订单'}
return json.JSONEncoder().encode(res)
if productions:
# 修改需求计划中的程序工时
demand_plan = request.env['sf.production.demand.plan'].with_user(
request.env.ref("base.user_admin")).search([('model_id', '=', ret['folder_name'])])
if demand_plan and ret['total_estimated_time']:
demand_plan.write(
{'processing_time': ret['total_estimated_time']})
# 拉取所有加工面的程序文件
for r in ret['processing_panel'].split(','):