# 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.pool import PoolMeta from trytond.model import fields, Workflow, ModelView from trytond.pyson import Eval, Bool from trytond.i18n import gettext from trytond.model.exceptions import AccessError from trytond.pool import Pool class Invoice(metaclass=PoolMeta): __name__ = 'account.invoice' position = fields.Char('Position', states={'invisible': Eval('type') != 'out'}) turn = fields.Integer('Turn', states={'invisible': Eval('type') != 'out'}) @classmethod def __setup__(cls): super(Invoice, cls).__setup__() cls.party.states['readonly'] = Bool(Eval('number')) if 'turn' not in cls._check_modify_exclude: cls._check_modify_exclude.add('turn') @classmethod @ModelView.button @Workflow.transition('cancelled') def cancel(cls, invoices): pool = Pool() Move = pool.get('account.move') Line = pool.get('account.move.line') cancel_moves = [] delete_moves = [] to_save = [] for invoice in invoices: if invoice.move: if invoice.move.state == 'draft': delete_moves.append(invoice.move) elif not invoice.cancel_move: if (invoice.type == 'out' and not invoice.company.cancel_invoice_out): raise AccessError( gettext('account_invoice.msg_invoice_customer_cancel_move', invoice=invoice.rec_name)) invoice.cancel_move = invoice.move.cancel() to_save.append(invoice) cancel_moves.append(invoice.cancel_move) if cancel_moves: Move.save(cancel_moves) cls.save(to_save) if delete_moves: Move.delete(delete_moves) if cancel_moves: Move.post(cancel_moves) # Write state before reconcile to prevent invoice to go to paid state cls.write(invoices, { 'state': 'cancelled', }) for invoice in invoices: if not invoice.move or not invoice.cancel_move: continue to_reconcile = [] for line in invoice.move.lines + invoice.cancel_move.lines: if line.account == invoice.account: to_reconcile.append(line) Line.reconcile(to_reconcile) cls._clean_payments(invoices)