# 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 decimal import Decimal from sql.conditionals import Coalesce from sql.aggregate import Sum from collections import OrderedDict from trytond.model import ModelView, ModelSQL, fields from trytond.wizard import Wizard, StateView, Button, StateReport from trytond.transaction import Transaction from trytond.report import Report from trytond.pyson import Eval, PYSONEncoder from trytond.pool import Pool, PoolMeta class PrintTrialBalanceDetailedStart(ModelView): 'Print Trial Balance Detailed' __name__ = 'account_co_reports.print_trial_balance_detailed.start' fiscalyear = fields.Many2One('account.fiscalyear', 'Fiscal Year', required=True, depends=['start_period', 'end_period']) start_period = fields.Many2One('account.period', 'Start Period', domain=[ ('fiscalyear', '=', Eval('fiscalyear')), ('start_date', '<=', (Eval('end_period'), 'start_date')) ], depends=['end_period', 'fiscalyear']) end_period = fields.Many2One('account.period', 'End Period', domain=[ ('fiscalyear', '=', Eval('fiscalyear')), ('start_date', '>=', (Eval('start_period'), 'start_date')) ], depends=['start_period', 'fiscalyear']) party = fields.Many2One('party.party', 'Party') accounts = fields.Many2Many('account.account', None, None, 'Accounts', domain=[ ('type', '!=', ''), ]) company = fields.Many2One('company.company', 'Company', required=True) posted = fields.Boolean('Posted Move', help='Show only posted move') by_reference = fields.Boolean('By Reference', help='Show all moves by reference ignoring the parties') empty_account = fields.Boolean('Empty Account', help='With account without move') @staticmethod def default_fiscalyear(): FiscalYear = Pool().get('account.fiscalyear') return FiscalYear.find( Transaction().context.get('company'), exception=False) @staticmethod def default_company(): return Transaction().context.get('company') @staticmethod def default_posted(): return False @staticmethod def default_by_reference(): return False @staticmethod def default_empty_account(): return False @fields.depends('fiscalyear') def on_change_fiscalyear(self): self.start_period = None self.end_period = None class PrintTrialBalanceDetailed(Wizard): 'Print Trial Balance Detailed' __name__ = 'account_co_reports.print_trial_balance_detailed' start = StateView('account_co_reports.print_trial_balance_detailed.start', 'account_co_reports.print_trial_balance_detailed_start_view_form', [ Button('Cancel', 'end', 'tryton-cancel'), Button('Print', 'print_', 'tryton-print', default=True), ]) print_ = StateReport('account_co_reports.trial_balance_detailed') def do_print_(self, action): start_period = None end_period = None party_id = None accounts_ids = [] if self.start.start_period: start_period = self.start.start_period.id if self.start.end_period: end_period = self.start.end_period.id if self.start.party: party_id = self.start.party.id if self.start.accounts: accounts_ids = [acc.id for acc in self.start.accounts] data = { 'company': self.start.company.id, 'fiscalyear': self.start.fiscalyear.id, 'start_period': start_period, 'end_period': end_period, 'party': party_id, 'accounts': accounts_ids, 'posted': self.start.posted, 'empty_account': self.start.empty_account, 'by_reference': self.start.by_reference, } return action, data def transition_print_(self): return 'end' class TrialBalanceDetailed(Report): __name__ = 'account_co_reports.trial_balance_detailed' @classmethod def get_context(cls, records, header, data): report_context = super(TrialBalanceDetailed, cls).get_context(records, header, data) pool = Pool() Account = pool.get('account.account') Move = pool.get('account.move') Line = pool.get('account.move.line') Period = pool.get('account.period') Company = pool.get('company.company') Party = pool.get('party.party') FiscalYear = pool.get('account.fiscalyear') cursor = Transaction().connection.cursor() move = Move.__table__() line = Line.__table__() start_period_name = None end_period_name = None # ----- Set Periods ----- start_periods = [] if data['start_period']: start_period = Period(data['start_period']) start_periods = Period.search([ ('fiscalyear', '=', data['fiscalyear']), ('end_date', '<=', start_period.start_date), ]) start_period_name = start_period.name else: fiscalyear = FiscalYear(data['fiscalyear']) start_periods = Period.search([ ('end_date', '<=', fiscalyear.start_date), ]) if data['end_period']: end_period = Period(data['end_period']) end_periods = Period.search([ ('fiscalyear', '=', data['fiscalyear']), ('end_date', '<=', end_period.start_date), ]) end_periods = list(set(end_periods).difference( set(start_periods))) end_period_name = end_period.name if end_period not in end_periods: end_periods.append(end_period) else: end_periods = Period.search([ ('fiscalyear', '=', data['fiscalyear']), ]) end_periods = list(set(end_periods).difference( set(start_periods))) # Select Query for In in_periods = [p.id for p in end_periods] join1 = line.join(move) join1.condition = join1.right.id == line.move entity = line.party default_entity = 0 if not data['party'] and data['by_reference']: entity = line.reference default_entity = '0' select1 = join1.select( line.account, Coalesce(entity, default_entity), Sum(line.debit), Sum(line.credit), group_by=(line.account, entity), order_by=line.account, ) select1.where = (join1.right.period.in_(in_periods)) if data['party']: select1.where = select1.where & (line.party == data['party']) if data['accounts']: select1.where = select1.where & (line.account.in_(data['accounts'])) cursor.execute(*select1) result_in = cursor.fetchall() # Select Query for Start start_periods_ids = [p.id for p in start_periods] result_start = [] if start_periods_ids: join1 = line.join(move) join1.condition = join1.right.id == line.move select2 = join1.select( line.account, Coalesce(entity, default_entity), Sum(line.debit) - Sum(line.credit), group_by=(line.account, entity), order_by=line.account, ) select2.where = (join1.right.period.in_(start_periods_ids)) if data['party']: select2.where = select2.where & (line.party == data['party']) if data['accounts']: select2.where = select2.where & (line.account.in_(data['accounts'])) cursor.execute(*select2) result_start = cursor.fetchall() all_result = result_in + result_start accs_ids = [] parties_ids = [] for r in all_result: accs_ids.append(r[0]) parties_ids.append(r[1]) accounts = OrderedDict() # Prepare accounts if accs_ids: acc_records = Account.search_read([ ('id', 'in', list(set(accs_ids))), ('active', 'in', [False, True]), ], order=[('code', 'ASC')], fields_names=['code', 'name']) for acc in acc_records: accounts[acc['id']] = [ acc, {}, { 'debits': [], 'credits': [], 'start_balance': [], 'end_balance': [], } ] if not data['by_reference']: parties_obj = Party.search_read([ ('id', 'in', parties_ids), ('active', 'in', [False, True]), ], fields_names=['name']) parties = {p['id'] : p for p in parties_obj} else: parties = {p : p for p in parties_ids} def _get_process_result(kind, values): for val in values: party_id = 0 id_number = '---' party_name = '---' if not data['by_reference']: if val[1]: party_id = val[1] if Party(party_id).identifiers: id_number = Party(party_id).identifiers[0].code else: id_number = '' party_name = parties[party_id]['name'] else: party_id = val[1] id_number = val[1] party_name = val[1] acc_id = val[0] debit = 0 credit = 0 start_balance = 0 if kind == 'in': debit = val[2] credit = val[3] amount = debit - credit else: # kind == start start_balance = val[2] amount = val[2] if debit == credit == start_balance == 0: continue if party_id not in accounts[acc_id][1].keys(): end_balance = start_balance + debit - credit rec = { 'id_number': id_number, 'party': party_name, 'start_balance': start_balance, 'debit': debit, 'credit': credit, 'end_balance': end_balance, } accounts[acc_id][1][party_id] = rec amount = end_balance else: dictval = accounts[acc_id][1][party_id] if kind == 'in': dictval['debit'] = debit dictval['credit'] = credit else: dictval['start_balance'] = start_balance end_balance = dictval['start_balance'] + dictval['debit'] - dictval['credit'] dictval['end_balance'] = end_balance accounts[acc_id][2]['debits'].append(debit) accounts[acc_id][2]['credits'].append(credit) accounts[acc_id][2]['start_balance'].append(start_balance) accounts[acc_id][2]['end_balance'].append(amount) _get_process_result(kind='in', values=result_in) _get_process_result(kind='start', values=result_start) if accounts: records = accounts.values() else: records = accounts report_context['accounts'] = records report_context['fiscalyear'] = FiscalYear(data['fiscalyear']) report_context['start_period'] = start_period_name report_context['end_period'] = end_period_name report_context['company'] = Company(data['company']) return report_context