diff --git a/sf_bf_connect/models/http.py b/sf_bf_connect/models/http.py index 8b10aa21..e70d5e79 100644 --- a/sf_bf_connect/models/http.py +++ b/sf_bf_connect/models/http.py @@ -36,7 +36,7 @@ class Http(models.AbstractModel): post_time = int(datas['HTTP_TIMESTAMP']) datetime_post = datetime.fromtimestamp(post_time) datetime_now = datetime.now().replace(microsecond=0) - datetime_del = datetime_now + timedelta(seconds=5) + datetime_del = datetime_now + timedelta(seconds=30) if datetime_post > datetime_del: raise AuthenticationError('请求已过期') check_str = '%s%s%s' % (datas['HTTP_TOKEN'], post_time, factory_secret.sf_secret_key) diff --git a/sf_manufacturing/models/mrp_production.py b/sf_manufacturing/models/mrp_production.py index ff2fde3a..c4eb21dc 100644 --- a/sf_manufacturing/models/mrp_production.py +++ b/sf_manufacturing/models/mrp_production.py @@ -6,7 +6,9 @@ import os import re import requests from itertools import groupby -from odoo import api, fields, models, _ +from datetime import datetime +from collections import defaultdict, namedtuple +from odoo import api, fields, models, SUPERUSER_ID, _ from odoo.exceptions import UserError, ValidationError from odoo.addons.sf_base.commons.common import Common from odoo.tools import float_compare, float_round, float_is_zero, format_datetime @@ -77,9 +79,10 @@ class MrpProduction(models.Model): ('pending_cam', '待加工'), ('progress', '加工中'), ('rework', '返工'), + ('scrap', '报废'), ('to_close', 'To Close'), ('done', 'Done'), - ('cancel', '报废')], string='State', + ('cancel', '已取消')], string='State', compute='_compute_state', copy=False, index=True, readonly=True, store=True, tracking=True, help=" * Draft: The MO is not confirmed yet.\n" @@ -122,6 +125,7 @@ class MrpProduction(models.Model): manual_quotation = fields.Boolean('人工编程', default=False, readonly=True) is_scrap = fields.Boolean('是否报废', default=False) + is_remanufacture = fields.Boolean('是否重新制造', default=False) @api.depends( 'move_raw_ids.state', 'move_raw_ids.quantity_done', 'move_finished_ids.state', 'tool_state', @@ -166,7 +170,7 @@ class MrpProduction(models.Model): production.state = 'pending_cam' if production.state == 'progress': - if all(wo_state not in ('progress', 'done', 'rework') for wo_state in + if all(wo_state not in ('progress', 'done', 'rework', 'scrap') for wo_state in production.workorder_ids.mapped('state')): production.state = 'pending_cam' if production.is_rework is True: @@ -184,9 +188,14 @@ class MrpProduction(models.Model): for wo in production.workorder_ids): production.state = 'rework' + if any(wo.test_results == '报废' and wo.state == 'done' for wo in production.workorder_ids): + production.state = 'scrap' + if any(dr.test_results == '报废' and dr.handle_result == '已处理' for dr in + production.detection_result_ids): + production.state = 'cancel' # 如果制造订单的功能刀具为【无效刀】则制造订单状态改为返工 - # if production.tool_state == '2': - # production.state = 'rework' + if production.tool_state == '2': + production.state = 'rework' def action_check(self): """ @@ -788,6 +797,22 @@ class MrpProduction(models.Model): }) return action + # 返工 + def button_scrap_new(self): + cloud_programming = self._cron_get_programming_state() + return { + 'name': _('报废'), + 'type': 'ir.actions.act_window', + 'view_mode': 'form', + 'res_model': 'sf.production.wizard', + 'target': 'new', + 'context': { + 'default_production_id': self.id, + 'default_programming_state': cloud_programming['programming_state'], + 'default_is_reprogramming': True if cloud_programming['programming_state'] in ['已下发'] else False + } + } + # 返工 def button_rework(self): cloud_programming = None @@ -912,44 +937,117 @@ class MrpProduction(models.Model): logging.info('get_new_program error:%s' % e) raise UserError("从云平台获取最新程序失败,请联系管理员") - def recreateManufacturing(self): + def recreateManufacturing(self, item): """ 重新生成制造订单 """ if self.is_scrap is True: - sale_order = self.env['sale.order'].sudo().search([('name', '=', productions.origin)]) - values = self.env['mrp.production'].create_production1_values(self.production_id) - productions = self.env['mrp.production'].with_user(SUPERUSER_ID).sudo().with_company( - self.production_id.company_id).create( - values) - # self.env['stock.move'].sudo().create(productions._get_moves_raw_values()) - self.env['stock.move'].sudo().create(productions._get_moves_finished_values()) - productions._create_workorder() - productions.filtered(lambda p: (not p.orderpoint_id and p.move_raw_ids) or \ - ( - p.move_dest_ids.procure_method != 'make_to_order' and - not p.move_raw_ids and not p.workorder_ids)).action_confirm() - for production_item in productions: - process_parameter_workorder = self.env['mrp.workorder'].search( - [('surface_technics_parameters_id', '!=', False), ('production_id', '=', production_item.id), - ('is_subcontract', '=', True)]) - if process_parameter_workorder: - is_pick = False - consecutive_workorders = [] - m = 0 - sorted_workorders = sorted(process_parameter_workorder, key=lambda w: w.id) - for i in range(len(sorted_workorders) - 1): - if m == 0: - is_pick = False - if sorted_workorders[i].supplier_id.id == sorted_workorders[i + 1].supplier_id.id and \ - sorted_workorders[i].is_subcontract == sorted_workorders[i + 1].is_subcontract and \ - sorted_workorders[i].id == sorted_workorders[i + 1].id - 1: - if sorted_workorders[i] not in consecutive_workorders: - consecutive_workorders.append(sorted_workorders[i]) - consecutive_workorders.append(sorted_workorders[i + 1]) - m += 1 - continue - else: + procurement_requests = [] + sale_order = self.env['sale.order'].sudo().search([('name', '=', self.origin)]) + values = self.env['mrp.production'].create_production1_values(self) + # productions = self.env['mrp.production'].with_user(SUPERUSER_ID).sudo().with_company( + # self.company_id).create( + # values) + # 查询出库移动记录 + out_picking = self.env['stock.picking'].search( + [('origin', '=', sale_order.name), ('name', 'ilike', 'WH/OUT/')]) + move = out_picking.move_ids.filtered(lambda pd: pd.product_id == self.product_id) + move_values = {'product_description_variants': '', + 'date_planned': datetime.now(), + 'date_deadline': datetime.now(), + # 'move_dest_ids': self.env['stock.move'].search([('id', '=', move.id)]), + 'move_dest_ids': move, + 'group_id': False, + 'route_ids': [], + 'warehouse_id': self.warehouse_id, + 'priority': 0, + 'orderpoint_id': False, + 'product_packaging_id': False} + rule = self.env['stock.rule'].search( + [('action', '=', 'pull'), ('procure_method', '=', 'mts_else_mto'), ( + 'location_dest_id', '=', self.env['stock.location'].search([('parent_path', '=', '2/5/')]).id), + ('location_src_id', '=', self.env['stock.location'].search( + [('barcode', '=', 'CP')]).id)]) + origin = move._prepare_procurement_origin() + procurement_requests.append(self.env['procurement.group'].Procurement( + move.product_id, 1.0, move.product_uom, + self.env['stock.location'].search([('barcode', '=', 'CP')]), + rule and rule.name or "/", + origin, move.company_id, move_values)) + self.env['procurement.group'].run(procurement_requests, + raise_user_error=not self.env.context.get('from_orderpoint')) + # self.env['stock.move'].sudo().create(productions._get_moves_finished_values()) + # productions.filtered(lambda p: (not p.orderpoint_id and p.move_raw_ids) or \ + # ( + # p.move_dest_ids.procure_method != 'make_to_order' and + # not p.move_raw_ids and not p.workorder_ids)).action_confirm() + productions = self.env['mrp.production'].sudo().search( + [('origin', '=', self.origin)], order='id desc', limit=1) + move = self.env['stock.move'].search([('origin', '=', productions.name)], order='id desc') + for mo in move: + print(mo.id) + if mo.name in ['/', '拉']: + if mo.name == '/': + domain = [('barcode', '=', 'WH-PC'), ('sequence_code', '=', 'PC')] + elif mo.name == '拉': + domain = [('barcode', '=', 'WH-INTERNAL'), ('sequence_code', '=', 'INT')] + picking_type = self.env['stock.picking.type'].search(domain) + mo.picking_type_id = picking_type.id + mo._assign_picking() + mo.reference = mo.picking_id.name + productions.write({'programming_no': self.programming_no, 'is_remanufacture': True}) + productions.procurement_group_id.mrp_production_ids.move_dest_ids.write( + {'group_id': self.env['procurement.group'].search([('name', '=', sale_order.name)])}) + scarp_process_parameter_workorder = self.env['mrp.workorder'].search( + [('surface_technics_parameters_id', '!=', False), ('production_id', '=', self.id), + ('is_subcontract', '=', True)]) + if scarp_process_parameter_workorder: + production_programming = self.env['mrp.production'].search( + [('programming_no', '=', self.programming_no)], order='name asc') + production_list = [production.name for production in production_programming] + purchase_orders = self.env['purchase.order'].search([('origin', '=', ','.join(production_list))]) + for purchase_item in purchase_orders.order_line: + for process_item in scarp_process_parameter_workorder: + if purchase_item.product_id.categ_type == '表面工艺': + if purchase_item.product_id.server_product_process_parameters_id == process_item.surface_technics_parameters_id: + print(purchase_orders.find(productions.name)) + if purchase_orders.find(productions.name) == -1: + purchase_orders.origin += productions.name + if item['is_reprogramming'] is False: + productions._create_workorder(item) + productions.programming_state = '已编程' + for production_item in productions: + process_parameter_workorder = self.env['mrp.workorder'].search( + [('surface_technics_parameters_id', '!=', False), ('production_id', '=', production_item.id), + ('is_subcontract', '=', True)]) + if process_parameter_workorder: + is_pick = False + consecutive_workorders = [] + m = 0 + sorted_workorders = sorted(process_parameter_workorder, key=lambda w: w.id) + for i in range(len(sorted_workorders) - 1): + if m == 0: + is_pick = False + if sorted_workorders[i].supplier_id.id == sorted_workorders[i + 1].supplier_id.id and \ + sorted_workorders[i].is_subcontract == sorted_workorders[i + 1].is_subcontract and \ + sorted_workorders[i].id == sorted_workorders[i + 1].id - 1: + if sorted_workorders[i] not in consecutive_workorders: + consecutive_workorders.append(sorted_workorders[i]) + consecutive_workorders.append(sorted_workorders[i + 1]) + m += 1 + continue + else: + if m == len(consecutive_workorders) - 1 and m != 0: + self.env['stock.picking'].create_outcontract_picking(consecutive_workorders, + production_item) + if sorted_workorders[i] in consecutive_workorders: + is_pick = True + consecutive_workorders = [] + m = 0 + # 当前面的连续工序生成对应的外协出入库单再生成当前工序的外协出入库单 + if is_pick is False: + self.env['stock.picking'].create_outcontract_picking(sorted_workorders[i], + production_item) if m == len(consecutive_workorders) - 1 and m != 0: self.env['stock.picking'].create_outcontract_picking(consecutive_workorders, production_item) @@ -957,25 +1055,17 @@ class MrpProduction(models.Model): is_pick = True consecutive_workorders = [] m = 0 - # 当前面的连续工序生成对应的外协出入库单再生成当前工序的外协出入库单 - if is_pick is False: - self.env['stock.picking'].create_outcontract_picking(sorted_workorders[i], - production_item) if m == len(consecutive_workorders) - 1 and m != 0: self.env['stock.picking'].create_outcontract_picking(consecutive_workorders, production_item) - if sorted_workorders[i] in consecutive_workorders: - is_pick = True - consecutive_workorders = [] - m = 0 - if m == len(consecutive_workorders) - 1 and m != 0: - self.env['stock.picking'].create_outcontract_picking(consecutive_workorders, production_item) - if is_pick is False and m == 0: - if len(sorted_workorders) == 1: - self.env['stock.picking'].create_outcontract_picking(sorted_workorders, production_item) - else: - self.env['stock.picking'].create_outcontract_picking(sorted_workorders[i], production_item) - + if is_pick is False and m == 0: + if len(sorted_workorders) == 1: + self.env['stock.picking'].create_outcontract_picking(sorted_workorders, production_item) + else: + self.env['stock.picking'].create_outcontract_picking(sorted_workorders[i], + production_item) + else: + productions.programming_state = '编程中' for production in productions: origin_production = production.move_dest_ids and production.move_dest_ids[ 0].raw_material_production_id or False @@ -1005,9 +1095,8 @@ class MrpProduction(models.Model): workorder_duration += workorder.duration_expected if sale_order: - sale_order.mrp_production_ids |= productions - # sale_order.write({'schedule_status': 'to schedule'}) - self.env['sf.production.plan'].sudo().with_company(self.production_id.company_id).create({ + # sale_order.mrp_production_ids |= productions + self.env['sf.production.plan'].sudo().with_company(self.company_id).create({ 'name': productions.name, 'order_deadline': sale_order.deadline_of_delivery, 'production_id': productions.id, @@ -1017,11 +1106,13 @@ class MrpProduction(models.Model): 'product_id': productions.product_id.id, 'state': 'draft', }) + return productions # 在之前的销售单上重新生成制造订单 - def create_production1_values(self, production, sale_order): + def create_production1_values(self, production): production_values_str = {'origin': production.origin, 'product_id': production.product_id.id, + 'programming_state': '已编程', 'product_description_variants': production.product_description_variants, 'product_qty': production.product_qty, 'product_uom_id': production.product_uom_id.id, @@ -1031,7 +1122,8 @@ class MrpProduction(models.Model): 'date_deadline': production.date_deadline, 'date_planned_start': production.date_planned_start, 'date_planned_finished': production.date_planned_finished, - 'procurement_group_id': sale_order.id, + # 'procurement_group_id': self.env["procurement.group"].create( + # {'name': production.name}).id, 'propagate_cancel': production.propagate_cancel, 'orderpoint_id': production.orderpoint_id.id, 'picking_type_id': production.picking_type_id.id, diff --git a/sf_manufacturing/models/mrp_workorder.py b/sf_manufacturing/models/mrp_workorder.py index 1b4cc642..479a56bc 100644 --- a/sf_manufacturing/models/mrp_workorder.py +++ b/sf_manufacturing/models/mrp_workorder.py @@ -934,7 +934,7 @@ class ResMrpWorkOrder(models.Model): workorder.state = 'waiting' elif workorder.routing_type == '解除装夹' and workorder.state not in ['done', 'rework', 'cancel']: if cnc_workorder: - if not cnc_workorder_pending: + if not cnc_workorder_pending or unclamp_workorder.test_results == '报废': workorder.state = 'waiting' # else: # if workorder.production_id.is_rework is True: @@ -1173,7 +1173,8 @@ class ResMrpWorkOrder(models.Model): 'detailed_reason': record.detailed_reason, 'processing_panel': record.processing_panel, 'routing_type': record.routing_type, - 'handle_result': '待处理' if record.test_results == '返工' or record.is_rework is True else '', + 'handle_result': '待处理' if record.test_results in ['返工', + '报废'] or record.is_rework is True else '', 'test_results': record.test_results, 'test_report': record.detection_report})], 'is_scrap': True if record.test_results == '报废' else False}) diff --git a/sf_manufacturing/models/stock.py b/sf_manufacturing/models/stock.py index ca080f11..db07ab91 100644 --- a/sf_manufacturing/models/stock.py +++ b/sf_manufacturing/models/stock.py @@ -68,6 +68,7 @@ class StockRule(models.Model): @api.model def _run_pull(self, procurements): + logging.info(procurements) moves_values_by_company = defaultdict(list) mtso_products_by_locations = defaultdict(list) @@ -176,7 +177,9 @@ class StockRule(models.Model): for company_id, moves_values in moves_values_by_company.items(): # create the move as SUPERUSER because the current user may not have the rights to do it (mto product # launched by a sale for example) + logging.info(moves_values) moves = self.env['stock.move'].with_user(SUPERUSER_ID).sudo().with_company(company_id).create(moves_values) + logging.info(moves) # Since action_confirm launch following procurement_group we should activate it. moves._action_confirm() diff --git a/sf_manufacturing/views/mrp_production_addional_change.xml b/sf_manufacturing/views/mrp_production_addional_change.xml index a39a3d07..b1c1ff1e 100644 --- a/sf_manufacturing/views/mrp_production_addional_change.xml +++ b/sf_manufacturing/views/mrp_production_addional_change.xml @@ -7,10 +7,10 @@ mrp.production - - - - + + + + @@ -70,7 +70,7 @@ - confirmed,pending_cam,progress,done + confirmed,pending_cam,progress,rework,scrap,done @@ -128,9 +128,9 @@ attrs="{'invisible': ['|',('state', '!=', 'rework'),('programming_state', '!=', '已编程未下发')]}"/>