Add balance sheet and modify account type to use a tree structure

This commit is contained in:
Cédric Krier
2008-04-03 17:14:00 +02:00
parent ee36aa0c05
commit f271d71e68
3 changed files with 383 additions and 69 deletions
+178 -21
View File
@@ -5,26 +5,86 @@ from trytond.osv.orm import ID_MAX, exclude
from trytond.wizard import Wizard, WizardOSV
from trytond.report import Report
from decimal import Decimal
import datetime
import time
import locale
import os
from trytond.report.report import _LOCALE2WIN32
class Type(OSV):
'Account Type'
_name = 'account.account.type'
_order = 'code'
_order = 'sequence, id'
_description = __doc__
name = fields.Char('Name', size=None, required=True, translate=True)
code = fields.Char('Code', size=None, required=True)
code = fields.Char('Code', size=None)
parent = fields.Many2One('account.account.type', 'Parent')
childs = fields.One2Many('account.account.type', 'parent', 'Childs')
sequence = fields.Integer('Sequence', required=True,
help='Use to order the account type')
#TODO add constraint (only for end level)
account_type = fields.Boolean('Account Type',
help='Can be use as type for account')
partner_account = fields.Boolean('Partner account')
def __init__(self):
super(Type, self).__init__()
self._sql_constraints += [
('code_uniq', 'UNIQUE(code)', 'Code must be unique!'),
]
#TODO fix digits depend of the currency
amount = fields.Function('get_amount', digits=(16, 2), string='Amount')
def default_partner_account(self, cursor, user, context=None):
return False
def default_sequence(self, cursor, user, context=None):
cursor.execute('SELECT MAX(sequence) ' \
'FROM "' + self._table + '"')
res = cursor.fetchone()
if res:
return res[0]
return 0
def default_account_type(self, cursor, user, context=None):
return False
def get_amount(self, cursor, user, ids, name, arg, context=None):
company_obj = self.pool.get('company.company')
account_obj = self.pool.get('account.account')
currency_obj = self.pool.get('account.currency')
if context is None:
context = {}
res = {}
for type_id in ids:
res[type_id] = Decimal('0.0')
if not context.get('company'):
return res
company = company_obj.browse(cursor, user, context['company'],
context=context)
child_ids = self.search(cursor, user, [
('parent', 'child_of', ids),
], context=context)
type_sum = {}
for type_id in child_ids:
type_sum[type_id] = Decimal('0.0')
account_ids = account_obj.search(cursor, user, [
('type', 'in', child_ids),
('company', '=', company.id),
], context=context)
for account in account_obj.browse(cursor, user, account_ids,
context=context):
type_sum[account.type.id] += currency_obj.round(cursor, user,
company.currency, account.debit - account.credit)
for type_id in ids:
child_ids = self.search(cursor, user, [
('parent', 'child_of', [type_id]),
], context=context)
for child_id in child_ids:
res[type_id] += type_sum[child_id]
res[type_id] = currency_obj.round(cursor, user,
company.currency, res[type_id])
return res
Type()
@@ -45,7 +105,8 @@ class Account(OSV):
second_currency = fields.Many2One('account.currency', 'Secondary currency',
help='Force all moves for this account \n' \
'to have this secondary currency.')
type = fields.Selection('get_types', 'Type', required=True)
type = fields.Many2One('account.account.type', 'Type', required=True,
domain=[('account_type', '=', True)])
parents = fields.Many2Many('account.account', 'account_account_rel',
'child', 'parent', 'Parents')
childs = fields.Many2Many('account.account', 'account_account_rel',
@@ -87,7 +148,11 @@ class Account(OSV):
return context.get('company', False)
def default_type(self, cursor, user, context=None):
return 'view'
type_obj = self.pool.get('account.account.type')
types = type_obj.search(cursor, user, [
('code', '=', 'view'),
], limit=1, context=context)
return type_obj.name_get(cursor, user, types, context=context)[0]
def default_reconcile(self, cursor, user, context=None):
return False
@@ -131,12 +196,6 @@ class Account(OSV):
res[i] = False
return res
def get_types(self, cursor, user, context=None):
type_obj = self.pool.get('account.account.type')
type_ids = type_obj.search(cursor, user, [], context=context)
types = type_obj.browse(cursor, user, type_ids, context=context)
return [(x.code, x.name) for x in types]
def get_balance(self, cursor, user, ids, name, arg, context=None):
res = {}
company_obj = self.pool.get('company.company')
@@ -152,7 +211,9 @@ class Account(OSV):
'FROM account_account a ' \
'LEFT JOIN account_move_line l ' \
'ON (a.id = l.account) ' \
'WHERE a.type != \'view\' ' \
'JOIN account_account_type t ' \
'ON (a.type = t.id) ' \
'WHERE t.code != \'view\' ' \
'AND a.id IN (' + \
','.join(['%s' for x in all_ids]) + ') ' \
'AND ' + line_query + ' ' \
@@ -201,7 +262,9 @@ class Account(OSV):
'FROM account_account a ' \
'LEFT JOIN account_move_line l ' \
'ON (a.id = l.account) ' \
'WHERE a.type != \'view\' ' \
'JOIN account_account_type t ' \
'ON (a.type = t.id) ' \
'WHERE t.code != \'view\' ' \
'AND a.id IN (' + \
','.join(['%s' for x in ids]) + ') ' \
'AND ' + line_query + ' ' \
@@ -342,7 +405,7 @@ class Partner(OSV):
account_payable = fields.Property('account.account', type='many2one',
relation='account.account', string='Account Payable',
group_name='Accounting Properties', view_load=True,
domain="[('type', '=', 'payable'), ('company', '=', company)]",
domain="[('type.code', '=', 'payable'), ('company', '=', company)]",
states={
'required': "company",
'invisible': "not company",
@@ -350,7 +413,7 @@ class Partner(OSV):
account_receivable = fields.Property('account.account', type='many2one',
relation='account.account', string='Account Receivable',
group_name='Accounting Properties', view_load=True,
domain="[('type', '=', 'receivable'), ('company', '=', company)]",
domain="[('type.code', '=', 'receivable'), ('company', '=', company)]",
states={
'required': "company",
'invisible': "not company",
@@ -636,7 +699,7 @@ class TrialBalance(Report):
datas['form']['company'], context=context)
account_ids = account_obj.search(cursor, user, [
('type', '!=', 'view'),
('type.code', '!=', 'view'),
], context=context)
start_period_ids = [0]
@@ -668,6 +731,7 @@ class TrialBalance(Report):
ctx = context.copy()
ctx['fiscalyear'] = datas['form']['fiscalyear']
ctx['periods'] = end_period_ids
ctx['posted'] = datas['form']['posted']
accounts = account_obj.browse(cursor, user, account_ids,
context=ctx)
@@ -692,3 +756,96 @@ class TrialBalance(Report):
return amount
TrialBalance()
class OpenBalanceSheet(WizardOSV):
_name = 'account.account.open_balance_sheet.init'
date = fields.Date('Date', required=True)
company = fields.Many2One('company.company', 'Company', required=True)
posted = fields.Boolean('Posted Move', help='Only posted move')
def default_date(self, cursor, user, context=None):
return datetime.date.today()
def default_company(self, cursor, user, context=None):
if context is None:
context = {}
company_obj = self.pool.get('company.company')
if context.get('company'):
return company_obj.name_get(cursor, user, context['company'],
context=context)[0]
return False
def default_posted(self, cursor, user, context=None):
return False
OpenBalanceSheet()
class OpenBalanceSheet(Wizard):
'Open Balance Sheet'
_name = 'account.account.open_balance_sheet'
states = {
'init': {
'result': {
'type': 'form',
'object': 'account.account.open_balance_sheet.init',
'state': [
('end', 'Cancel', 'gtk-cancel'),
('open', 'Open', 'gtk-ok', True),
],
},
},
'open': {
'result': {
'type': 'action',
'action': '_action_open',
'state': 'end',
},
},
}
def _get_root_codes(self, cursor, user, data, context=None):
return ('asset', 'liability', 'equity')
def _action_open(self, cursor, user, data, context=None):
if context is None:
context = {}
model_data_obj = self.pool.get('ir.model.data')
act_window_obj = self.pool.get('ir.action.act_window')
company_obj = self.pool.get('company.company')
company = company_obj.browse(cursor, user, data['form']['company'],
context=context)
lang = context.get('language', False) or 'en_US'
try:
if os.name == 'nt':
locale.setlocale(locale.LC_ALL,
_LOCALE2WIN32.get(lang, lang) + '.' + encoding)
else:
locale.setlocale(locale.LC_ALL, lang + '.' + encoding)
except:
pass
date = time.strptime(str(data['form']['date']), '%Y-%m-%d')
date = time.strftime(locale.nl_langinfo(locale.D_FMT).\
replace('%y', '%Y'), date)
model_data_ids = model_data_obj.search(cursor, user, [
('fs_id', '=', 'act_account_balance_sheet_tree'),
('module', '=', 'account'),
], limit=1, context=context)
model_data = model_data_obj.browse(cursor, user, model_data_ids[0],
context=context)
res = act_window_obj.read(cursor, user, model_data.db_id, context=context)
res['context'] = str({
'date': data['form']['date'],
'posted': data['form']['posted'],
'company': data['form']['company'],
})
res['domain'] = res['domain'][:-1] + ', ' + \
str(('code', 'in', self._get_root_codes(cursor, user, data,
context=context))) + res['domain'][-1]
res['name'] = res['name'] + ' - '+ date + ' - ' + company.name
return res
OpenBalanceSheet()
+159 -39
View File
@@ -36,6 +36,12 @@
<field name="name"/>
<label name="code"/>
<field name="code"/>
<label name="parent"/>
<field name="parent"/>
<label name="sequence"/>
<field name="sequence"/>
<label name="account_type"/>
<field name="account_type"/>
<label name="partner_account"/>
<field name="partner_account"/>
</form>
@@ -45,11 +51,13 @@
<record model="ir.ui.view" id="account_type_view_tree">
<field name="model">account.account.type</field>
<field name="type">tree</field>
<field name="field_childs">childs</field>
<field name="arch" type="xml">
<![CDATA[
<tree string="Account Types">
<field name="name" select="1"/>
<field name="code" select="1"/>
<field name="account_type" select="2"/>
<field name="partner_account" select="2"/>
</tree>
]]>
@@ -72,6 +80,19 @@
</record>
<menuitem parent="menu_general_account_configuration"
action="act_account_type_form" id="menu_account_type_form"/>
<record model="ir.action.act_window" id="act_account_type_tree">
<field name="name">Account Types</field>
<field name="res_model">account.account.type</field>
<field name="view_type">tree</field>
<field name="domain">[('parent', '=', False)]</field>
</record>
<record model="ir.action.act_window.view" id="act_account_type_tree_view1">
<field name="sequence" eval="10"/>
<field name="view" ref="account_type_view_tree"/>
<field name="act_window" ref="act_account_type_tree"/>
</record>
<menuitem parent="menu_account_type_form"
action="act_account_type_tree" id="menu_account_type_tree"/>
<record model="ir.model.access" id="access_account_type">
<field name="model" search="[('model', '=', 'account.account.type')]"/>
<field name="perm_read" eval="True"/>
@@ -87,47 +108,95 @@
<field name="perm_create" eval="True"/>
<field name="perm_unlink" eval="True"/>
</record>
<record model="account.account.type" id="account_type_receivable">
<field name="name">Receivable</field>
<field name="code">receivable</field>
<field name="partner_account" eval="True"/>
</record>
<record model="account.account.type" id="account_type_payable">
<field name="name">Payable</field>
<field name="code">payable</field>
<field name="partner_account" eval="True"/>
</record>
<record model="account.account.type" id="account_type_view">
<field name="name">View</field>
<field name="code">view</field>
</record>
<record model="account.account.type" id="account_type_income">
<field name="name">Income</field>
<field name="code">income</field>
</record>
<record model="account.account.type" id="account_type_expense">
<field name="name">Expense</field>
<field name="code">expense</field>
</record>
<record model="account.account.type" id="account_type_tax">
<field name="name">Tax</field>
<field name="code">tax</field>
</record>
<record model="account.account.type" id="account_type_cash">
<field name="name">Cash</field>
<field name="code">cash</field>
</record>
<record model="account.account.type" id="account_type_asset">
<field name="name">Asset</field>
<field name="code">asset</field>
<field name="sequence" eval="10"/>
</record>
<record model="account.account.type" id="account_type_asset_current">
<field name="name">Current</field>
<field name="parent" ref="account_type_asset"/>
<field name="sequence" eval="10"/>
</record>
<record model="account.account.type" id="account_type_asset_current_cash">
<field name="name">Cash</field>
<field name="code">cash</field>
<field name="parent" ref="account_type_asset_current"/>
<field name="sequence" eval="10"/>
<field name="account_type" eval="True"/>
</record>
<record model="account.account.type" id="account_type_asset_current_receivable">
<field name="name">Receivable</field>
<field name="code">receivable</field>
<field name="parent" ref="account_type_asset_current"/>
<field name="partner_account" eval="True"/>
<field name="sequence" eval="20"/>
<field name="account_type" eval="True"/>
</record>
<record model="account.account.type" id="account_type_asset_long_term">
<field name="name">Long-term</field>
<field name="parent" ref="account_type_asset"/>
<field name="sequence" eval="20"/>
</record>
<record model="account.account.type" id="account_type_liability">
<field name="name">Liability</field>
<field name="code">liability</field>
<field name="sequence" eval="20"/>
</record>
<record model="account.account.type" id="account_type_liability_current">
<field name="name">Current</field>
<field name="parent" ref="account_type_liability"/>
<field name="sequence" eval="10"/>
</record>
<record model="account.account.type" id="account_type_liability_current_payable">
<field name="name">Payable</field>
<field name="code">payable</field>
<field name="parent" ref="account_type_liability_current"/>
<field name="partner_account" eval="True"/>
<field name="sequence" eval="10"/>
<field name="account_type" eval="True"/>
</record>
<record model="account.account.type" id="account_type_liability_current_tax">
<field name="name">Tax</field>
<field name="code">tax</field>
<field name="parent" ref="account_type_liability_current"/>
<field name="sequence" eval="20"/>
<field name="account_type" eval="True"/>
</record>
<record model="account.account.type" id="account_type_liability_long_term">
<field name="name">Long-term</field>
<field name="parent" ref="account_type_liability"/>
<field name="sequence" eval="20"/>
</record>
<record model="account.account.type" id="account_type_equity">
<field name="name">Equity</field>
<field name="code">equity</field>
<field name="sequence" eval="30"/>
<field name="account_type" eval="True"/>
</record>
<record model="account.account.type" id="account_type_revenue">
<field name="name">Revenue</field>
<field name="code">revenue</field>
<field name="sequence" eval="40"/>
<field name="account_type" eval="True"/>
</record>
<record model="account.account.type" id="account_type_expense">
<field name="name">Expense</field>
<field name="code">expense</field>
<field name="sequence" eval="50"/>
<field name="account_type" eval="True"/>
</record>
<record model="account.account.type" id="account_type_view">
<field name="name">View</field>
<field name="code">view</field>
<field name="sequence" eval="60"/>
<field name="account_type" eval="True"/>
</record>
<record model="account.account.type" id="account_type_closed">
<field name="name">Closed</field>
<field name="code">closed</field>
<field name="sequence" eval="70"/>
<field name="account_type" eval="True"/>
</record>
<record model="ir.ui.view" id="account_view_form">
@@ -147,7 +216,7 @@
<label name="company"/>
<field name="company"/>
<label name="type"/>
<field name="type"/>
<field name="type" widget="selection"/>
<label name="currency"/>
<field name="currency"/>
<label name="second_currency"/>
@@ -268,12 +337,12 @@
<record model="account.account" id="account_root">
<field name="name">Root</field>
<field name="close_method">none</field>
<field name="type">view</field>
<field name="type" ref="account_type_view"/>
<field name="company" ref="company.main"/>
</record>
<record model="account.account" id="account_receivable">
<field name="name">Main Receivable</field>
<field name="type">receivable</field>
<field name="type" ref="account_type_asset_current_receivable"/>
<field name="company" ref="company.main"/>
<field name="reconcile" eval="True"/>
<field name="close_method">unreconciled</field>
@@ -281,27 +350,27 @@
</record>
<record model="account.account" id="account_payable">
<field name="name">Main Payable</field>
<field name="type">payable</field>
<field name="type" ref="account_type_liability_current_payable"/>
<field name="company" ref="company.main"/>
<field name="reconcile" eval="True"/>
<field name="close_method">unreconciled</field>
<field name="parents" eval="[('add', ref('account_root'))]"/>
</record>
<record model="account.account" id="account_income">
<field name="name">Main Income</field>
<field name="type">income</field>
<record model="account.account" id="account_revenue">
<field name="name">Main Revenue</field>
<field name="type" ref="account_type_revenue"/>
<field name="company" ref="company.main"/>
<field name="parents" eval="[('add', ref('account_root'))]"/>
</record>
<record model="account.account" id="account_expense">
<field name="name">Main Expense</field>
<field name="type">expense</field>
<field name="type" ref="account_type_expense"/>
<field name="company" ref="company.main"/>
<field name="parents" eval="[('add', ref('account_root'))]"/>
</record>
<record model="account.account" id="account_cash">
<field name="name">Main Cash</field>
<field name="type">cash</field>
<field name="type" ref="account_type_asset_current_cash"/>
<field name="company" ref="company.main"/>
<field name="parents" eval="[('add', ref('account_root'))]"/>
</record>
@@ -406,5 +475,56 @@
<field name="report_name">account.account.trial_balance</field>
<field name="report">account/trial_balance.odt</field>
</record>
<record model="ir.ui.view" id="open_balance_sheet_init_view_form">
<field name="model">account.account.open_balance_sheet.init</field>
<field name="type">form</field>
<field name="arch" type="xml">
<![CDATA[
<form string="Open Balance Sheet" col="2">
<label name="date"/>
<field name="date"/>
<label name="company"/>
<field name="company"/>
<label name="posted"/>
<field name="posted"/>
</form>
]]>
</field>
</record>
<record model="ir.ui.view" id="account_balance_sheet_view_tree">
<field name="model">account.account.type</field>
<field name="type">tree</field>
<field name="field_childs">childs</field>
<field name="arch" type="xml">
<![CDATA[
<tree string="Balance Sheet">
<field name="name"/>
<field name="amount"/>
</tree>
]]>
</field>
</record>
<record model="ir.action.act_window" id="act_account_balance_sheet_tree">
<field name="name">Balance Sheet</field>
<field name="res_model">account.account.type</field>
<field name="view_type">tree</field>
<field name="domain">[('parent', '=', False)]</field>
</record>
<record model="ir.action.act_window.view" id="act_balance_sheet_view1">
<field name="sequence" eval="10"/>
<field name="view" ref="account_balance_sheet_view_tree"/>
<field name="act_window" ref="act_account_balance_sheet_tree"/>
</record>
<record model="ir.action.wizard" id="wizard_open_balance_sheet">
<field name="name">Open Balance Sheet</field>
<field name="wiz_name">account.account.open_balance_sheet</field>
</record>
<menuitem parent="menu_reporting" action="wizard_open_balance_sheet"
id="menu_print_balance_sheet" icon="STOCK_INDENT"
name="Balance Sheet"/>
</data>
</tryton>
+46 -9
View File
@@ -332,7 +332,7 @@ class Line(OSV):
on_change=['account', 'debit', 'credit', 'tax_lines',
'journal', 'move'])
account = fields.Many2One('account.account', 'Account', required=True,
domain=[('type', '!=', 'view'), ('type', '!=', 'closed')],
domain=[('type.code', '!=', 'view'), ('type.code', '!=', 'closed')],
select=1,
on_change=['account', 'debit', 'credit', 'tax_lines',
'journal', 'move'])
@@ -786,12 +786,44 @@ class Line(OSV):
def query_get(self, cursor, user, obj='l', context=None):
'''
Return SQL clause for account move line.
Return SQL clause for account move line depending of the context.
obj is the SQL alias of the account_move_line in the query.
'''
fiscalyear_obj = self.pool.get('account.fiscalyear')
if context is None:
context = {}
if context.get('date'):
fiscalyear_ids = fiscalyear_obj.search(cursor, user, [
('start_date', '<=', context['date']),
('end_date', '>=', context['date']),
], limit=1, context=context)
if context.get('posted'):
return obj + '.active ' \
'AND ' + obj + '.state != \'draft\' ' \
'AND ' + obj + '.move IN (' \
'SELECT m.id FROM account_move AS m, ' \
'account_period AS p ' \
'WHERE m.period = p.id ' \
'AND p.fiscalyear = ' + \
str(fiscalyear_ids[0]) + ' ' \
'AND m.date <= \'' + \
str(context['date']) + '\' ' \
'AND m.state = \'posted\' ' \
')'
else:
return obj + '.active ' \
'AND ' + obj + '.state != \'draft\' ' \
'AND ' + obj + '.move IN (' \
'SELECT m.id FROM account_move AS m, ' \
'account_period AS p ' \
'WHERE m.period = p.id ' \
'AND p.fiscalyear = ' + \
str(fiscalyear_ids[0]) + ' ' \
'AND m.date <= \'' + \
str(context['date']) + '\'' \
')'
if not context.get('fiscalyear', False):
fiscalyear_ids = fiscalyear_obj.search(cursor, user, [
('state', '=', 'open'),
@@ -799,6 +831,7 @@ class Line(OSV):
fiscalyear_clause = (','.join([str(x) for x in fiscalyear_ids])) or '0'
else:
fiscalyear_clause = '%s' % int(context.get('fiscalyear'))
if context.get('periods', False):
ids = ','.join([str(int(x)) for x in context['periods']])
if context.get('posted'):
@@ -848,7 +881,7 @@ class Line(OSV):
def check_account(self, cursor, user, ids):
for line in self.browse(cursor, user, ids):
if line.account.type in ('view', 'closed'):
if line.account.type.code in ('view', 'closed'):
return False
if not line.account.active:
return False
@@ -1255,7 +1288,7 @@ class ReconcileLinesWriteOff(WizardOSV):
journal = fields.Many2One('account.journal', 'Journal', required=True)
period = fields.Many2One('account.period', 'Period', required=True)
account = fields.Many2One('account.account', 'Account', required=True,
domain=[('type', '!=', 'view'), ('type', '!=', 'closed')])
domain=[('type.code', '!=', 'view'), ('type.code', '!=', 'closed')])
def default_period(self, cursor, user, context=None):
period_obj = self.pool.get('account.period')
@@ -1374,7 +1407,7 @@ UnreconcileLines()
class OpenReconcileLinesInit(WizardOSV):
_name = 'account.move.open_reconcile_lines.init'
account = fields.Many2One('account.account', 'Account', required=True,
domain=[('type', '!=', 'view'), ('reconcile', '=', True)])
domain=[('type.code', '!=', 'view'), ('reconcile', '=', True)])
OpenReconcileLinesInit()
@@ -1473,10 +1506,12 @@ class Partner(OSV):
cursor.execute('SELECT l.partner, ' \
'SUM((COALESCE(l.debit, 0) - COALESCE(l.credit, 0))) ' \
'FROM account_move_line AS l, ' \
'account_account AS a ' \
'account_account AS a, ' \
'account_account_type AS t ' \
'WHERE a.id = l.account ' \
'AND a.active ' \
'AND a.type = %s ' \
'AND a.type = t.id ' \
'AND t.code = %s ' \
'AND l.partner IN ' \
'(' + ','.join(['%s' for x in ids]) + ') ' \
'AND l.reconciliation IS NULL ' \
@@ -1520,10 +1555,12 @@ class Partner(OSV):
cursor.execute('SELECT l.partner ' \
'FROM account_move_line AS l, ' \
'account_account AS a ' \
'account_account AS a, ' \
'account_account_type AS t ' \
'WHERE a.id = l.account ' \
'AND a.active ' \
'AND a.type = %s ' \
'AND a.type = t.id ' \
'AND t.code = %s ' \
'AND l.partner IS NOT NULL ' \
'AND l.reconciliation IS NOT NULL ' \
'AND ' + line_query + ' ' \