bemade-addons/commercial_invoice/models/commercial_invoice.py

159 lines
5.6 KiB
Python

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,
)
# 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.ref("base.USD")
)
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", "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")
# 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,
)
@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"
)
return super().create(vals_list)
@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
)
def action_confirm(self):
self.write({"state": "done"})
def action_draft(self):
self.write({"state": "draft"})
def action_cancel(self):
self.write({"state": "cancelled"})
@api.onchange("partner_id")
def _onchange_partner_id(self):
if self.partner_id:
self.payment_term_id = self.partner_id.property_payment_term_id
@api.model
def _prepare_commercial_invoice_from_invoices(self, invoices):
"""Prepare commercial invoice values from a set of invoices."""
if not invoices:
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")
# Validate consistency
if len(currencies) > 1:
raise UserError(_("Selected invoices have different currencies."))
if len(companies) > 1:
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")
# 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,
}
return vals
@api.model
def create_from_invoices(self, invoices):
"""Create a commercial invoice from a set of invoices."""
vals = self._prepare_commercial_invoice_from_invoices(invoices)
return self.create(vals)