import logging import json import re from odoo import models, fields, api, _ from odoo.exceptions import UserError _logger = logging.getLogger(__name__) class SaleOrder(models.Model): _inherit = 'sale.order' state = fields.Selection([ ('draft', "报价"), ('sent', "报价已发送"), ('supply method', "供货方式待确认"), ('sale', "销售订单"), ('processing', "加工中"), ('physical_distribution', "物流中"), ('delivered', "已交付"), ('done', "已锁定"), ('cancel', "已取消"), ]) def confirm_to_supply_method(self): self.state = 'supply method' for line in self.order_line: if line.product_id.auto_machining: line.supply_method = 'automation' def action_confirm(self): if self._get_forbidden_state_confirm() & set(self.mapped('state')): raise UserError(_('订单状态已发生变化,请刷新当前页面')) # 判断是否所有产品都选择了供货方式 filter_line = self.order_line.filtered(lambda line: not line.supply_method) if filter_line: raise UserError('当前订单内(%s)产品未选择路线,请选择后重试' % ','.join(filter_line.mapped('product_id.name'))) for line in self.order_line: bom_type = '' # 根据供货方式修改成品模板 if line.supply_method == 'automation': bom_type = 'normal' product_template_id = self.env.ref('sf_dlm.product_template_sf').sudo().product_tmpl_id elif line.supply_method == 'outsourcing': bom_type = 'subcontract' product_template_id = self.env.ref( 'jikimo_sale_multiple_supply_methods.product_template_outsourcing').sudo() elif line.supply_method == 'purchase': product_template_id = self.env.ref( 'jikimo_sale_multiple_supply_methods.product_template_purchase').sudo() elif line.supply_method == 'manual': bom_type = 'normal' product_template_id = self.env.ref( 'jikimo_sale_multiple_supply_methods.product_template_manual_processing').sudo() # 复制成品模板上的属性 line.product_id.product_tmpl_id.copy_template(product_template_id) # 将模板上的single_manufacturing属性复制到成品上 line.product_id.single_manufacturing = product_template_id.single_manufacturing order_id = self product = line.product_id # 拼接方法需要的item结构,成品的模型数据信息就是坯料的数据信息 item = { 'texture_code': product.materials_id.materials_no, 'texture_type_code': product.materials_type_id.materials_no, 'model_long': product.length, 'model_width': product.width, 'model_height': product.height, 'blank_volume': product.model_volume, 'blank_area': product.model_area, 'price': product.list_price, 'embryo_redundancy_id': line.embryo_redundancy_id, } product_name = '' match = re.search(r'(S\d{5}-\d)', product.name) # 如果匹配成功,提取结果 if match: product_name = match.group(0) # 获取成品名结尾-n的n product_seria = int(product_name.split('-')[-1]) # 成品供货方式为采购则不生成bom if line.supply_method != 'purchase': bom_data = self.env['mrp.bom'].with_user(self.env.ref("base.user_admin")).get_bom(product) _logger.info('bom_data:%s' % bom_data) if bom_data: bom = self.env['mrp.bom'].with_user(self.env.ref("base.user_admin")).bom_create(product, 'normal', False) bom.with_user(self.env.ref("base.user_admin")).bom_create_line_has(bom_data) else: # 当成品上带有客供料选项时,生成坯料时选择“客供料”路线 if line.embryo_redundancy_id: # 将成品模板的内容复制到成品上 customer_provided_embryo = self.env.ref( 'jikimo_sale_multiple_supply_methods.product_template_embryo_customer_provided').sudo() # 创建坯料,客供料的批量不需要创建bom material_customer_provided_embryo = self.env['product.template'].sudo().no_bom_product_create( customer_provided_embryo.with_context(active_test=False).product_variant_id, item, order_id, 'material_customer_provided', product_seria, product) # 成品配置bom product_bom_material_customer_provided = self.env['mrp.bom'].with_user( self.env.ref("base.user_admin")).bom_create( product, bom_type, 'product') product_bom_material_customer_provided.with_user( self.env.ref("base.user_admin")).bom_create_line_has( material_customer_provided_embryo) elif line.product_id.materials_type_id.gain_way == '自加工': self_machining_id = self.env.ref('sf_dlm.product_embryo_sf_self_machining').sudo() # 创建坯料 self_machining_embryo = self.env['product.template'].sudo().no_bom_product_create( self_machining_id, item, order_id, 'self_machining', product_seria, product) # 创建坯料的bom self_machining_bom = self.env['mrp.bom'].with_user( self.env.ref("base.user_admin")).bom_create( self_machining_embryo, 'normal', False) # 创建坯料里bom的组件 self_machining_bom_line = self_machining_bom.with_user( self.env.ref("base.user_admin")).bom_create_line( self_machining_embryo) if not self_machining_bom_line: raise UserError('该订单模型的材料型号暂未有原材料,请先配置再进行分配') # 产品配置bom product_bom_self_machining = self.env['mrp.bom'].with_user( self.env.ref("base.user_admin")).bom_create( product, bom_type, 'product') product_bom_self_machining.with_user(self.env.ref("base.user_admin")).bom_create_line_has( self_machining_embryo) elif line.product_id.materials_type_id.gain_way == '外协': outsource_id = self.env.ref('sf_dlm.product_embryo_sf_outsource').sudo() # 创建坯料 outsource_embryo = self.env['product.template'].sudo().no_bom_product_create(outsource_id, item, order_id, 'subcontract', product_seria, product) if outsource_embryo == -3: raise UserError('该订单模型的材料型号暂未设置获取方式和供应商,请先配置再进行分配') # 创建坯料的bom outsource_bom = self.env['mrp.bom'].with_user(self.env.ref("base.user_admin")).bom_create( outsource_embryo, 'subcontract', True) # 创建坯料的bom的组件 outsource_bom_line = outsource_bom.with_user( self.env.ref("base.user_admin")).bom_create_line(outsource_embryo) if not outsource_bom_line: raise UserError('该订单模型的材料型号暂未有原材料,请先配置再进行分配') # 产品配置bom product_bom_outsource = self.env['mrp.bom'].with_user( self.env.ref("base.user_admin")).bom_create(product, bom_type, 'product') product_bom_outsource.with_user(self.env.ref("base.user_admin")).bom_create_line_has( outsource_embryo) elif line.product_id.materials_type_id.gain_way == '采购': purchase_id = self.env.ref('sf_dlm.product_embryo_sf_purchase').sudo() purchase_embryo = self.env['product.template'].sudo().no_bom_product_create(purchase_id, item, order_id, 'purchase', product_seria, product) if purchase_embryo and purchase_embryo == -3: raise UserError('该订单模型的材料型号暂未设置获取方式和供应商,请先配置再进行分配') else: # 产品配置bom product_bom_purchase = self.env['mrp.bom'].with_user( self.env.ref("base.user_admin")).bom_create(product, bom_type, 'product') product_bom_purchase.with_user(self.env.ref("base.user_admin")).bom_create_line_has( purchase_embryo) return super(SaleOrder, self).action_confirm() def action_show_cancel_wizard(self): wizard = self.env['sf.sale.order.cancel.wizard'].create({ 'order_id': self.id, }) # 创建关联单据行 self.env['sf.sale.order.cancel.line'].create_from_order(wizard.id, self) return { 'name': '取消销售订单', 'type': 'ir.actions.act_window', 'res_model': 'sf.sale.order.cancel.wizard', 'view_mode': 'form', 'target': 'new', 'res_id': wizard.id, } class SaleOrderLine(models.Model): _inherit = 'sale.order.line' part_number = fields.Char('零件图号', related='product_id.part_number', readonly=True) # 供货方式 supply_method = fields.Selection([ ('automation', "自动化产线加工"), ('manual', "人工线下加工"), ('purchase', "外购"), ('outsourcing', "委外加工"), ], string='供货方式') def write(self, vals): if 'supply_method' in vals: for line in self: if vals['supply_method'] == 'automation' and line.manual_quotation: raise UserError('当前(%s)产品为人工编程产品,不能选择自动化产线加工' % ','.join(line.mapped('product_id.name'))) if vals['supply_method'] == 'purchase' and line.is_incoming_material: raise UserError('当前(%s)产品为客供料,不能选择外购' % ','.join(line.mapped('product_id.name'))) return super(SaleOrderLine, self).write(vals) cancel_auto_machining = fields.Boolean('是否取消自动化加工', compute='_compute_cancel_auto_machining', store=True) cancel_auto_machining_reason = fields.Char('更改供货原因') @api.depends('product_id', 'supply_method') def _compute_cancel_auto_machining(self): for line in self: line.cancel_auto_machining = True if line.product_id.auto_machining \ and line.supply_method != 'automation' else False