diff --git a/sf_demand_plan/models/sf_production_demand_plan.py b/sf_demand_plan/models/sf_production_demand_plan.py index 12214bff..49cbe926 100644 --- a/sf_demand_plan/models/sf_production_demand_plan.py +++ b/sf_demand_plan/models/sf_production_demand_plan.py @@ -196,11 +196,14 @@ class SfProductionDemandPlan(models.Model): else: line.model_long = None - @api.depends('product_id.model_long', 'product_id.model_width', 'product_id.model_height') + @api.depends('product_id.model_long', 'product_id.model_width', 'product_id.model_height', 'product_id.blank_type') def _compute_embryo_long(self): for line in self: if line.product_id: - line.embryo_long = f"{round(line.product_id.model_long, 3)}*{round(line.product_id.model_width, 3)}*{round(line.product_id.model_height, 3)}" + if line.product_id.blank_type == '圆料': + line.embryo_long = f"Ø{round(line.product_id.model_width, 3)}*{round(line.product_id.model_long, 3)}" + else: + line.embryo_long = f"{round(line.product_id.model_long, 3)}*{round(line.product_id.model_width, 3)}*{round(line.product_id.model_height, 3)}" else: line.embryo_long = None @@ -403,29 +406,30 @@ class SfProductionDemandPlan(models.Model): outsourcing_purchase_request.extend(pr_ids.ids) if record.supply_method == 'outsourcing' and not record.sale_order_line_id.is_incoming_material: bom_line_ids = record.product_id.bom_ids.bom_line_ids - # BOM_数量 - total_product_qty = sum(line.product_qty for line in bom_line_ids) - bom_product_ids = bom_line_ids.mapped('product_id') - product_purchase_orders = self.env['purchase.order'].sudo().search([ - ('state', 'in', ('purchase', 'done')), - ('order_line.product_id', 'in', bom_product_ids.ids) - ]) - # 购订单_数量 - total_outsourcing_purchase_quantity = sum( - sum( - order.order_line.filtered( - lambda line: line.product_id in bom_product_ids - ).mapped('product_qty') + if bom_line_ids: + # BOM_数量 + total_product_qty = sum(line.product_qty for line in bom_line_ids) + bom_product_ids = bom_line_ids.mapped('product_id') + product_purchase_orders = self.env['purchase.order'].sudo().search([ + ('state', 'in', ('purchase', 'done')), + ('order_line.product_id', 'in', bom_product_ids.ids) + ]) + # 购订单_数量 + total_outsourcing_purchase_quantity = sum( + sum( + order.order_line.filtered( + lambda line: line.product_id in bom_product_ids + ).mapped('product_qty') + ) + for order in product_purchase_orders ) - for order in product_purchase_orders - ) - 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')]) - outsourcing_purchase_request.extend(purchase_request.ids) + 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')]) + outsourcing_purchase_request.extend(purchase_request.ids) record.outsourcing_purchase_request = json.dumps(outsourcing_purchase_request) if outsourcing_purchase_request: record.hide_action_purchase_orders = True diff --git a/sf_demand_plan/views/demand_plan.xml b/sf_demand_plan/views/demand_plan.xml index 24a2707e..5b9c425a 100644 --- a/sf_demand_plan/views/demand_plan.xml +++ b/sf_demand_plan/views/demand_plan.xml @@ -28,7 +28,7 @@ - + diff --git a/sf_machine_connect/controllers/controllers.py b/sf_machine_connect/controllers/controllers.py index 4974127e..de4a8a33 100644 --- a/sf_machine_connect/controllers/controllers.py +++ b/sf_machine_connect/controllers/controllers.py @@ -601,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('"') # 默认单位为天 @@ -636,6 +639,15 @@ class Sf_Dashboard_Connect(http.Controller): 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' # 替换为你模型中的实际字段名 @@ -678,19 +690,10 @@ class Sf_Dashboard_Connect(http.Controller): ) # 使用小时和分钟作为键,确保每个小时的数据有独立的键 - key = start_time.strftime('%H:%M:%S') # 只取小时:分钟:秒作为键 + 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')) - # 计划量,目前只能从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 time_interval in time_intervals: start_time, end_time = time_interval @@ -715,7 +718,7 @@ class Sf_Dashboard_Connect(http.Controller): interval_orders = interval_orders.filtered(lambda o: o.routing_type == 'CNC加工' and o.production_line_id.name == line) # 使用小时和分钟作为键,确保每个小时的数据有独立的键 - key = start_time.strftime('%H:%M:%S') # 只取小时:分钟:秒作为键 + 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')) @@ -859,6 +862,8 @@ class Sf_Dashboard_Connect(http.Controller): """ # 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() line_list = ast.literal_eval(kw['line_list']) @@ -867,13 +872,25 @@ class Sf_Dashboard_Connect(http.Controller): 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 = {} - not_done_index = 1 - done_index = 1 + + # 获取当前时间,并计算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加工'])] @@ -889,21 +906,29 @@ class Sf_Dashboard_Connect(http.Controller): # [('production_line_id.name', '=', line), ('state', 'not in', ['finished']), # ('production_id.state', 'not in', ['cancel', 'done']), ('active', '=', True) # ]) - not_done_orders = work_order_obj.search(work_order_domain + - [('state', 'in', ['ready', 'progress'])], order='id asc' - ) + # not_done_orders = work_order_obj.search(work_order_domain + + # [('state', 'in', ['ready', 'progress'])], order='id asc' + # ) + not_done_orders = request.env['mrp.workorder'].sudo().browse(plan_order_messages.mapped('res_id')) + if line == '业绩总览': + not_done_orders = not_done_orders.filtered(lambda o: o.routing_type in ['人工线下加工', 'CNC加工']) + elif line == '人工线下加工中心': + not_done_orders = not_done_orders.filtered(lambda o: o.routing_type == '人工线下加工') + else: + not_done_orders = not_done_orders.filtered(lambda o: o.routing_type == 'CNC加工' and o.production_line_id.name == line) + # 完成订单 # 获取当前时间,并计算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 = work_order_obj.search(work_order_domain + [ - ('state', 'in', ['finished']), + ('state', 'in', ['done']), ('production_id.state', 'not in', ['cancel']), - ('date_finished', '>=', time_24_hours_ago) + ('date_finished', '>=', time_48_hours_ago) ], order='id asc') - # print(finish_orders) + # logging.info('完成订单: %s' % finish_orders) # 获取所有未完成订单的ID列表 order_ids = [order.id for order in not_done_orders] @@ -962,8 +987,6 @@ class Sf_Dashboard_Connect(http.Controller): 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 @@ -984,8 +1007,8 @@ class Sf_Dashboard_Connect(http.Controller): 'material': material, 'dimensions': dimensions, 'order_qty': order.qty_produced, - 'finish_time': finish_order.actual_end_time.strftime( - '%Y-%m-%d %H:%M:%S') if finish_order.actual_end_time else ' ' + 'finish_time': finish_order.date_finished.strftime( + '%Y-%m-%d %H:%M:%S') if finish_order.date_finished else ' ' } done_data.append(line_dict) diff --git a/sf_manufacturing/models/__init__.py b/sf_manufacturing/models/__init__.py index 8af783e7..c8af2d82 100644 --- a/sf_manufacturing/models/__init__.py +++ b/sf_manufacturing/models/__init__.py @@ -18,4 +18,5 @@ from . import quick_easy_order from . import purchase_order from . import quality_check from . import purchase_request_line +from . import bom # from . import stock_warehouse_orderpoint \ No newline at end of file diff --git a/sf_manufacturing/models/bom.py b/sf_manufacturing/models/bom.py new file mode 100644 index 00000000..d0a35300 --- /dev/null +++ b/sf_manufacturing/models/bom.py @@ -0,0 +1,16 @@ +from odoo import models +from odoo.osv.expression import AND + + +class MrpBom(models.Model): + _inherit = 'mrp.bom' + + def _bom_subcontract_find(self, product, picking_type=None, company_id=False, bom_type='subcontract', subcontractor=False): + domain = self._bom_find_domain(product, picking_type=picking_type, company_id=company_id, bom_type=bom_type) + if self.env.context.get('stock_picking') == 'outsourcing': + return self.search(domain, order='sequence, product_id, id', limit=1) + if subcontractor: + domain = AND([domain, [('subcontractor_ids', 'parent_of', subcontractor.ids)]]) + return self.search(domain, order='sequence, product_id, id', limit=1) + else: + return self.env['mrp.bom'] diff --git a/sf_manufacturing/models/stock.py b/sf_manufacturing/models/stock.py index 7dbe1706..4e8dc438 100644 --- a/sf_manufacturing/models/stock.py +++ b/sf_manufacturing/models/stock.py @@ -1205,6 +1205,20 @@ class ReStockMove(models.Model): res['lot_id'] = self.subcontract_workorder_id.production_id.move_raw_ids.move_line_ids[0].lot_id.id return res + def _get_subcontract_bom(self): + self.ensure_one() + purchase_type = getattr(self.picking_id.purchase_id, 'purchase_type', False) + if purchase_type: + self = self.with_context(stock_picking=purchase_type) + bom = self.env['mrp.bom'].sudo()._bom_subcontract_find( + self.product_id, + picking_type=self.picking_type_id, + company_id=self.company_id.id, + bom_type='subcontract', + subcontractor=self.picking_id.partner_id + ) + return bom + class ReStockQuant(models.Model): _inherit = 'stock.quant'