Create invoice line cost for shipment from sale line
issue10799 review350741002
This commit is contained in:
1 parent
884a65bfd7
commit
d10aac3893
6 files changed
+67
-28
No files matched your search
@@ -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
@@ -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)
|
||||
@@ -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>
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -170,6 +170,9 @@ Send products::
|
||||
>>> shipment.state
|
||||
'done'
|
||||
|
||||
>>> shipment.cost_invoice_line.amount
|
||||
Decimal('3.00')
|
||||
|
||||
Check customer invoice::
|
||||
|
||||
>>> sale.reload()
|
||||
|
||||
Reference in new issue
Block a user