from trytond.pool import Pool, PoolMeta from trytond.model.exceptions import AccessError from trytond.i18n import gettext from trytond.model import ModelView from decimal import Decimal from itertools import groupby __all__ = ['Account','Move','Line'] class Account(metaclass=PoolMeta): __name__ = 'account.account' @classmethod def __setup__(cls): super(Account, cls).__setup__() cls.party_required.domain = [()] cls.party_required.states = {} class Move(metaclass=PoolMeta): __name__ = 'account.move' @classmethod def create(cls, vlist): pool = Pool() Sequence = pool.get('ir.sequence') Journal = pool.get('account.journal') Account_Configuration = pool.get('account.configuration') configuration = Account_Configuration(1) draft_default = configuration.default_draft_sequence vlist = [x.copy() for x in vlist] for vals in vlist: if not vals.get('number'): journal_id = (vals.get('journal') or Transaction().context.get('journal')) if journal_id: journal = Journal(journal_id) if journal.sequence: vals['number'] = Sequence.get_id(draft_default.id) moves = super(Move, cls).create(vlist) cls.validate_move(moves) return moves @classmethod @ModelView.button def post(cls, moves): pool = Pool() Date = pool.get('ir.date') Line = pool.get('account.move.line') Sequence = pool.get('ir.sequence') for move in moves: amount = Decimal('0.0') if not move.lines: raise PostError( gettext('account.msg_post_empty_move', move=move.rec_name)) company = None for line in move.lines: amount += line.debit - line.credit if not company: company = line.account.company if not company.currency.is_zero(amount): raise PostError( gettext('account.msg_post_unbalanced_move', move=move.rec_name)) for move in moves: move.state = 'posted' move.number = Sequence.get_id(move.journal.sequence.id) if not move.post_number: move.post_date = Date.today() move.post_number = Sequence.get_id( move.period.post_move_sequence_used.id) def keyfunc(l): return l.party, l.account to_reconcile = [l for l in move.lines if ((l.debit == l.credit == Decimal('0')) and l.account.reconcile)] to_reconcile = sorted(to_reconcile, key=keyfunc) for _, zero_lines in groupby(to_reconcile, keyfunc): Line.reconcile(list(zero_lines)) cls.save(moves) class Line(metaclass=PoolMeta): __name__ = 'account.move.line' @classmethod def __setup__(cls): super(Line, cls).__setup__() cls.party.states = {} def check_account(self): if not self.account.type or self.account.closed: raise AccessError( gettext('account.msg_line_closed_account', account=self.account.rec_name)) if self.account.party_required: if bool(self.party) != bool(self.account.party_required): error = 'party_set' if self.party else 'party_required' raise AccessError( gettext('account.msg_line_%s' % error, account=self.account.rec_name, line=self.rec_name))