From d9cc020e7f1df6875944e75fa0e6638e1272d502 Mon Sep 17 00:00:00 2001 From: Marc Durepos Date: Fri, 21 Mar 2025 11:41:36 -0400 Subject: [PATCH] allow commercial invoice on vendor refunds --- .../models/commercial_invoice.py | 157 +++++++++++------- 1 file changed, 101 insertions(+), 56 deletions(-) diff --git a/commercial_invoice/models/commercial_invoice.py b/commercial_invoice/models/commercial_invoice.py index dd58ee2..f9316f3 100644 --- a/commercial_invoice/models/commercial_invoice.py +++ b/commercial_invoice/models/commercial_invoice.py @@ -1,73 +1,112 @@ from odoo import api, fields, models, _ from odoo.exceptions import UserError -class CommercialInvoice(models.Model): - _name = 'commercial.invoice' - _description = 'Commercial Invoice for Export' - _inherit = ['mail.thread', 'mail.activity.mixin'] - _order = 'date desc, id desc' - name = fields.Char(string='Reference', required=True, copy=False, readonly=True, default='New') - date = fields.Date(string='Export Date', required=True, default=fields.Date.context_today) - state = fields.Selection([ - ('draft', 'Draft'), - ('done', 'Done'), - ('cancelled', 'Cancelled') - ], string='Status', default='draft', tracking=True) +class CommercialInvoice(models.Model): + _name = "commercial.invoice" + _description = "Commercial Invoice for Export" + _inherit = ["mail.thread", "mail.activity.mixin"] + _order = "date desc, id desc" + + name = fields.Char( + string="Reference", required=True, copy=False, readonly=True, default="New" + ) + date = fields.Date( + string="Export Date", required=True, default=fields.Date.context_today + ) + state = fields.Selection( + [("draft", "Draft"), ("done", "Done"), ("cancelled", "Cancelled")], + string="Status", + default="draft", + tracking=True, + ) # Related parties - partner_id = fields.Many2one('res.partner', string='Consignee', required=True) - importer_id = fields.Many2one('res.partner', string='Importer of Record') - customs_broker_id = fields.Many2one('res.partner', string='Customs Broker') - company_id = fields.Many2one('res.company', string='Company', required=True, default=lambda self: self.env.company) - currency_id = fields.Many2one('res.currency', string='Currency', required=True, - default=lambda self: self.env.company.currency_id) - related_parties = fields.Boolean(string='Related Parties', default=False) - + partner_id = fields.Many2one("res.partner", string="Consignee", required=True) + importer_id = fields.Many2one("res.partner", string="Importer of Record") + customs_broker_id = fields.Many2one("res.partner", string="Customs Broker") + company_id = fields.Many2one( + "res.company", + string="Company", + required=True, + default=lambda self: self.env.company, + ) + currency_id = fields.Many2one( + "res.currency", + string="Currency", + required=True, + default=lambda self: self.env.company.currency_id, + ) + related_parties = fields.Boolean(string="Related Parties", default=False) # Invoice lines and related fields - invoice_ids = fields.Many2many('account.move', string='Invoices', domain=[('move_type', '=', 'out_invoice')]) - payment_term_id = fields.Many2one('account.payment.term', string='Payment Terms') - incoterm_id = fields.Many2one('account.incoterms', string='Incoterms') + invoice_ids = fields.Many2many( + "account.move", + string="Invoices", + domain=[("move_type", "in", ["out_invoice", "in_refund"])], + ) + payment_term_id = fields.Many2one("account.payment.term", string="Payment Terms") + incoterm_id = fields.Many2one("account.incoterms", string="Incoterms") # Shipping details - number_of_packages = fields.Integer(string='Number of Packages') - total_weight = fields.Float(string='Total Weight (kg)') - packaging_cost = fields.Monetary(string='Packaging Cost', currency_field='currency_id') - freight_cost = fields.Monetary(string='Freight Cost', currency_field='currency_id') - insurance_cost = fields.Monetary(string='Insurance Cost', currency_field='currency_id') - other_cost = fields.Monetary(string='Other Costs', currency_field='currency_id') + number_of_packages = fields.Integer(string="Number of Packages") + total_weight = fields.Float(string="Total Weight (kg)") + packaging_cost = fields.Monetary( + string="Packaging Cost", currency_field="currency_id" + ) + freight_cost = fields.Monetary(string="Freight Cost", currency_field="currency_id") + insurance_cost = fields.Monetary( + string="Insurance Cost", currency_field="currency_id" + ) + other_cost = fields.Monetary(string="Other Costs", currency_field="currency_id") # Computed fields - invoice_amount = fields.Monetary(string='Invoice Amount', currency_field='currency_id', - compute='_compute_amounts', store=True) - total_amount = fields.Monetary(string='Total Amount', currency_field='currency_id', - compute='_compute_amounts', store=True) + invoice_amount = fields.Monetary( + string="Invoice Amount", + currency_field="currency_id", + compute="_compute_amounts", + store=True, + ) + total_amount = fields.Monetary( + string="Total Amount", + currency_field="currency_id", + compute="_compute_amounts", + store=True, + ) @api.model_create_multi def create(self, vals_list): for vals in vals_list: - if vals.get('name', 'New') == 'New': - vals['name'] = self.env['ir.sequence'].next_by_code('commercial.invoice') or 'New' + if vals.get("name", "New") == "New": + vals["name"] = ( + self.env["ir.sequence"].next_by_code("commercial.invoice") or "New" + ) return super().create(vals_list) - @api.depends('invoice_ids', 'packaging_cost', 'freight_cost', 'insurance_cost', 'other_cost') + @api.depends( + "invoice_ids", "packaging_cost", "freight_cost", "insurance_cost", "other_cost" + ) def _compute_amounts(self): for record in self: - record.invoice_amount = sum(record.invoice_ids.mapped('amount_total')) - record.total_amount = (record.invoice_amount + record.packaging_cost + - record.freight_cost + record.insurance_cost + record.other_cost) + record.invoice_amount = sum(record.invoice_ids.mapped("amount_total")) + record.total_amount = ( + record.invoice_amount + + record.packaging_cost + + record.freight_cost + + record.insurance_cost + + record.other_cost + ) def action_confirm(self): - self.write({'state': 'done'}) + self.write({"state": "done"}) def action_draft(self): - self.write({'state': 'draft'}) + self.write({"state": "draft"}) def action_cancel(self): - self.write({'state': 'cancelled'}) + self.write({"state": "cancelled"}) - @api.onchange('partner_id') + @api.onchange("partner_id") def _onchange_partner_id(self): if self.partner_id: self.payment_term_id = self.partner_id.property_payment_term_id @@ -79,10 +118,10 @@ class CommercialInvoice(models.Model): raise UserError(_("No invoices selected.")) # Get unique values for key fields - currencies = invoices.mapped('currency_id') - payment_terms = invoices.mapped('invoice_payment_term_id') - incoterms = invoices.mapped('invoice_incoterm_id') - companies = invoices.mapped('company_id') + currencies = invoices.mapped("currency_id") + payment_terms = invoices.mapped("invoice_payment_term_id") + incoterms = invoices.mapped("invoice_incoterm_id") + companies = invoices.mapped("company_id") # Validate consistency if len(currencies) > 1: @@ -91,18 +130,24 @@ class CommercialInvoice(models.Model): raise UserError(_("Selected invoices are from different companies.")) # Get shipping and billing partners - shipping_partners = invoices.mapped('partner_shipping_id.commercial_partner_id') - billing_partners = invoices.mapped('partner_id.commercial_partner_id') + shipping_partners = invoices.mapped("partner_shipping_id.commercial_partner_id") + billing_partners = invoices.mapped("partner_id.commercial_partner_id") # Prepare values vals = { - 'invoice_ids': [(6, 0, invoices.ids)], - 'company_id': companies[0].id, - 'currency_id': currencies[0].id, - 'partner_id': shipping_partners[0].id if len(shipping_partners) == 1 else False, - 'importer_id': billing_partners[0].id if len(billing_partners) == 1 else False, - 'payment_term_id': payment_terms[0].id if len(payment_terms) == 1 else False, - 'incoterm_id': incoterms[0].id if len(incoterms) == 1 else False, + "invoice_ids": [(6, 0, invoices.ids)], + "company_id": companies[0].id, + "currency_id": currencies[0].id, + "partner_id": ( + shipping_partners[0].id if len(shipping_partners) == 1 else False + ), + "importer_id": ( + billing_partners[0].id if len(billing_partners) == 1 else False + ), + "payment_term_id": ( + payment_terms[0].id if len(payment_terms) == 1 else False + ), + "incoterm_id": incoterms[0].id if len(incoterms) == 1 else False, } return vals