1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146
|
# 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 ModelSQL, fields
from trytond.pool import Pool, PoolMeta
from trytond.pyson import Eval, If
from trytond.transaction import Transaction
class Invoice(metaclass=PoolMeta):
__name__ = 'account.invoice'
shipments = fields.Function(fields.Char("Shipments"), 'get_shipments')
def get_shipments(self, name):
shipments = {
m.shipment.rec_name for l in self.lines
for m in l.stock_moves if m.shipment}
return ', '.join(sorted(shipments))
@classmethod
def _post(cls, invoices):
pool = Pool()
Move = pool.get('stock.move')
transaction = Transaction()
context = transaction.context
super()._post(invoices)
moves = sum((l.stock_moves for i in invoices for l in i.lines), ())
if moves:
with transaction.set_context(
queue_batch=context.get('queue_batch', True)):
Move.__queue__.update_unit_price(moves)
class InvoiceLineStockMove(ModelSQL):
'Invoice Line - Stock Move'
__name__ = 'account.invoice.line-stock.move'
invoice_line = fields.Many2One(
'account.invoice.line', "Invoice Line",
required=True, ondelete='CASCADE')
stock_move = fields.Many2One(
'stock.move', "Stock Move", required=True, ondelete='CASCADE')
class InvoiceLine(metaclass=PoolMeta):
__name__ = 'account.invoice.line'
warehouse = fields.Function(fields.Many2One(
'stock.location', "Warehouse"), 'get_warehouse')
stock_moves = fields.Many2Many(
'account.invoice.line-stock.move', 'invoice_line', 'stock_move',
"Stock Moves",
domain=[
('product.default_uom_category',
'=', Eval('product_uom_category', -1)),
If((Eval('_parent_invoice', {}).get('type') == 'out')
| (Eval('invoice_type') == 'out'),
['OR',
('to_location.type', '=', 'customer'),
('from_location.type', '=', 'customer'),
],
['OR',
('from_location.type', '=', 'supplier'),
('to_location.type', '=', 'supplier'),
]),
],
states={
'invisible': (
(Eval('type') != 'line')
| ~Eval('product')),
})
shipments = fields.Function(fields.Char("Shipments"), 'get_shipments')
correction = fields.Boolean(
"Correction",
states={
'invisible': ((Eval('_parent_invoice', {}).get('type') == 'out')
| (Eval('invoice_type') == 'out')),
},
help="Check to correct price of already posted invoice.")
@classmethod
def __setup__(cls):
super().__setup__()
cls._check_modify_exclude.update(['stock_moves', 'correction'])
@classmethod
def default_correction(cls):
return False
def get_warehouse(self, name):
if (self.invoice_type == 'out'
or (self.invoice and self.invoice.type) == 'out'):
warehouses = set(filter(None, [
m.from_location.warehouse for m in self.stock_moves]))
else:
warehouses = set(filter(None, [
m.to_location.warehouse for m in self.stock_moves]))
if warehouses:
return list(warehouses)[0].id
@property
def moved_quantity(self):
'The quantity from linked stock moves in line unit'
pool = Pool()
Uom = pool.get('product.uom')
quantity = 0
for stock_move in self.stock_moves:
if stock_move.state != 'cancelled':
quantity += Uom.compute_qty(
stock_move.unit, stock_move.quantity, self.unit)
return quantity
def get_shipments(self, name):
shipments = {
m.shipment.rec_name for m in self.stock_moves if m.shipment}
return ', '.join(sorted(shipments))
@classmethod
def write(cls, *args):
pool = Pool()
Move = pool.get('stock.move')
transaction = Transaction()
context = transaction.context
super().write(*args)
lines = sum(args[0:None:2], [])
moves = sum((l.stock_moves for l in lines), ())
if moves:
with transaction.set_context(
queue_batch=context.get('queue_batch', True)):
Move.__queue__.update_unit_price(moves)
@classmethod
def copy(cls, lines, default=None):
if default is None:
default = {}
else:
default = default.copy()
default.setdefault('correction', False)
if not Transaction().context.get('_account_invoice_correction'):
default.setdefault('stock_moves', None)
return super(InvoiceLine, cls).copy(lines, default=default)
def _credit(self):
line = super()._credit()
line.stock_moves = self.stock_moves
return line
|