File: account.py

package info (click to toggle)
tryton-modules-account-invoice-stock 7.0.2-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 380 kB
  • sloc: python: 443; xml: 48; makefile: 11; sh: 3
file content (146 lines) | stat: -rw-r--r-- 5,163 bytes parent folder | download
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