diff --git a/CHANGELOG b/CHANGELOG index a17a344068..30c0802ec9 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,7 @@ +* Merge Third Party Balance into Aged Balance +* Add date to Aged Balance +* Add date on Reconciliation + Version 3.8.0 - 2015-11-02 * Bug fixes (see mercurial logs for details) * Make Chart of Account not translatable diff --git a/__init__.py b/__init__.py index 8a718fc64c..2a77933b59 100644 --- a/__init__.py +++ b/__init__.py @@ -33,7 +33,6 @@ def register(): CreateChartProperties, UpdateChartStart, UpdateChartSucceed, - OpenThirdPartyBalanceStart, OpenAgedBalanceStart, Configuration, Period, @@ -87,7 +86,6 @@ def register(): OpenIncomeStatement, CreateChart, UpdateChart, - OpenThirdPartyBalance, OpenAgedBalance, ClosePeriod, ReOpenPeriod, @@ -108,7 +106,6 @@ def register(): Pool.register( GeneralLedger, TrialBalance, - ThirdPartyBalance, AgedBalance, GeneralJournal, module='account', type_='report') diff --git a/account.py b/account.py index e3d8efbb98..29b8e9e623 100644 --- a/account.py +++ b/account.py @@ -6,7 +6,7 @@ import operator from itertools import izip, groupby from functools import wraps -from sql import Column, Literal, Null +from sql import Column, Null from sql.aggregate import Sum from sql.conditionals import Coalesce, Case @@ -28,7 +28,6 @@ __all__ = ['TypeTemplate', 'Type', 'OpenType', 'AccountTemplate', 'Account', 'OpenIncomeStatementStart', 'OpenIncomeStatement', 'CreateChartStart', 'CreateChartAccount', 'CreateChartProperties', 'CreateChart', 'UpdateChartStart', 'UpdateChartSucceed', 'UpdateChart', - 'OpenThirdPartyBalanceStart', 'OpenThirdPartyBalance', 'ThirdPartyBalance', 'OpenAgedBalanceStart', 'OpenAgedBalance', 'AgedBalance'] @@ -1856,115 +1855,6 @@ class UpdateChart(Wizard): return 'succeed' -class OpenThirdPartyBalanceStart(ModelView): - 'Open Third Party Balance' - __name__ = 'account.open_third_party_balance.start' - company = fields.Many2One('company.company', 'Company', required=True) - fiscalyear = fields.Many2One('account.fiscalyear', 'Fiscal Year', - required=True) - posted = fields.Boolean('Posted Move', help='Show only posted move') - - @staticmethod - def default_fiscalyear(): - Fiscalyear = Pool().get('account.fiscalyear') - return Fiscalyear.find( - Transaction().context.get('company'), exception=False) - - @staticmethod - def default_posted(): - return False - - @staticmethod - def default_company(): - return Transaction().context.get('company') - - -class OpenThirdPartyBalance(Wizard): - 'Open Third Party Balance' - __name__ = 'account.open_third_party_balance' - start = StateView('account.open_third_party_balance.start', - 'account.open_third_party_balance_start_view_form', [ - Button('Cancel', 'end', 'tryton-cancel'), - Button('Print', 'print_', 'tryton-print', default=True), - ]) - print_ = StateReport('account.third_party_balance') - - def do_print_(self, action): - data = { - 'company': self.start.company.id, - 'fiscalyear': self.start.fiscalyear.id, - 'posted': self.start.posted, - } - return action, data - - def transition_print_(self): - return 'end' - - -class ThirdPartyBalance(Report): - __name__ = 'account.third_party_balance' - - @classmethod - def get_context(cls, records, data): - report_context = super(ThirdPartyBalance, cls).get_context(records, - data) - - pool = Pool() - Party = pool.get('party.party') - MoveLine = pool.get('account.move.line') - Move = pool.get('account.move') - Account = pool.get('account.account') - Company = pool.get('company.company') - Date = pool.get('ir.date') - cursor = Transaction().cursor - - line = MoveLine.__table__() - move = Move.__table__() - account = Account.__table__() - - company = Company(data['company']) - report_context['company'] = company - report_context['digits'] = company.currency.digits - report_context['fiscalyear'] = data['fiscalyear'] - with Transaction().set_context(context=report_context): - line_query, _ = MoveLine.query_get(line) - if data['posted']: - posted_clause = move.state == 'posted' - else: - posted_clause = Literal(True) - - cursor.execute(*line.join(move, condition=line.move == move.id - ).join(account, condition=line.account == account.id - ).select(line.party, Sum(line.debit), Sum(line.credit), - where=(line.party != Null) - & (account.active == True) - & account.kind.in_(('payable', 'receivable')) - & (account.company == data['company']) - & ((line.maturity_date <= Date.today()) - | (line.maturity_date == Null)) - & line_query & posted_clause, - group_by=line.party, - having=(Sum(line.debit) != 0) | (Sum(line.credit) != 0))) - - res = cursor.fetchall() - id2party = {} - for party in Party.browse([x[0] for x in res]): - id2party[party.id] = party - objects = [{ - 'name': id2party[x[0]].rec_name, - 'debit': x[1], - 'credit': x[2], - 'solde': x[1] - x[2], - } for x in res] - objects.sort(lambda x, y: cmp(x['name'], y['name'])) - report_context['total_debit'] = sum((x['debit'] for x in objects)) - report_context['total_credit'] = sum((x['credit'] for x in objects)) - report_context['total_solde'] = sum((x['solde'] for x in objects)) - report_context['records'] = objects - - return report_context - - class OpenAgedBalanceStart(ModelView): 'Open Aged Balance' __name__ = 'account.open_aged_balance.start' @@ -1972,9 +1862,18 @@ class OpenAgedBalanceStart(ModelView): balance_type = fields.Selection( [('customer', 'Customer'), ('supplier', 'Supplier'), ('both', 'Both')], "Type", required=True) + date = fields.Date('Date', required=True) term1 = fields.Integer("First Term", required=True) - term2 = fields.Integer("Second Term", required=True) - term3 = fields.Integer("Third Term", required=True) + term2 = fields.Integer("Second Term", required=True, + domain=[ + ('term2', '>', Eval('term1', 0)), + ], + depends=['term1']) + term3 = fields.Integer("Third Term", required=True, + domain=[ + ('term3', '>', Eval('term2', 0)), + ], + depends=['term2']) unit = fields.Selection( [('day', 'Day'), ('month', 'Month')], "Unit", required=True) posted = fields.Boolean('Posted Move', help='Show only posted move') @@ -1987,6 +1886,10 @@ class OpenAgedBalanceStart(ModelView): def default_posted(): return False + @classmethod + def default_date(cls): + return Pool().get('ir.date').today() + @staticmethod def default_term1(): return 30 @@ -2032,6 +1935,7 @@ class OpenAgedBalance(Wizard): error_description="term_overlap_desc") data = { 'company': self.start.company.id, + 'date': self.start.date, 'term1': self.start.term1, 'term2': self.start.term2, 'term3': self.start.term3, @@ -2056,13 +1960,14 @@ class AgedBalance(Report): Party = pool.get('party.party') MoveLine = pool.get('account.move.line') Move = pool.get('account.move') + Reconciliation = pool.get('account.move.reconciliation') Account = pool.get('account.account') Company = pool.get('company.company') - Date = pool.get('ir.date') cursor = Transaction().cursor line = MoveLine.__table__() move = Move.__table__() + reconciliation = Reconciliation.__table__() account = Account.__table__() company = Company(data['company']) @@ -2071,7 +1976,7 @@ class AgedBalance(Report): with Transaction().set_context(context=report_context): line_query, _ = MoveLine.query_get(line) - terms = (data['term1'], data['term2'], data['term3']) + terms = (0, data['term1'], data['term2'], data['term3']) if data['unit'] == 'month': coef = datetime.timedelta(days=30) else: @@ -2083,20 +1988,27 @@ class AgedBalance(Report): 'customer': ('receivable',), }[data['balance_type']] + report_context['date'] = date = data['date'] res = {} for position, term in enumerate(terms): - term_query = line.maturity_date <= (Date.today() - term * coef) - if position != 2: + term_query = line.maturity_date <= (date - term * coef) + if position + 1 < len(terms): term_query &= line.maturity_date > ( - Date.today() - terms[position + 1] * coef) + date - terms[position + 1] * coef) + else: + term_query |= line.maturity_date == Null cursor.execute(*line.join(move, condition=line.move == move.id ).join(account, condition=line.account == account.id + ).join(reconciliation, 'LEFT', + condition=reconciliation.id == line.reconciliation ).select(line.party, Sum(line.debit) - Sum(line.credit), where=(line.party != Null) & (account.active == True) & account.kind.in_(kind) - & (line.reconciliation == Null) + & ((line.reconciliation == Null) + | (reconciliation.date > date)) + & (move.date <= date) & (account.company == data['company']) & term_query & line_query, group_by=line.party, @@ -2113,17 +2025,22 @@ class AgedBalance(Report): report_context['main_title'] = data['balance_type'] report_context['unit'] = data['unit'] - for i in range(3): + total = 0 + for i in range(len(terms)): report_context['total' + str(i)] = sum( (v[i] for v in res.itervalues())) + total += report_context['total' + str(i)] report_context['term' + str(i)] = terms[i] + report_context['total'] = total report_context['company'] = company report_context['parties'] = [{ 'name': p.rec_name, + 'balance': sum(res[p.id]), 'amount0': res[p.id][0], 'amount1': res[p.id][1], 'amount2': res[p.id][2], + 'amount3': res[p.id][3], } for p in parties] return report_context diff --git a/account.xml b/account.xml index d830c8c067..dff06932d4 100644 --- a/account.xml +++ b/account.xml @@ -523,25 +523,6 @@ this repository contains the full copyright notices and license terms. --> id="menu_open_income_statement" icon="tryton-tree" name="Income Statement"/> - - account.open_third_party_balance.start - form - open_third_party_balance_start_form - - - Third Party Balance - - account.third_party_balance - account/third_party_balance.odt - - - Open Third Party Balance - account.open_third_party_balance - - - account.open_aged_balance.start form diff --git a/aged_balance.odt b/aged_balance.odt index 5ef8ddcf11..a7956d1eb7 100644 Binary files a/aged_balance.odt and b/aged_balance.odt differ diff --git a/move.py b/move.py index 905d697f43..fa36604bb4 100644 --- a/move.py +++ b/move.py @@ -7,7 +7,7 @@ from operator import itemgetter from collections import defaultdict from sql import Null -from sql.aggregate import Sum +from sql.aggregate import Sum, Max from sql.conditionals import Coalesce, Case from trytond.model import ModelView, ModelSQL, fields, Check @@ -460,6 +460,8 @@ class Reconciliation(ModelSQL, ModelView): name = fields.Char('Name', size=None, required=True) lines = fields.One2Many('account.move.line', 'reconciliation', 'Lines') + date = fields.Date('Date', required=True, select=True, + help='Highest date of the reconciled lines') @classmethod def __setup__(cls): @@ -483,6 +485,32 @@ class Reconciliation(ModelSQL, ModelView): '"%(credit)s" differ.'), }) + @classmethod + def __register__(cls, module_name): + TableHandler = backend.get('TableHandler') + cursor = Transaction().cursor + table = TableHandler(cursor, cls, module_name) + sql_table = cls.__table__() + pool = Pool() + Move = pool.get('account.move') + Line = pool.get('account.move.line') + move = Move.__table__() + line = Line.__table__() + + date_exist = table.column_exist('date') + + super(Reconciliation, cls).__register__(module_name) + + # Migration from 3.8: new date field + if not date_exist: + cursor.execute(*sql_table.update( + [sql_table.date], + line.join(move, + condition=move.id == line.move + ).select(Max(move.date), + where=line.reconciliation == sql_table.id, + group_by=line.reconciliation))) + @classmethod def create(cls, vlist): Sequence = Pool().get('ir.sequence') @@ -1579,6 +1607,7 @@ class Line(ModelSQL, ModelView): ], limit=1) return Reconciliation.create([{ 'lines': [('add', [x.id for x in lines])], + 'date': max(l.date for l in lines), }])[0] diff --git a/third_party_balance.odt b/third_party_balance.odt deleted file mode 100644 index 9b6a0c8d4a..0000000000 Binary files a/third_party_balance.odt and /dev/null differ diff --git a/view/open_aged_balance_start_form.xml b/view/open_aged_balance_start_form.xml index 42efbf4d0c..2fd86af7e5 100644 --- a/view/open_aged_balance_start_form.xml +++ b/view/open_aged_balance_start_form.xml @@ -9,6 +9,8 @@ this repository contains the full copyright notices and license terms. -->