Create invoice line cost for shipment from sale line

issue10799
review350741002
This commit is contained in:
Cédric Krier committed 2021-10-11 18:47:59 +02:00
1 parent 884a65bfd7
commit d10aac3893
6 files changed
+67 -28

No files matched your search

+2
View File
@@ -2,12 +2,14 @@
# this repository contains the full copyright notices and license terms.
from trytond.pool import Pool
from . import account
from . import sale
from . import stock
def register():
Pool.register(
account.InvoiceLine,
sale.Configuration,
sale.ConfigurationSaleMethod,
sale.Sale,
+12
View File
@@ -0,0 +1,12 @@
# This file is part of Tryton. The COPYRIGHT file at the top level of
# this repository contains the full copyright notices and license terms.
from trytond.model import fields
from trytond.pool import PoolMeta
class InvoiceLine(metaclass=PoolMeta):
__name__ = 'account.invoice.line'
cost_shipments = fields.One2Many(
'stock.shipment.out', 'cost_invoice_line', "Cost of Shipments",
readonly=True)
+3
View File
@@ -6,6 +6,9 @@ this repository contains the full copyright notices and license terms. -->
<record model="ir.message" id="msg_sale_invalid_carrier">
<field name="text">To confirm sale "%(sale)s" you must change the carrier "%(carrier)s".</field>
</record>
<record model="ir.message" id="msg_sale_shipment_cost_unique">
<field name="text">A sale can have only one shipment cost line.</field>
</record>
<record model="ir.message" id="msg_shipment_cost_invoice_missing_account_revenue">
<field name="text">To invoice shipment cost of "%(shipment)s", you must define an account revenue for product "%(product)s".</field>
</record>
+46 -28
View File
@@ -4,7 +4,7 @@ from decimal import Decimal
from trytond import backend
from trytond.i18n import gettext
from trytond.model import ModelView, Workflow, fields
from trytond.model import ModelView, Workflow, Unique, fields
from trytond.transaction import Transaction
from trytond.pyson import Eval, If
from trytond.pool import Pool, PoolMeta
@@ -205,6 +205,12 @@ class Sale(metaclass=PoolMeta):
carrier=sale.carrier.rec_name))
super(Sale, cls).confirm(sales)
@classmethod
@ModelView.button
def process(cls, sales):
with Transaction().set_context(_shipment_cost_invoiced=set()):
super().process(sales)
def _get_carrier_context(self):
return {}
@@ -301,47 +307,59 @@ class Sale(metaclass=PoolMeta):
shipment.carrier = self.carrier
return shipment
def create_invoice(self):
pool = Pool()
InvoiceLine = pool.get('account.invoice.line')
Shipment = pool.get('stock.shipment.out')
invoice = super().create_invoice()
if invoice and self.shipment_cost_method == 'shipment':
invoice_lines = []
# Copy shipments to avoid losing changes as the cache is cleared
# after invoice line save because shipment is a Function field
shipments = list(self.shipments)
for shipment in shipments:
if (shipment.state == 'done'
and shipment.carrier
and not shipment.cost_invoice_line):
invoice_line = shipment.get_cost_invoice_line(invoice)
if not invoice_line:
continue
invoice_line.invoice = invoice
invoice_lines.append(invoice_line)
shipment.cost_invoice_line = invoice_line
InvoiceLine.save(invoice_lines)
Shipment.save(shipments)
return invoice
class Line(metaclass=PoolMeta):
__name__ = 'sale.line'
shipment_cost = fields.Numeric('Shipment Cost', digits=price_digits)
@classmethod
def __setup__(cls):
super().__setup__()
t = cls.__table__()
cls._sql_constraints += [
('sale_shipment_cost_unique',
Unique(t, t.sale, t.shipment_cost),
'sale_shipment_cost.msg_sale_shipment_cost_unique'),
]
def get_invoice_line(self):
context = Transaction().context
shipment_cost_invoiced = context.get('_shipment_cost_invoiced')
lines = super().get_invoice_line()
if (self.sale.shipment_cost_method == 'shipment'
and self.shipment_cost
and shipment_cost_invoiced is not None):
for shipment in self.sale.shipments:
if (shipment.state == 'done'
and shipment.carrier
and not shipment.cost_invoice_line
and shipment.id not in shipment_cost_invoiced):
invoice_line = shipment.get_cost_invoice_line(
self.sale._get_invoice_sale())
if invoice_line:
invoice_line.origin = self
lines.append(invoice_line)
shipment_cost_invoiced.add(shipment.id)
return lines
def _get_invoice_line_quantity(self):
quantity = super()._get_invoice_line_quantity()
if self.shipment_cost:
if self.sale.shipment_cost_method == 'shipment':
return 0
quantity = 0
elif (self.sale.shipment_cost_method == 'order'
and self.sale.invoice_method == 'shipment'):
shipments = self.sale.shipments
if (not shipments
or all(s.state != 'done' for s in shipments)):
return 0
quantity = 0
return quantity
def _get_invoiced_quantity(self):
quantity = super()._get_invoiced_quantity()
if self.shipment_cost:
if self.sale.shipment_cost_method == 'shipment':
quantity = 0
return quantity
+1
View File
@@ -152,6 +152,7 @@ class ShipmentOut(metaclass=PoolMeta):
invoice_line.unit_price = round_price(cost)
invoice_line.product = product
invoice_line.on_change_product()
invoice_line.cost_shipments = [self]
if not invoice_line.account:
raise InvoiceShipmentCostError(
+3
View File
@@ -170,6 +170,9 @@ Send products::
>>> shipment.state
'done'
>>> shipment.cost_invoice_line.amount
Decimal('3.00')
Check customer invoice::
>>> sale.reload()