Add Journal Cash reporting
issue4891 review15581002
This commit is contained in:
@@ -1,3 +1,5 @@
|
||||
* Add Journal Cash reporting
|
||||
|
||||
Version 3.6.0 - 2015-04-20
|
||||
* Bug fixes (see mercurial logs for details)
|
||||
* Add support for PyPy
|
||||
|
||||
@@ -41,6 +41,7 @@ def register():
|
||||
JournalView,
|
||||
JournalViewColumn,
|
||||
Journal,
|
||||
OpenJournalCashStart,
|
||||
JournalPeriod,
|
||||
Move,
|
||||
Reconciliation,
|
||||
@@ -90,6 +91,7 @@ def register():
|
||||
OpenAgedBalance,
|
||||
ClosePeriod,
|
||||
ReOpenPeriod,
|
||||
OpenJournalCash,
|
||||
CloseJournalPeriod,
|
||||
ReOpenJournalPeriod,
|
||||
OpenJournal,
|
||||
|
||||
+123
-2
@@ -1,16 +1,22 @@
|
||||
# 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 import Null
|
||||
from sql.conditionals import Case
|
||||
from sql.aggregate import Sum
|
||||
|
||||
from trytond.model import ModelView, ModelSQL, fields, Unique
|
||||
from trytond.wizard import Wizard, StateTransition
|
||||
from trytond.wizard import Wizard, StateTransition, StateView, StateAction
|
||||
from trytond.wizard import Button
|
||||
from trytond import backend
|
||||
from trytond.pyson import Eval, Bool
|
||||
from trytond.pyson import Eval, Bool, PYSONEncoder
|
||||
from trytond.transaction import Transaction
|
||||
from trytond.pool import Pool
|
||||
from trytond.tools import reduce_ids, grouped_slice
|
||||
|
||||
__all__ = ['JournalType', 'JournalView', 'JournalViewColumn', 'Journal',
|
||||
'OpenJournalCash', 'OpenJournalCashStart',
|
||||
'JournalPeriod', 'CloseJournalPeriod', 'ReOpenJournalPeriod']
|
||||
|
||||
STATES = {
|
||||
@@ -128,6 +134,17 @@ class Journal(ModelSQL, ModelView):
|
||||
& (Eval('context', {}).get('company', -1) != -1)),
|
||||
'invisible': ~Eval('context', {}).get('company', -1),
|
||||
}, depends=['type']))
|
||||
debit = fields.Function(fields.Numeric('Debit',
|
||||
digits=(16, Eval('currency_digits', 2)),
|
||||
depends=['currency_digits']), 'get_debit_credit_balance')
|
||||
credit = fields.Function(fields.Numeric('Credit',
|
||||
digits=(16, Eval('currency_digits', 2)),
|
||||
depends=['currency_digits']), 'get_debit_credit_balance')
|
||||
balance = fields.Function(fields.Numeric('Balance',
|
||||
digits=(16, Eval('currency_digits', 2)),
|
||||
depends=['currency_digits']), 'get_debit_credit_balance')
|
||||
currency_digits = fields.Function(fields.Integer('Currency Digits'),
|
||||
'get_currency_digits')
|
||||
|
||||
@classmethod
|
||||
def __setup__(cls):
|
||||
@@ -181,6 +198,110 @@ class Journal(ModelSQL, ModelView):
|
||||
(cls._rec_name,) + tuple(clause[1:]),
|
||||
]
|
||||
|
||||
@classmethod
|
||||
def get_currency_digits(cls, journals, name):
|
||||
pool = Pool()
|
||||
Company = pool.get('company.company')
|
||||
company_id = Transaction().context.get('company')
|
||||
if company_id:
|
||||
company = Company(company_id)
|
||||
digits = company.currency.digits
|
||||
else:
|
||||
digits = 2
|
||||
return dict.fromkeys([j.id for j in journals], digits)
|
||||
|
||||
@classmethod
|
||||
def get_debit_credit_balance(cls, journals, names):
|
||||
pool = Pool()
|
||||
MoveLine = pool.get('account.move.line')
|
||||
Move = pool.get('account.move')
|
||||
context = Transaction().context
|
||||
cursor = Transaction().cursor
|
||||
|
||||
result = {}
|
||||
ids = [j.id for j in journals]
|
||||
for name in ['debit', 'credit', 'balance']:
|
||||
result[name] = dict.fromkeys(ids, 0)
|
||||
|
||||
line = MoveLine.__table__()
|
||||
move = Move.__table__()
|
||||
where = ((move.date >= context['start_date'])
|
||||
& (move.date <= context['end_date']))
|
||||
for sub_journals in grouped_slice(journals):
|
||||
sub_journals = list(sub_journals)
|
||||
red_sql = reduce_ids(move.journal, [j.id for j in sub_journals])
|
||||
accounts = None
|
||||
for journal in sub_journals:
|
||||
credit_account = (journal.credit_account.id
|
||||
if journal.credit_account else None)
|
||||
debit_account = (journal.debit_account.id
|
||||
if journal.debit_account else None)
|
||||
clause = ((move.journal == journal.id)
|
||||
& (((line.credit != Null)
|
||||
& (line.account == credit_account))
|
||||
| ((line.debit != Null)
|
||||
& (line.account == debit_account))))
|
||||
if accounts is None:
|
||||
accounts = clause
|
||||
else:
|
||||
accounts |= clause
|
||||
|
||||
query = line.join(move, 'LEFT', condition=line.move == move.id
|
||||
).select(move.journal, Sum(line.debit), Sum(line.credit),
|
||||
where=where & red_sql & accounts,
|
||||
group_by=move.journal)
|
||||
cursor.execute(*query)
|
||||
for journal_id, debit, credit in cursor.fetchall():
|
||||
# SQLite uses float for SUM
|
||||
if not isinstance(debit, Decimal):
|
||||
debit = Decimal(str(debit))
|
||||
if not isinstance(credit, Decimal):
|
||||
credit = Decimal(str(credit))
|
||||
result['debit'][journal_id] = debit
|
||||
result['credit'][journal_id] = credit
|
||||
result['balance'][journal_id] = debit - credit
|
||||
return result
|
||||
|
||||
|
||||
class OpenJournalCash(Wizard):
|
||||
'Open Journal Cash'
|
||||
__name__ = 'account.journal.open_cash'
|
||||
start = StateView('account.journal.open_cash.start',
|
||||
'account.journal_open_cash_start_view_form', [
|
||||
Button('Cancel', 'end', 'tryton-cancel'),
|
||||
Button('Open', 'open_', 'tryton-ok', default=True),
|
||||
])
|
||||
open_ = StateAction('account.act_journal_open_cash')
|
||||
|
||||
def do_open_(self, action):
|
||||
pool = Pool()
|
||||
Lang = pool.get('ir.lang')
|
||||
|
||||
lang, = Lang.search([
|
||||
('code', '=', Transaction().language),
|
||||
])
|
||||
|
||||
action['pyson_context'] = PYSONEncoder().encode({
|
||||
'start_date': self.start.start_date,
|
||||
'end_date': self.start.end_date,
|
||||
})
|
||||
action['name'] += ' %s - %s' % (
|
||||
Lang.strftime(self.start.start_date, lang.code, lang.date),
|
||||
Lang.strftime(self.start.end_date, lang.code, lang.date))
|
||||
return action, {}
|
||||
|
||||
|
||||
class OpenJournalCashStart(ModelView):
|
||||
'Open Journal Cash'
|
||||
__name__ = 'account.journal.open_cash.start'
|
||||
start_date = fields.Date('Start Date', required=True)
|
||||
end_date = fields.Date('End Date', required=True)
|
||||
|
||||
@classmethod
|
||||
def default_start_date(cls):
|
||||
return Pool().get('ir.date').today()
|
||||
default_end_date = default_start_date
|
||||
|
||||
|
||||
class JournalPeriod(ModelSQL, ModelView):
|
||||
'Journal - Period'
|
||||
|
||||
+33
@@ -161,6 +161,13 @@ this repository contains the full copyright notices and license terms. -->
|
||||
<field name="type">tree</field>
|
||||
<field name="name">journal_tree</field>
|
||||
</record>
|
||||
<record model="ir.ui.view" id="journal_view_list_cash">
|
||||
<field name="model">account.journal</field>
|
||||
<field name="priority" eval="20"/>
|
||||
<field name="type">tree</field>
|
||||
<field name="name">journal_list_cash</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.action.act_window" id="act_journal_form">
|
||||
<field name="name">Journals</field>
|
||||
<field name="res_model">account.journal</field>
|
||||
@@ -178,6 +185,32 @@ this repository contains the full copyright notices and license terms. -->
|
||||
<menuitem parent="menu_journal_configuration"
|
||||
action="act_journal_form" id="menu_journal_form"/>
|
||||
|
||||
<record model="ir.ui.view" id="journal_open_cash_start_view_form">
|
||||
<field name="model">account.journal.open_cash.start</field>
|
||||
<field name="type">form</field>
|
||||
<field name="name">journal_open_cash_start</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.action.wizard" id="wizard_journal_open_cash">
|
||||
<field name="name">Open Journal Cash</field>
|
||||
<field name="wiz_name">account.journal.open_cash</field>
|
||||
</record>
|
||||
<menuitem parent="menu_reporting" action="wizard_journal_open_cash"
|
||||
id="menu_journal_open_cash" icon="tryton-list"
|
||||
name="Journals Cash"/>
|
||||
|
||||
<record model="ir.action.act_window" id="act_journal_open_cash">
|
||||
<field name="name">Journals Cash</field>
|
||||
<field name="res_model">account.journal</field>
|
||||
<field name="domain" eval="[('type', '=', 'cash')]" pyson="1"/>
|
||||
</record>
|
||||
<record model="ir.action.act_window.view"
|
||||
id="act_journal_open_cash_view1">
|
||||
<field name="sequence" eval="10"/>
|
||||
<field name="view" ref="journal_view_list_cash"/>
|
||||
<field name="act_window" ref="act_journal_open_cash"/>
|
||||
</record>
|
||||
|
||||
<record model="ir.model.access" id="access_journal">
|
||||
<field name="model" search="[('model', '=', 'account.journal')]"/>
|
||||
<field name="perm_read" eval="True"/>
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
<?xml version="1.0"?>
|
||||
<!-- This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||
this repository contains the full copyright notices and license terms. -->
|
||||
<tree string="Journals">
|
||||
<field name="name"/>
|
||||
<field name="code"/>
|
||||
<field name="debit"/>
|
||||
<field name="credit"/>
|
||||
<field name="balance"/>
|
||||
</tree>
|
||||
@@ -0,0 +1,9 @@
|
||||
<?xml version="1.0"?>
|
||||
<!-- This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||
this repository contains the full copyright notices and license terms. -->
|
||||
<form string="Open Journal Cash">
|
||||
<label name="start_date"/>
|
||||
<field name="start_date"/>
|
||||
<label name="end_date"/>
|
||||
<field name="end_date"/>
|
||||
</form>
|
||||
Reference in New Issue
Block a user