Show debit / credit columns in ledgers when they contain lines
issue11072 review372881002
This commit is contained in:
@@ -1,3 +1,5 @@
|
||||
* Show debit / credit columns in ledgers when they contain lines
|
||||
* Count number of lines in Account and General Ledger
|
||||
* Handle errors in move template expression
|
||||
* Rename split lines into reschedule lines
|
||||
* Add optional credit type on account
|
||||
|
||||
+111
-18
@@ -9,9 +9,10 @@ from itertools import zip_longest
|
||||
|
||||
from dateutil.relativedelta import relativedelta
|
||||
from sql import Column, Literal, Null, Window
|
||||
from sql.aggregate import Max, Min, Sum
|
||||
from sql.aggregate import Count, Max, Min, Sum
|
||||
from sql.conditionals import Case, Coalesce
|
||||
|
||||
from trytond import backend
|
||||
from trytond.i18n import gettext
|
||||
from trytond.model import (
|
||||
Check, ModelSQL, ModelView, Unique, fields, sequence_ordered, tree)
|
||||
@@ -876,10 +877,18 @@ class Account(AccountMixin(), ActivePeriodMixin, tree(), ModelSQL, ModelView):
|
||||
"Balance", currency='currency', digits='currency'),
|
||||
'get_balance')
|
||||
credit = fields.Function(Monetary(
|
||||
"Credit", currency='currency', digits='currency'),
|
||||
"Credit", currency='currency', digits='currency',
|
||||
states={
|
||||
'invisible': ~Eval('line_count', -1),
|
||||
},
|
||||
depends=['line_count']),
|
||||
'get_credit_debit')
|
||||
debit = fields.Function(Monetary(
|
||||
"Debit", currency='currency', digits='currency'),
|
||||
"Debit", currency='currency', digits='currency',
|
||||
states={
|
||||
'invisible': ~Eval('line_count', -1),
|
||||
},
|
||||
depends=['line_count']),
|
||||
'get_credit_debit')
|
||||
amount_second_currency = fields.Function(Monetary(
|
||||
"Amount Second Currency",
|
||||
@@ -889,6 +898,8 @@ class Account(AccountMixin(), ActivePeriodMixin, tree(), ModelSQL, ModelView):
|
||||
},
|
||||
depends=['second_currency']),
|
||||
'get_credit_debit')
|
||||
line_count = fields.Function(
|
||||
fields.Integer("Line Count"), 'get_credit_debit')
|
||||
note = fields.Text('Note')
|
||||
deferrals = fields.One2Many(
|
||||
'account.account.deferral', 'account', "Deferrals", readonly=True,
|
||||
@@ -1026,16 +1037,21 @@ class Account(AccountMixin(), ActivePeriodMixin, tree(), ModelSQL, ModelView):
|
||||
result = {}
|
||||
ids = [a.id for a in accounts]
|
||||
for name in names:
|
||||
if name not in {'credit', 'debit', 'amount_second_currency'}:
|
||||
if name not in {
|
||||
'credit', 'debit', 'amount_second_currency', 'line_count'}:
|
||||
raise ValueError('Unknown name: %s' % name)
|
||||
result[name] = dict((i, Decimal(0)) for i in ids)
|
||||
col_type = int if name == 'line_count' else Decimal
|
||||
result[name] = defaultdict(col_type)
|
||||
|
||||
table = cls.__table__()
|
||||
line = MoveLine.__table__()
|
||||
line_query, fiscalyear_ids = MoveLine.query_get(line)
|
||||
columns = [table.id]
|
||||
for name in names:
|
||||
columns.append(Sum(Coalesce(Column(line, name), 0)))
|
||||
if name == 'line_count':
|
||||
columns.append(Count(Literal('*')))
|
||||
else:
|
||||
columns.append(Sum(Coalesce(Column(line, name), 0)))
|
||||
for sub_ids in grouped_slice(ids):
|
||||
red_sql = reduce_ids(table.id, sub_ids)
|
||||
cursor.execute(*table.join(line, 'LEFT',
|
||||
@@ -1047,12 +1063,15 @@ class Account(AccountMixin(), ActivePeriodMixin, tree(), ModelSQL, ModelView):
|
||||
account_id = row[0]
|
||||
for i, name in enumerate(names, 1):
|
||||
# SQLite uses float for SUM
|
||||
if not isinstance(row[i], Decimal):
|
||||
if (name != 'line_count'
|
||||
and not isinstance(row[i], Decimal)):
|
||||
result[name][account_id] = Decimal(str(row[i]))
|
||||
else:
|
||||
result[name][account_id] = row[i]
|
||||
for account in accounts:
|
||||
for name in names:
|
||||
if name == 'line_count':
|
||||
continue
|
||||
if (name == 'amount_second_currency'
|
||||
and account.second_currency):
|
||||
currency = account.second_currency
|
||||
@@ -1397,6 +1416,8 @@ class AccountParty(ActivePeriodMixin, ModelSQL):
|
||||
},
|
||||
depends=['second_currency']),
|
||||
'get_credit_debit')
|
||||
line_count = fields.Function(
|
||||
fields.Integer("Line Count"), 'get_credit_debit')
|
||||
second_currency = fields.Many2One(
|
||||
'currency.currency', "Secondary Currency")
|
||||
|
||||
@@ -1496,11 +1517,12 @@ class AccountParty(ActivePeriodMixin, ModelSQL):
|
||||
cursor = Transaction().connection.cursor()
|
||||
|
||||
result = {}
|
||||
ids = [a.id for a in records]
|
||||
for name in names:
|
||||
if name not in {'credit', 'debit', 'amount_second_currency'}:
|
||||
if name not in {
|
||||
'credit', 'debit', 'amount_second_currency', 'line_count'}:
|
||||
raise ValueError('Unknown name: %s' % name)
|
||||
result[name] = dict((i, Decimal(0)) for i in ids)
|
||||
column_type = int if name == 'line_count' else Decimal
|
||||
result[name] = defaultdict(column_type)
|
||||
|
||||
account_ids = {a.account.id for a in records}
|
||||
party_ids = {a.party.id for a in records}
|
||||
@@ -1510,7 +1532,10 @@ class AccountParty(ActivePeriodMixin, ModelSQL):
|
||||
line_query, fiscalyear_ids = MoveLine.query_get(line)
|
||||
columns = [table.id, line.party]
|
||||
for name in names:
|
||||
columns.append(Sum(Coalesce(Column(line, name), 0)))
|
||||
if name == 'line_count':
|
||||
columns.append(Count(Literal('*')))
|
||||
else:
|
||||
columns.append(Sum(Coalesce(Column(line, name), 0)))
|
||||
for sub_account_ids in grouped_slice(account_ids):
|
||||
account_sql = reduce_ids(table.id, sub_account_ids)
|
||||
for sub_party_ids in grouped_slice(party_ids):
|
||||
@@ -1529,12 +1554,15 @@ class AccountParty(ActivePeriodMixin, ModelSQL):
|
||||
continue
|
||||
for i, name in enumerate(names, 2):
|
||||
# SQLite uses float for SUM
|
||||
if not isinstance(row[i], Decimal):
|
||||
if (name != 'line_count'
|
||||
and not isinstance(row[i], Decimal)):
|
||||
result[name][id_] = Decimal(str(row[i]))
|
||||
else:
|
||||
result[name][id_] = row[i]
|
||||
for record in records:
|
||||
for name in names:
|
||||
if name == 'line_count':
|
||||
continue
|
||||
if name == 'amount_second_currency' and record.second_currency:
|
||||
currency = record.second_currency
|
||||
else:
|
||||
@@ -1586,6 +1614,7 @@ class AccountDeferral(ModelSQL, ModelView):
|
||||
'invisible': ~Eval('second_currency'),
|
||||
},
|
||||
depends=['second_currency'])
|
||||
line_count = fields.Integer("Line Count", required=True)
|
||||
second_currency = fields.Function(fields.Many2One(
|
||||
'currency.currency', "Second Currency"), 'get_second_currency')
|
||||
|
||||
@@ -1598,10 +1627,47 @@ class AccountDeferral(ModelSQL, ModelView):
|
||||
'account.msg_deferral_unique'),
|
||||
]
|
||||
|
||||
@classmethod
|
||||
def __register__(cls, module_name):
|
||||
pool = Pool()
|
||||
MoveLine = pool.get('account.move.line')
|
||||
Move = pool.get('account.move')
|
||||
Period = pool.get('account.period')
|
||||
|
||||
cursor = Transaction().connection.cursor()
|
||||
deferral = cls.__table__()
|
||||
move_line = MoveLine.__table__()
|
||||
move = Move.__table__()
|
||||
period = Period.__table__()
|
||||
|
||||
exist = backend.TableHandler.table_exist(cls._table)
|
||||
table_h = cls.__table_handler__(module_name)
|
||||
created_line_count = exist and not table_h.column_exist('line_count')
|
||||
|
||||
super().__register__(module_name)
|
||||
|
||||
# Migration from 6.2: add line_count on deferrals
|
||||
if created_line_count:
|
||||
counting_query = (move_line
|
||||
.join(move, condition=move_line.move == move.id)
|
||||
.join(period, condition=move.period == period.id)
|
||||
.select(
|
||||
move_line.account, period.fiscalyear, Count(Literal('*')),
|
||||
group_by=[move_line.account, period.fiscalyear]))
|
||||
cursor.execute(*deferral.update(
|
||||
[deferral.line_count], [counting_query.line_count],
|
||||
from_=[counting_query],
|
||||
where=((deferral.account == counting_query.account)
|
||||
& (deferral.fiscalyear == counting_query.fiscalyear))))
|
||||
|
||||
@classmethod
|
||||
def default_amount_second_currency(cls):
|
||||
return Decimal(0)
|
||||
|
||||
@classmethod
|
||||
def default_line_count(cls):
|
||||
return 0
|
||||
|
||||
@classmethod
|
||||
def get_balance(cls, deferrals, name):
|
||||
pool = Pool()
|
||||
@@ -1715,23 +1781,50 @@ class _GeneralLedgerAccount(ActivePeriodMixin, ModelSQL, ModelView):
|
||||
account = fields.Many2One('account.account', "Account")
|
||||
company = fields.Many2One('company.company', 'Company')
|
||||
start_debit = fields.Function(Monetary(
|
||||
"Start Debit", currency='currency', digits='currency'),
|
||||
"Start Debit", currency='currency', digits='currency',
|
||||
states={
|
||||
'invisible': ~Eval('line_count', -1),
|
||||
},
|
||||
depends=['line_count']),
|
||||
'get_account', searcher='search_account')
|
||||
debit = fields.Function(Monetary(
|
||||
"Debit", currency='currency', digits='currency'),
|
||||
"Debit", currency='currency', digits='currency',
|
||||
states={
|
||||
'invisible': ~Eval('line_count', -1),
|
||||
},
|
||||
depends=['line_count']),
|
||||
'get_debit_credit', searcher='search_debit_credit')
|
||||
end_debit = fields.Function(Monetary(
|
||||
"End Debit", currency='currency', digits='currency'),
|
||||
"End Debit", currency='currency', digits='currency',
|
||||
states={
|
||||
'invisible': ~Eval('line_count', -1),
|
||||
},
|
||||
depends=['line_count']),
|
||||
'get_account', searcher='search_account')
|
||||
start_credit = fields.Function(Monetary(
|
||||
"Start Credit", currency='currency', digits='currency'),
|
||||
"Start Credit", currency='currency', digits='currency',
|
||||
states={
|
||||
'invisible': ~Eval('line_count', -1),
|
||||
},
|
||||
depends=['line_count']),
|
||||
'get_account', searcher='search_account')
|
||||
credit = fields.Function(Monetary(
|
||||
"Credit", currency='currency', digits='currency'),
|
||||
"Credit", currency='currency', digits='currency',
|
||||
states={
|
||||
'invisible': ~Eval('line_count', -1),
|
||||
},
|
||||
depends=['line_count']),
|
||||
'get_debit_credit', searcher='search_debit_credit')
|
||||
end_credit = fields.Function(Monetary(
|
||||
"End Credit", currency='currency', digits='currency'),
|
||||
"End Credit", currency='currency', digits='currency',
|
||||
states={
|
||||
'invisible': ~Eval('line_count', -1),
|
||||
},
|
||||
depends=['line_count']),
|
||||
'get_account', searcher='search_account')
|
||||
line_count = fields.Function(
|
||||
fields.Integer("Line Count"),
|
||||
'get_debit_credit', searcher='search_debit_credit')
|
||||
start_balance = fields.Function(Monetary(
|
||||
"Start Balance", currency='currency', digits='currency'),
|
||||
'get_account', searcher='search_account')
|
||||
|
||||
@@ -550,6 +550,7 @@ this repository contains the full copyright notices and license terms. -->
|
||||
<field name="name">General Ledger - Accounts</field>
|
||||
<field name="res_model">account.general_ledger.account</field>
|
||||
<field name="context_model">account.general_ledger.account.context</field>
|
||||
<field name="search_value" eval="[('line_count', '!=', 0)]" pyson="1"/>
|
||||
</record>
|
||||
<record model="ir.action.act_window.view"
|
||||
id="act_general_ledger_account_form_view1">
|
||||
|
||||
@@ -257,6 +257,7 @@ class FiscalYear(Workflow, ModelSQL, ModelView):
|
||||
deferral.fiscalyear = self
|
||||
deferral.debit = account.debit
|
||||
deferral.credit = account.credit
|
||||
deferral.line_count = account.line_count
|
||||
deferral.amount_second_currency = account.amount_second_currency
|
||||
return deferral
|
||||
|
||||
|
||||
+105
-5
@@ -40,6 +40,12 @@ Create chart of accounts::
|
||||
>>> expense = accounts['expense']
|
||||
>>> cash = accounts['cash']
|
||||
|
||||
Create a child account::
|
||||
|
||||
>>> _ = revenue.childs.new()
|
||||
>>> revenue.save()
|
||||
>>> child_revenue, = revenue.childs
|
||||
|
||||
Create parties::
|
||||
|
||||
>>> Party = Model.get('party.party')
|
||||
@@ -61,7 +67,7 @@ Create a moves::
|
||||
>>> move.journal = journal_revenue
|
||||
>>> move.date = period_3.start_date
|
||||
>>> line = move.lines.new()
|
||||
>>> line.account = revenue
|
||||
>>> line.account = child_revenue
|
||||
>>> line.credit = Decimal(10)
|
||||
>>> line = move.lines.new()
|
||||
>>> line.account = receivable
|
||||
@@ -102,6 +108,9 @@ Print some reports::
|
||||
... 'fiscalyear': fiscalyear.id,
|
||||
... }
|
||||
>>> with config.set_context(context):
|
||||
... gl_child_revenue, = GeneralLedgerAccount.find([
|
||||
... ('account', '=', child_revenue.id),
|
||||
... ])
|
||||
... gl_revenue, = GeneralLedgerAccount.find([
|
||||
... ('account', '=', revenue.id),
|
||||
... ])
|
||||
@@ -109,14 +118,26 @@ Print some reports::
|
||||
... ('account', '=', receivable.id),
|
||||
... ('party', '=', party.id),
|
||||
... ])
|
||||
>>> gl_child_revenue.start_balance
|
||||
Decimal('0.00')
|
||||
>>> gl_child_revenue.credit
|
||||
Decimal('10.00')
|
||||
>>> gl_child_revenue.debit
|
||||
Decimal('0.00')
|
||||
>>> gl_child_revenue.end_balance
|
||||
Decimal('-10.00')
|
||||
>>> gl_child_revenue.line_count
|
||||
1
|
||||
>>> gl_revenue.start_balance
|
||||
Decimal('0.00')
|
||||
>>> gl_revenue.credit
|
||||
Decimal('10.00')
|
||||
Decimal('0.00')
|
||||
>>> gl_revenue.debit
|
||||
Decimal('0.00')
|
||||
>>> gl_revenue.end_balance
|
||||
Decimal('-10.00')
|
||||
>>> gl_revenue.line_count
|
||||
0
|
||||
>>> glp_receivable.start_balance
|
||||
Decimal('0.00')
|
||||
>>> glp_receivable.credit
|
||||
@@ -125,6 +146,8 @@ Print some reports::
|
||||
Decimal('10.00')
|
||||
>>> glp_receivable.end_balance
|
||||
Decimal('0.00')
|
||||
>>> glp_receivable.line_count
|
||||
2
|
||||
|
||||
>>> context = {
|
||||
... 'company': company.id,
|
||||
@@ -133,6 +156,9 @@ Print some reports::
|
||||
... 'to_date': period_3.end_date,
|
||||
... }
|
||||
>>> with config.set_context(context):
|
||||
... gl_child_revenue, = GeneralLedgerAccount.find([
|
||||
... ('account', '=', child_revenue.id),
|
||||
... ])
|
||||
... gl_revenue, = GeneralLedgerAccount.find([
|
||||
... ('account', '=', revenue.id),
|
||||
... ])
|
||||
@@ -140,14 +166,26 @@ Print some reports::
|
||||
... ('account', '=', receivable.id),
|
||||
... ('party', '=', party.id),
|
||||
... ])
|
||||
>>> gl_child_revenue.start_balance
|
||||
Decimal('0.00')
|
||||
>>> gl_child_revenue.credit
|
||||
Decimal('10.00')
|
||||
>>> gl_child_revenue.debit
|
||||
Decimal('0.00')
|
||||
>>> gl_child_revenue.end_balance
|
||||
Decimal('-10.00')
|
||||
>>> gl_child_revenue.line_count
|
||||
1
|
||||
>>> gl_revenue.start_balance
|
||||
Decimal('0.00')
|
||||
>>> gl_revenue.credit
|
||||
Decimal('10.00')
|
||||
Decimal('0.00')
|
||||
>>> gl_revenue.debit
|
||||
Decimal('0.00')
|
||||
>>> gl_revenue.end_balance
|
||||
Decimal('-10.00')
|
||||
>>> gl_revenue.line_count
|
||||
0
|
||||
>>> glp_receivable.start_balance
|
||||
Decimal('0.00')
|
||||
>>> glp_receivable.credit
|
||||
@@ -156,6 +194,8 @@ Print some reports::
|
||||
Decimal('10.00')
|
||||
>>> glp_receivable.end_balance
|
||||
Decimal('10.00')
|
||||
>>> glp_receivable.line_count
|
||||
1
|
||||
|
||||
>>> context = {
|
||||
... 'company': company.id,
|
||||
@@ -163,17 +203,32 @@ Print some reports::
|
||||
... 'start_period': period_3.id,
|
||||
... }
|
||||
>>> with config.set_context(context):
|
||||
... gl_child_revenue, = GeneralLedgerAccount.find([
|
||||
... ('account', '=', child_revenue.id),
|
||||
... ])
|
||||
... gl_revenue, = GeneralLedgerAccount.find([
|
||||
... ('account', '=', revenue.id),
|
||||
... ])
|
||||
>>> gl_child_revenue.start_balance
|
||||
Decimal('0.00')
|
||||
>>> gl_child_revenue.credit
|
||||
Decimal('10.00')
|
||||
>>> gl_child_revenue.debit
|
||||
Decimal('0.00')
|
||||
>>> gl_child_revenue.end_balance
|
||||
Decimal('-10.00')
|
||||
>>> gl_child_revenue.line_count
|
||||
1
|
||||
>>> gl_revenue.start_balance
|
||||
Decimal('0.00')
|
||||
>>> gl_revenue.credit
|
||||
Decimal('10.00')
|
||||
Decimal('0.00')
|
||||
>>> gl_revenue.debit
|
||||
Decimal('0.00')
|
||||
>>> gl_revenue.end_balance
|
||||
Decimal('-10.00')
|
||||
>>> gl_revenue.line_count
|
||||
0
|
||||
|
||||
>>> context = {
|
||||
... 'company': company.id,
|
||||
@@ -181,9 +236,22 @@ Print some reports::
|
||||
... 'start_period': period_5.id,
|
||||
... }
|
||||
>>> with config.set_context(context):
|
||||
... gl_child_revenue, = GeneralLedgerAccount.find([
|
||||
... ('account', '=', child_revenue.id),
|
||||
... ])
|
||||
... gl_revenue, = GeneralLedgerAccount.find([
|
||||
... ('account', '=', revenue.id),
|
||||
... ])
|
||||
>>> gl_child_revenue.start_balance
|
||||
Decimal('-10.00')
|
||||
>>> gl_child_revenue.credit
|
||||
Decimal('0.00')
|
||||
>>> gl_child_revenue.debit
|
||||
Decimal('0.00')
|
||||
>>> gl_child_revenue.end_balance
|
||||
Decimal('-10.00')
|
||||
>>> gl_child_revenue.line_count
|
||||
0
|
||||
>>> gl_revenue.start_balance
|
||||
Decimal('-10.00')
|
||||
>>> gl_revenue.credit
|
||||
@@ -192,6 +260,8 @@ Print some reports::
|
||||
Decimal('0.00')
|
||||
>>> gl_revenue.end_balance
|
||||
Decimal('-10.00')
|
||||
>>> gl_revenue.line_count
|
||||
0
|
||||
|
||||
>>> context = {
|
||||
... 'company': company.id,
|
||||
@@ -199,17 +269,32 @@ Print some reports::
|
||||
... 'from_date': period_3.start_date,
|
||||
... }
|
||||
>>> with config.set_context(context):
|
||||
... gl_child_revenue, = GeneralLedgerAccount.find([
|
||||
... ('account', '=', child_revenue.id),
|
||||
... ])
|
||||
... gl_revenue, = GeneralLedgerAccount.find([
|
||||
... ('account', '=', revenue.id),
|
||||
... ])
|
||||
>>> gl_child_revenue.start_balance
|
||||
Decimal('0.00')
|
||||
>>> gl_child_revenue.credit
|
||||
Decimal('10.00')
|
||||
>>> gl_child_revenue.debit
|
||||
Decimal('0.00')
|
||||
>>> gl_child_revenue.end_balance
|
||||
Decimal('-10.00')
|
||||
>>> gl_child_revenue.line_count
|
||||
1
|
||||
>>> gl_revenue.start_balance
|
||||
Decimal('0.00')
|
||||
>>> gl_revenue.credit
|
||||
Decimal('10.00')
|
||||
Decimal('0.00')
|
||||
>>> gl_revenue.debit
|
||||
Decimal('0.00')
|
||||
>>> gl_revenue.end_balance
|
||||
Decimal('-10.00')
|
||||
>>> gl_revenue.line_count
|
||||
0
|
||||
|
||||
>>> context = {
|
||||
... 'company': company.id,
|
||||
@@ -217,9 +302,22 @@ Print some reports::
|
||||
... 'from_date': period_5.start_date,
|
||||
... }
|
||||
>>> with config.set_context(context):
|
||||
... gl_child_revenue, = GeneralLedgerAccount.find([
|
||||
... ('account', '=', child_revenue.id),
|
||||
... ])
|
||||
... gl_revenue, = GeneralLedgerAccount.find([
|
||||
... ('account', '=', revenue.id),
|
||||
... ])
|
||||
>>> gl_child_revenue.start_balance
|
||||
Decimal('-10.00')
|
||||
>>> gl_child_revenue.credit
|
||||
Decimal('0.00')
|
||||
>>> gl_child_revenue.debit
|
||||
Decimal('0.00')
|
||||
>>> gl_child_revenue.end_balance
|
||||
Decimal('-10.00')
|
||||
>>> gl_child_revenue.line_count
|
||||
0
|
||||
>>> gl_revenue.start_balance
|
||||
Decimal('-10.00')
|
||||
>>> gl_revenue.credit
|
||||
@@ -228,6 +326,8 @@ Print some reports::
|
||||
Decimal('0.00')
|
||||
>>> gl_revenue.end_balance
|
||||
Decimal('-10.00')
|
||||
>>> gl_revenue.line_count
|
||||
0
|
||||
|
||||
>>> trial_balance = Report('account.trial_balance', context={
|
||||
... 'company': company.id,
|
||||
|
||||
@@ -4,6 +4,7 @@ this repository contains the full copyright notices and license terms. -->
|
||||
<tree keyword_open="1">
|
||||
<field name="account" expand="1"/>
|
||||
<field name="start_balance" sum="Start Balance" optional="0"/>
|
||||
<field name="line_count" optional="1"/>
|
||||
<field name="debit" sum="Debit" optional="0"/>
|
||||
<field name="credit" sum="Credit" optional="0"/>
|
||||
<field name="end_balance" sum="End Balance" optional="0"/>
|
||||
|
||||
Reference in New Issue
Block a user