# -*- coding: utf-8 -*- from collections import Counter from xml import etree from odoo import models, fields, api, Command from odoo.exceptions import UserError, AccessError from odoo.http import request class jikimo_bom(models.Model): _name = 'jikimo.bom' _description = '功能刀具物料清单' tool_inventory_id = fields.Many2one('sf.tool.inventory', '功能刀具清单') tool_name = fields.Char(related="tool_inventory_id.name", string='功能刀具名称') functional_cutting_tool_model_id = fields.Many2one(related='tool_inventory_id.functional_cutting_tool_model_id', string='功能刀具类型') tool_groups_id = fields.Many2one(related='tool_inventory_id.tool_groups_id', string='刀具组') tool_length = fields.Float(related='tool_inventory_id.tool_length', string='刀具总长(mm)') diameter = fields.Float(related='tool_inventory_id.diameter', string='直径(mm)') angle = fields.Float(related='tool_inventory_id.angle', string='R角(mm)') extension = fields.Float(related='tool_inventory_id.extension', string='伸出长度(mm)') product_ids = fields.Many2many('product.product', string='产品') knife_handle_model = fields.Selection(related='tool_inventory_id.knife_handle_model', string='使用刀柄型号') options = fields.Char('产品清单') def name_get(self): result = [] for bom in self: result.append((bom.id, '功能刀具物料清单')) return result def check_types_in_list(self): # 统计每个元素的类型 type_counts = Counter(item.cutting_tool_material_id.name for item in self.product_ids) return all(count > 0 for count in type_counts.values()) and len(type_counts) == self.options.split('+') def write(self, vals): # 在更新模型时记录旧的 Many2many ID 列表 if 'product_ids' in vals: old_product_counter = Counter(self.product_ids.ids) super(jikimo_bom, self).write(vals) new_product_counter = Counter(self.product_ids.ids) delete_product_counter = old_product_counter - new_product_counter if delete_product_counter: # 删除操作 if self.check_types_in_list(): return True else: raise UserError('每种物料最少要有一个') return super(jikimo_bom, self).write(vals) def bom_product_domains(self, assembly_options): self.options = assembly_options cutting_tool_materials = self.env['sf.cutting.tool.material'].search( [('name', 'in', assembly_options.split('+'))]) domains = [] for index, option in enumerate(cutting_tool_materials): domain = ['&', ('cutting_tool_material_id', '=', option.id), ("cutting_tool_type_id", "in", self.tool_inventory_id.functional_cutting_tool_model_id.cutting_tool_type_ids.ids)] if option.name == '刀柄': domain = ['&'] + domain + [ ("cutting_tool_taper_shank_model", "=", self.tool_inventory_id.knife_handle_model)] if option.name == '整体式刀具': domain = ['&'] + domain + [ '|', # 刀具直径 ('cutting_tool_blade_diameter', '=', self.tool_inventory_id.diameter), # r角 ('cutting_tool_blade_tip_working_size', '=', self.tool_inventory_id.angle)] if option.name == '刀杆': domain = ['&'] + domain + [ ("cutting_tool_cutter_arbor_diameter", "=", self.tool_inventory_id.diameter)] if option.name == '刀片': domain = ['&'] + domain + [ ("cutting_tool_blade_tip_circular_arc_radius", "=", self.tool_inventory_id.angle)] if option.name == '刀盘': domain = ['&'] + domain + [ ("cutting_tool_cutter_head_diameter", "=", self.tool_inventory_id.diameter)] domains = domains + domain if index != 0: domains = ['|'] + domains # wqwqwe = self.env['product.product'].search(ddd) # product = self.env['product.product'].search(domain) # if product: # products = products + product domains = domains + [('stock_move_count', '>', 0)] return domains def generate_bill_materials(self, assembly_options): domains = self.bom_product_domains(assembly_options) products = self.env['product.product'].search(domains) if products: self.product_ids = [Command.set(products.ids)] # if option.name == '刀盘': # hilt = self.env['product.product'].search( # [('cutting_tool_blade_diameter', '=', self.tool_inventory_id.diameter), # ('cutting_tool_material_id', '=', option.id)]) # self.product_ids = [Command.set(hilt.ids)]k class jikimo_bom_line(models.Model): _name = 'jikimo.bom.line' _description = 'jikimo.bom.line' name = fields.Char() class ProductProduct(models.Model): _inherit = 'product.product' _order = 'cutting_tool_material_id, cutting_tool_type_id' stock_move_count = fields.Integer(string='stock_move count', compute='_compute_stock_move_count', store=True) @api.depends('stock_move_ids') def _compute_stock_move_count(self): for record in self: if record.stock_move_ids: record.stock_move_count = len(record.stock_move_ids) else: record.stock_move_count = 0 def search(self, args, offset=0, limit=None, order=None, count=False): # 你可以在这里修改 `args` 以调整搜索条件 # 例如,添加额外的搜索条件 if self.env.context.get('jikimo_bom_product'): bom_id = self.env['jikimo.bom'].browse(request.session.get('jikimo_bom_product').get('bom_id')) if not bom_id.options: raise UserError('请先选择组装方式') domains = bom_id.bom_product_domains(bom_id.options) args = args + domains return super(ProductProduct, self).search(args, offset=offset, limit=limit, order=order, count=count)