Odoo15选择Job Card自动加载产品行到发票行报错排查
Odoo15 工卡明细同步发票行报错修复方案
问题原因
代码存在6类核心错误,直接触发运行异常:
- 主从表关联字段定义完全错误:Job Card主模型中,除
x_job_card_ids外其余关联明细的One2many字段,第二个参数(子表外键字段)错填为quantity/price等普通数值字段,x_product_ids错定义为Many2many类型且关联参数错误,根本无法读取到工卡下的产品明细数据。 - 字段名拼写错误:生成发票行值的方法中,单价字段名
price_unit前多了前置空格,写成' price_unit',Odoo无法识别字段直接抛出字段不存在的异常。 - 字段引用不匹配:Job Card Line明细模型中定义的单价字段名为
price,代码中错写为price_unit;产品字段关联的是product.template模型,而发票行产品字段要求关联product.product模型,类型不匹配触发约束报错。 - 方法写法不规范:Onchange方法中调用
update方法赋值One2many字段不符合Odoo规范,且未做空值判断,清空工卡字段时会触发空记录集调用方法的报错。 - 发票行必填字段缺失:创建发票行时仅传入数量、单价两个字段,缺少
product_id/name/tax_ids等必填字段,即使字段名正确也会触发必填校验报错。 - 精度问题:Job Card Line的
total字段定义为Integer整数类型,单价为Float浮点数,相乘后会丢失小数精度。
修正后代码
1. 修正Job Card主模型
删除原有错误的明细关联字段,替换为正确的One2many定义,同时修正发票行值生成方法:
class JobCard(models.Model): _name = "job.card" _inherit = ['mail.thread', 'mail.activity.mixin'] _description = "Job Card Master" _rec_name = 'job_card_number' job_card_number = fields.Char(string='Job Card No.', readonly=True) customer_id = fields.Many2one('res.partner', string="Customer Name", tracking=True) vehicle_id = fields.Many2one('res.partner.line', string="Vehicle", tracking=True, domain="[('x_customer_id','=',customer_id)]") date_time_of_invoice = fields.Datetime(string='Date & Time of Invoice', tracking=True, default=fields.Datetime.now) start_date_time = fields.Datetime(string='Start Date & Time', tracking=True) end_date_time = fields.Datetime(string='End Date & Time', tracking=True) priority = fields.Selection([ ('0', 'Normal'), ('1', 'Low'), ('2', 'High'), ('3', 'Very High')], string="Priority") state = fields.Selection([ ('draft', 'Draft'), ('in_progress', 'In Progress'), ('done', 'Done'), ('cancel', 'Cancelled')], string="Status", default='draft', required=True) active = fields.Boolean(string="Active", default=True, tracking=True) # 正确的明细行One2many关联:第二个参数为子表指向主表的外键字段名job_card_id job_card_line_ids = fields.One2many('job.card.line', 'job_card_id', string="Job Card Details") job_card_count = fields.Integer(compute='compute_job_card_count', string='Job Card Count') def get_invoice_line_vals(self): vals_list = [] for line in self.job_card_line_ids: vals_list.append({ # 关联product.product模型记录,取产品模板下的第一个可销售变体 'product_id': line.product_id.product_variant_id.id, # 修正字段名,去掉前置空格,取明细行的price字段作为单价 'price_unit': line.price, 'quantity': line.quantity, # 补全发票行必填的名称字段 'name': line.product_id.display_name, # 补全税费字段,自动带产品默认税费 'tax_ids': [(6, 0, line.product_id.taxes_id.ids)] }) return vals_list
2. 修正Job Card Line明细模型
调整金额字段类型避免精度丢失:
class JobCardLine(models.Model): _name = "job.card.line" job_card_id = fields.Many2one('job.card', string="Job Card Id", tracking=True) product_id = fields.Many2one('product.template', string="Product", tracking=True) quantity = fields.Integer(string="Quantity", tracking=True) price = fields.Float(string="Price") # 改为Float类型避免小数精度丢失 total = fields.Float(string='Total', compute='_compute_total', tracking=True, help="This field will be calculated from quantity and price !") employee_id = fields.Many2one('hr.employee', string="Employee", tracking=True) x_job_card_id = fields.Many2one('res.partner', string="Vehicle Details") @api.onchange('product_id') def _on_change_product_id(self): self.price = self.product_id.list_price @api.depends('quantity', 'price') def _compute_total(self): for rec in self: rec.total = rec.quantity * rec.price
3. 修正发票模型的Onchange方法
规范赋值逻辑,增加空值判断:
class CustomInvoice(models.Model): _inherit = "account.move" job_card_id = fields.Many2one('job.card', string="Job Card", domain="[('customer_id','=',partner_id)]", tracking=True) @api.onchange('job_card_id') def _onchange_job_card_id(self): # 先清空原有发票明细 self.invoice_line_ids = [(5, 0, 0)] # 未选择工卡时直接返回,避免空对象报错 if not self.job_card_id: return # 生成发票明细值并赋值 invoice_lines_vals = self.job_card_id.get_invoice_line_vals() self.invoice_line_ids = [(0, 0, vals) for vals in invoice_lines_vals] # 可选:自动带工卡关联的客户到发票 self.partner_id = self.job_card_id.customer_id
升级模块后重启Odoo服务,功能即可正常运行。
内容的提问来源于stack exchange,提问作者mr.robot
相关产品推荐
相关产品推荐

