It breaks the record rules if user create company from this wizard and it is not allow to create chart template so selection widget prevent this Add default value for company
2440 lines
95 KiB
Python
2440 lines
95 KiB
Python
#This file is part of Tryton. The COPYRIGHT file at the top level of
|
|
#this repository contains the full copyright notices and license terms.
|
|
"Account"
|
|
from trytond.model import ModelView, ModelSQL, fields
|
|
from trytond.wizard import Wizard
|
|
from trytond.report import Report
|
|
from trytond.tools import reduce_ids
|
|
from trytond.pyson import Equal, Eval, Not, PYSONEncoder, Date
|
|
from decimal import Decimal
|
|
import datetime
|
|
import time
|
|
import os
|
|
|
|
|
|
class TypeTemplate(ModelSQL, ModelView):
|
|
'Account Type Template'
|
|
_name = 'account.account.type.template'
|
|
_description = __doc__
|
|
name = fields.Char('Name', required=True, translate=True)
|
|
parent = fields.Many2One('account.account.type.template', 'Parent',
|
|
ondelete="RESTRICT")
|
|
childs = fields.One2Many('account.account.type.template', 'parent', 'Children')
|
|
sequence = fields.Integer('Sequence', required=True)
|
|
balance_sheet = fields.Boolean('Balance Sheet')
|
|
income_statement = fields.Boolean('Income Statement')
|
|
display_balance = fields.Selection([
|
|
('debit-credit', 'Debit - Credit'),
|
|
('credit-debit', 'Credit - Debit'),
|
|
], 'Display Balance', required=True)
|
|
|
|
def __init__(self):
|
|
super(TypeTemplate, self).__init__()
|
|
self._order.insert(0, ('sequence', 'ASC'))
|
|
|
|
def default_balance_sheet(self, cursor, user, context=None):
|
|
return False
|
|
|
|
def default_income_statement(self, cursor, user, context=None):
|
|
return False
|
|
|
|
def default_display_balance(self, cursor, user, context=None):
|
|
return 'debit-credit'
|
|
|
|
def get_rec_name(self, cursor, user, ids, name, arg, context=None):
|
|
if not ids:
|
|
return {}
|
|
res = {}
|
|
def _name(type):
|
|
if type.parent:
|
|
return _name(type.parent) + '\\' + type.name
|
|
else:
|
|
return type.name
|
|
for type in self.browse(cursor, user, ids, context=context):
|
|
res[type.id] = _name(type)
|
|
return res
|
|
|
|
def _get_type_value(self, cursor, user, template, context=None,
|
|
type=None):
|
|
'''
|
|
Set the values for account creation.
|
|
|
|
:param cursor: the database cursor
|
|
:param user: the user id
|
|
:param template: the BrowseRecord of the template
|
|
:param context: the context
|
|
:param type: the BrowseRecord of the type to update
|
|
:return: a dictionary with account fields as key and values as value
|
|
'''
|
|
res = {}
|
|
if not type or type.name != template.name:
|
|
res['name'] = template.name
|
|
if not type or type.sequence != template.sequence:
|
|
res['sequence'] = template.sequence
|
|
if not type or type.balance_sheet != template.balance_sheet:
|
|
res['balance_sheet'] = template.balance_sheet
|
|
if not type or type.income_statement != template.income_statement:
|
|
res['income_statement'] = template.income_statement
|
|
if not type or type.display_balance != template.display_balance:
|
|
res['display_balance'] = template.display_balance
|
|
if not type or type.template.id != template.id:
|
|
res['template'] = template.id
|
|
return res
|
|
|
|
def create_type(self, cursor, user, template, company_id, context=None,
|
|
template2type=None, parent_id=False):
|
|
'''
|
|
Create recursively types based on template.
|
|
|
|
:param cursor: the database cursor
|
|
:param user: the user id
|
|
:param template: the template id or the BrowseRecord of the template
|
|
used for type creation
|
|
:param company_id: the id of the company for which types are created
|
|
:param context: the context
|
|
:param template2type: a dictionary with template id as key
|
|
and type id as value, used to convert template id
|
|
into type. The dictionary is filled with new types
|
|
:param parent_id: the type id of the parent of the types that must
|
|
be created
|
|
:return: id of the type created
|
|
'''
|
|
type_obj = self.pool.get('account.account.type')
|
|
lang_obj = self.pool.get('ir.lang')
|
|
|
|
if template2type is None:
|
|
template2type = {}
|
|
|
|
if isinstance(template, (int, long)):
|
|
template = self.browse(cursor, user, template, context=context)
|
|
|
|
if template.id not in template2type:
|
|
vals = self._get_type_value(cursor, user, template, context=context)
|
|
vals['company'] = company_id
|
|
vals['parent'] = parent_id
|
|
|
|
new_id = type_obj.create(cursor, user, vals, context=context)
|
|
|
|
prev_lang = template._context.get('language') or 'en_US'
|
|
ctx = context.copy()
|
|
for lang in lang_obj.get_translatable_languages(cursor, user,
|
|
context=context):
|
|
if lang == prev_lang:
|
|
continue
|
|
ctx['language'] = lang
|
|
template.setLang(lang)
|
|
data = {}
|
|
for field in template._columns.keys():
|
|
if template._columns[field].translate:
|
|
data[field] = template[field]
|
|
if data:
|
|
type_obj.write(cursor, user, new_id, data, context=ctx)
|
|
template.setLang(prev_lang)
|
|
template2type[template.id] = new_id
|
|
else:
|
|
new_id = template2type[template.id]
|
|
|
|
new_childs = []
|
|
for child in template.childs:
|
|
new_childs.append(self.create_type(cursor, user, child, company_id,
|
|
context=context, template2type=template2type, parent_id=new_id))
|
|
return new_id
|
|
|
|
TypeTemplate()
|
|
|
|
|
|
class Type(ModelSQL, ModelView):
|
|
'Account Type'
|
|
_name = 'account.account.type'
|
|
_description = __doc__
|
|
name = fields.Char('Name', size=None, required=True, translate=True)
|
|
parent = fields.Many2One('account.account.type', 'Parent',
|
|
ondelete="RESTRICT")
|
|
childs = fields.One2Many('account.account.type', 'parent', 'Children')
|
|
sequence = fields.Integer('Sequence', required=True,
|
|
help='Use to order the account type')
|
|
currency_digits = fields.Function('get_currency_digits', type='integer',
|
|
string='Currency Digits')
|
|
amount = fields.Function('get_amount',
|
|
digits=(16, Eval('currency_digits', 2)),
|
|
string='Amount', depends=['currency_digits'])
|
|
balance_sheet = fields.Boolean('Balance Sheet')
|
|
income_statement = fields.Boolean('Income Statement')
|
|
display_balance = fields.Selection([
|
|
('debit-credit', 'Debit - Credit'),
|
|
('credit-debit', 'Credit - Debit'),
|
|
], 'Display Balance', required=True)
|
|
company = fields.Many2One('company.company', 'Company', required=True,
|
|
ondelete="RESTRICT")
|
|
template = fields.Many2One('account.account.type.template', 'Template')
|
|
|
|
def __init__(self):
|
|
super(Type, self).__init__()
|
|
self._order.insert(0, ('sequence', 'ASC'))
|
|
|
|
def default_balance_sheet(self, cursor, user, context=None):
|
|
return False
|
|
|
|
def default_income_statement(self, cursor, user, context=None):
|
|
return False
|
|
|
|
def default_display_balance(self, cursor, user, context=None):
|
|
return 'debit-credit'
|
|
|
|
def get_currency_digits(self, cursor, user, ids, name, arg, context=None):
|
|
res = {}
|
|
for type in self.browse(cursor, user, ids, context=context):
|
|
res[type.id] = type.company.currency.digits
|
|
return res
|
|
|
|
def get_amount(self, cursor, user, ids, name, arg, context=None):
|
|
account_obj = self.pool.get('account.account')
|
|
currency_obj = self.pool.get('currency.currency')
|
|
|
|
if context is None:
|
|
context = {}
|
|
res = {}
|
|
for type_id in ids:
|
|
res[type_id] = Decimal('0.0')
|
|
|
|
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),
|
|
], context=context)
|
|
for account in account_obj.browse(cursor, user, account_ids,
|
|
context=context):
|
|
type_sum[account.type.id] += currency_obj.round(cursor, user,
|
|
account.company.currency, account.debit - account.credit)
|
|
|
|
types = self.browse(cursor, user, ids, context=context)
|
|
for type in types:
|
|
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,
|
|
type.company.currency, res[type.id])
|
|
if type.display_balance == 'credit-debit':
|
|
res[type.id] = - res[type.id]
|
|
return res
|
|
|
|
def get_rec_name(self, cursor, user, ids, name, arg, context=None):
|
|
if not ids:
|
|
return {}
|
|
res = {}
|
|
def _name(type):
|
|
if type.parent:
|
|
return _name(type.parent) + '\\' + type.name
|
|
else:
|
|
return type.name
|
|
for type in self.browse(cursor, user, ids, context=context):
|
|
res[type.id] = _name(type)
|
|
return res
|
|
|
|
def delete(self, cursor, user, ids, context=None):
|
|
if isinstance(ids, (int, long)):
|
|
ids = [ids]
|
|
type_ids = self.search(cursor, user, [
|
|
('parent', 'child_of', ids),
|
|
], context=context)
|
|
return super(Type, self).delete(cursor, user, type_ids, context=context)
|
|
|
|
def update_type(self, cursor, user, type, context=None, template2type=None):
|
|
'''
|
|
Update recursively types based on template.
|
|
|
|
:param cursor: the database cursor
|
|
:param user: the user id
|
|
:param type: a type id or the BrowseRecord of the type
|
|
:param context: the context
|
|
:param template2type: a dictionary with template id as key
|
|
and type id as value, used to convert template id
|
|
into type. The dictionary is filled with new types
|
|
'''
|
|
template_obj = self.pool.get('account.account.type.template')
|
|
lang_obj = self.pool.get('ir.lang')
|
|
|
|
if template2type is None:
|
|
template2type = {}
|
|
|
|
if isinstance(type, (int, long)):
|
|
type = self.browse(cursor, user, type, context=context)
|
|
|
|
if type.template:
|
|
vals = template_obj._get_type_value(cursor, user, type.template,
|
|
context=context, type=type)
|
|
if vals:
|
|
self.write(cursor, user, type.id, vals, context=context)
|
|
|
|
prev_lang = type._context.get('language') or 'en_US'
|
|
ctx = context.copy()
|
|
for lang in lang_obj.get_translatable_languages(cursor, user,
|
|
context=context):
|
|
if lang == prev_lang:
|
|
continue
|
|
ctx['language'] = lang
|
|
type.setLang(lang)
|
|
data = template_obj._get_type_value(cursor, user,
|
|
type.template, context=ctx, type=type)
|
|
if data:
|
|
self.write(cursor, user, type.id, data, context=ctx)
|
|
type.setLang(prev_lang)
|
|
template2type[type.template.id] = type.id
|
|
|
|
for child in type.childs:
|
|
self.update_type(cursor, user, child, context=context,
|
|
template2type=template2type)
|
|
|
|
Type()
|
|
|
|
|
|
class AccountTemplate(ModelSQL, ModelView):
|
|
'Account Template'
|
|
_name = 'account.account.template'
|
|
_description = __doc__
|
|
|
|
name = fields.Char('Name', size=None, required=True, translate=True,
|
|
select=1)
|
|
code = fields.Char('Code', size=None, select=1)
|
|
type = fields.Many2One('account.account.type.template', 'Type',
|
|
ondelete="RESTRICT",
|
|
states={
|
|
'invisible': Equal(Eval('kind'), 'view'),
|
|
'required': Not(Equal(Eval('kind'), 'view')),
|
|
}, depends=['kind'])
|
|
parent = fields.Many2One('account.account.template', 'Parent', select=1,
|
|
ondelete="RESTRICT")
|
|
childs = fields.One2Many('account.account.template', 'parent', 'Children')
|
|
reconcile = fields.Boolean('Reconcile',
|
|
states={
|
|
'invisible': Equal(Eval('kind'), 'view'),
|
|
}, depends=['kind'])
|
|
kind = fields.Selection([
|
|
('other', 'Other'),
|
|
('payable', 'Payable'),
|
|
('revenue', 'Revenue'),
|
|
('receivable', 'Receivable'),
|
|
('expense', 'Expense'),
|
|
('view', 'View'),
|
|
], 'Kind', required=True)
|
|
deferral = fields.Boolean('Deferral', states={
|
|
'invisible': Equal(Eval('kind'), 'view'),
|
|
}, depends=['kind'])
|
|
|
|
def __init__(self):
|
|
super(AccountTemplate, self).__init__()
|
|
self._constraints += [
|
|
('check_recursion', 'recursive_accounts'),
|
|
]
|
|
self._error_messages.update({
|
|
'recursive_accounts': 'You can not create recursive accounts!',
|
|
})
|
|
self._order.insert(0, ('code', 'ASC'))
|
|
self._order.insert(1, ('name', 'ASC'))
|
|
|
|
def default_kind(self, cursor, user, context=None):
|
|
return 'view'
|
|
|
|
def default_reconcile(self, cursor, user, context=None):
|
|
return False
|
|
|
|
def default_deferral(self, cursor, user, context=None):
|
|
return True
|
|
|
|
def get_rec_name(self, cursor, user, ids, name, arg, context=None):
|
|
if not ids:
|
|
return {}
|
|
res = {}
|
|
for template in self.browse(cursor, user, ids, context=context):
|
|
if template.code:
|
|
res[template.id] = template.code + ' - ' + template.name
|
|
else:
|
|
res[template.id] = template.name
|
|
return res
|
|
|
|
def search_rec_name(self, cursor, user, name, args, context=None):
|
|
args2 = []
|
|
i = 0
|
|
while i < len(args):
|
|
ids = self.search(cursor, user, [
|
|
('code', args[i][1], args[i][2]),
|
|
], limit=1, context=context)
|
|
if ids:
|
|
args2.append(('code', args[i][1], args[i][2]))
|
|
else:
|
|
args2.append((self._rec_name, args[i][1], args[i][2]))
|
|
i += 1
|
|
return args2
|
|
|
|
def _get_account_value(self, cursor, user, template, context=None,
|
|
account=None):
|
|
'''
|
|
Set the values for account creation.
|
|
|
|
:param cursor: the database cursor
|
|
:param user: the user id
|
|
:param template: the BrowseRecord of the template
|
|
:param context: the context
|
|
:param account: the BrowseRecord of the account to update
|
|
:return: a dictionary with account fields as key and values as value
|
|
'''
|
|
res = {}
|
|
if not account or account.name != template.name:
|
|
res['name'] = template.name
|
|
if not account or account.code != template.code:
|
|
res['code'] = template.code
|
|
if not account or account.kind != template.kind:
|
|
res['kind'] = template.kind
|
|
if not account or account.reconcile != template.reconcile:
|
|
res['reconcile'] = template.reconcile
|
|
if not account or account.deferral != template.deferral:
|
|
res['deferral'] = template.deferral
|
|
if not account or account.template.id != template.id:
|
|
res['template'] = template.id
|
|
return res
|
|
|
|
def create_account(self, cursor, user, template, company_id, context=None,
|
|
template2account=None, template2type=None, parent_id=False):
|
|
'''
|
|
Create recursively accounts based on template.
|
|
|
|
:param cursor: the database cursor
|
|
:param user: the user id
|
|
:param template: the template id or the BrowseRecord of template
|
|
used for account creation
|
|
:param company_id: the id of the company for which accounts
|
|
are created
|
|
:param context: the context
|
|
:param template2account: a dictionary with template id as key
|
|
and account id as value, used to convert template id
|
|
into account. The dictionary is filled with new accounts
|
|
:param template2type: a dictionary with type template id as key
|
|
and type id as value, used to convert type template id
|
|
into type.
|
|
:param parent_id: the account id of the parent of the accounts
|
|
that must be created
|
|
:return: id of the account created
|
|
'''
|
|
account_obj = self.pool.get('account.account')
|
|
lang_obj = self.pool.get('ir.lang')
|
|
|
|
if template2account is None:
|
|
template2account = {}
|
|
|
|
if template2type is None:
|
|
template2type = {}
|
|
|
|
if isinstance(template, (int, long)):
|
|
template = self.browse(cursor, user, template, context=context)
|
|
|
|
if template.id not in template2account:
|
|
vals = self._get_account_value(cursor, user, template, context=context)
|
|
vals['company'] = company_id
|
|
vals['parent'] = parent_id
|
|
vals['type'] = template2type.get(template.type.id, False)
|
|
|
|
new_id = account_obj.create(cursor, user, vals, context=context)
|
|
|
|
prev_lang = template._context.get('language') or 'en_US'
|
|
ctx = context.copy()
|
|
for lang in lang_obj.get_translatable_languages(cursor, user,
|
|
context=context):
|
|
if lang == prev_lang:
|
|
continue
|
|
ctx['language'] = lang
|
|
template.setLang(lang)
|
|
data = {}
|
|
for field in template._columns.keys():
|
|
if template._columns[field].translate:
|
|
data[field] = template[field]
|
|
if data:
|
|
account_obj.write(cursor, user, new_id, data, context=ctx)
|
|
template.setLang(prev_lang)
|
|
template2account[template.id] = new_id
|
|
else:
|
|
new_id = template2account[template.id]
|
|
|
|
new_childs = []
|
|
for child in template.childs:
|
|
new_childs.append(self.create_account(cursor, user, child,
|
|
company_id, context=context, template2account=template2account,
|
|
template2type=template2type, parent_id=new_id))
|
|
return new_id
|
|
|
|
def update_account_taxes(self, cursor, user, template, template2account,
|
|
template2tax, context=None, template_done=None):
|
|
'''
|
|
Update recursively account taxes based on template.
|
|
|
|
:param cursor: the database cursor
|
|
:param user: the user id
|
|
:param template: the template id or the BrowseRecord of template
|
|
used for account creation
|
|
:param template2account: a dictionary with template id as key
|
|
and account id as value, used to convert template id into
|
|
account.
|
|
:param template2tax: a dictionary with tax template id as key
|
|
and tax id as value, used to convert tax template id into
|
|
tax.
|
|
:param context: the context
|
|
:param template_done: a list of template id already updated.
|
|
The list is filled.
|
|
'''
|
|
account_obj = self.pool.get('account.account')
|
|
|
|
if template2account is None:
|
|
template2account = {}
|
|
if template2tax is None:
|
|
template2tax = {}
|
|
if template_done is None:
|
|
template_done = []
|
|
|
|
if isinstance(template, (int, long)):
|
|
template = self.browse(cursor, user, template, context=context)
|
|
|
|
if template.id not in template_done:
|
|
if template.taxes:
|
|
account_obj.write(cursor, user, template2account[template.id], {
|
|
'taxes': [
|
|
('add', template2tax[x.id]) for x in template.taxes],
|
|
}, context=context)
|
|
template_done.append(template.id)
|
|
|
|
for child in template.childs:
|
|
self.update_account_taxes(cursor, user, child, template2account,
|
|
template2tax, context=context, template_done=template_done)
|
|
|
|
AccountTemplate()
|
|
|
|
|
|
class Account(ModelSQL, ModelView):
|
|
'Account'
|
|
_name = 'account.account'
|
|
_description = __doc__
|
|
|
|
name = fields.Char('Name', size=None, required=True, translate=True,
|
|
select=1)
|
|
code = fields.Char('Code', size=None, select=1)
|
|
active = fields.Boolean('Active', select=2)
|
|
company = fields.Many2One('company.company', 'Company', required=True,
|
|
ondelete="RESTRICT")
|
|
currency = fields.Function('get_currency', type='many2one',
|
|
relation='currency.currency', string='Currency')
|
|
currency_digits = fields.Function('get_currency_digits', type='integer',
|
|
string='Currency Digits')
|
|
second_currency = fields.Many2One('currency.currency', 'Secondary currency',
|
|
help='Force all moves for this account \n' \
|
|
'to have this secondary currency.', ondelete="RESTRICT")
|
|
type = fields.Many2One('account.account.type', 'Type', ondelete="RESTRICT",
|
|
states={
|
|
'invisible': Equal(Eval('kind'), 'view'),
|
|
'required': Not(Equal(Eval('kind'), 'view')),
|
|
}, depends=['kind'])
|
|
parent = fields.Many2One('account.account', 'Parent', select=1,
|
|
left="left", right="right", ondelete="RESTRICT")
|
|
left = fields.Integer('Left', required=True, select=1)
|
|
right = fields.Integer('Right', required=True, select=1)
|
|
childs = fields.One2Many('account.account', 'parent', 'Children')
|
|
balance = fields.Function('get_balance',
|
|
digits=(16, Eval('currency_digits', 2)),
|
|
string='Balance', depends=['currency_digits'])
|
|
credit = fields.Function('get_credit_debit',
|
|
digits=(16, Eval('currency_digits', 2)),
|
|
string='Credit', depends=['currency_digits'])
|
|
debit = fields.Function('get_credit_debit',
|
|
digits=(16, Eval('currency_digits', 2)),
|
|
string='Debit', depends=['currency_digits'])
|
|
reconcile = fields.Boolean('Reconcile',
|
|
help='Allow move lines of this account \n' \
|
|
'to be reconciled.',
|
|
states={
|
|
'invisible': Equal(Eval('kind'), 'view'),
|
|
}, depends=['kind'])
|
|
note = fields.Text('Note')
|
|
kind = fields.Selection([
|
|
('other', 'Other'),
|
|
('payable', 'Payable'),
|
|
('revenue', 'Revenue'),
|
|
('receivable', 'Receivable'),
|
|
('expense', 'Expense'),
|
|
('view', 'View'),
|
|
], 'Kind', required=True)
|
|
deferral = fields.Boolean('Deferral', states={
|
|
'invisible': Equal(Eval('kind'), 'view'),
|
|
}, depends=['kind'])
|
|
deferrals = fields.One2Many('account.account.deferral', 'account',
|
|
'Deferrals', readonly=True, states={
|
|
'invisible': Equal(Eval('kind'), 'view'),
|
|
}, depends=['kind'])
|
|
template = fields.Many2One('account.account.template', 'Template')
|
|
|
|
def __init__(self):
|
|
super(Account, self).__init__()
|
|
self._constraints += [
|
|
('check_recursion', 'recursive_accounts'),
|
|
]
|
|
self._error_messages.update({
|
|
'recursive_accounts': 'You can not create recursive accounts!',
|
|
'delete_account_containing_move_lines': 'You can not delete ' \
|
|
'accounts containing move lines!',
|
|
})
|
|
self._sql_error_messages.update({
|
|
'parent_fkey': 'You can not delete accounts ' \
|
|
'that have children!',
|
|
})
|
|
self._order.insert(0, ('code', 'ASC'))
|
|
self._order.insert(1, ('name', 'ASC'))
|
|
|
|
def default_left(self, cursor, user, context=None):
|
|
return 0
|
|
|
|
def default_right(self, cursor, user, context=None):
|
|
return 0
|
|
|
|
def default_active(self, cursor, user, context=None):
|
|
return True
|
|
|
|
def default_company(self, cursor, user, context=None):
|
|
if context is None:
|
|
context = {}
|
|
if context.get('company'):
|
|
return context['company']
|
|
return False
|
|
|
|
def default_reconcile(self, cursor, user, context=None):
|
|
return False
|
|
|
|
def default_deferral(self, cursor, user, context=None):
|
|
return True
|
|
|
|
def default_kind(self, cursor, user, context=None):
|
|
return 'view'
|
|
|
|
def get_currency(self, cursor, user, ids, name, arg, context=None):
|
|
currency_obj = self.pool.get('currency.currency')
|
|
res = {}
|
|
for account in self.browse(cursor, user, ids, context=context):
|
|
res[account.id] = account.company.currency.id
|
|
return res
|
|
|
|
def get_currency_digits(self, cursor, user, ids, name, arg, context=None):
|
|
res = {}
|
|
for account in self.browse(cursor, user, ids, context=context):
|
|
res[account.id] = account.company.currency.digits
|
|
return res
|
|
|
|
def get_balance(self, cursor, user, ids, name, arg, context=None):
|
|
res = {}
|
|
company_obj = self.pool.get('company.company')
|
|
currency_obj = self.pool.get('currency.currency')
|
|
move_line_obj = self.pool.get('account.move.line')
|
|
fiscalyear_obj = self.pool.get('account.fiscalyear')
|
|
deferral_obj = self.pool.get('account.account.deferral')
|
|
|
|
if context is None:
|
|
context = {}
|
|
|
|
query_ids, args_ids = self.search(cursor, user, [
|
|
('parent', 'child_of', ids),
|
|
], context=context, query_string=True)
|
|
line_query, fiscalyear_ids = move_line_obj.query_get(cursor, user,
|
|
context=context)
|
|
cursor.execute('SELECT a.id, ' \
|
|
'SUM((COALESCE(l.debit, 0) - COALESCE(l.credit, 0))) ' \
|
|
'FROM account_account a ' \
|
|
'LEFT JOIN account_move_line l ' \
|
|
'ON (a.id = l.account) ' \
|
|
'WHERE a.kind != \'view\' ' \
|
|
'AND a.id IN (' + query_ids + ') ' \
|
|
'AND ' + line_query + ' ' \
|
|
'AND a.active ' \
|
|
'GROUP BY a.id', args_ids)
|
|
account_sum = {}
|
|
for account_id, sum in cursor.fetchall():
|
|
# SQLite uses float for SUM
|
|
if not isinstance(sum, Decimal):
|
|
sum = Decimal(str(sum))
|
|
account_sum[account_id] = sum
|
|
|
|
account2company = {}
|
|
id2company = {}
|
|
id2account = {}
|
|
all_ids = self.search(cursor, user, [('parent', 'child_of', ids)],
|
|
context=context)
|
|
accounts = self.browse(cursor, user, all_ids, context=context)
|
|
for account in accounts:
|
|
account2company[account.id] = account.company.id
|
|
id2company[account.company.id] = account.company
|
|
id2account[account.id] = account
|
|
|
|
for account_id in ids:
|
|
res.setdefault(account_id, Decimal('0.0'))
|
|
child_ids = self.search(cursor, user, [
|
|
('parent', 'child_of', [account_id]),
|
|
], context=context)
|
|
company_id = account2company[account_id]
|
|
to_currency = id2company[company_id].currency
|
|
for child_id in child_ids:
|
|
child_company_id = account2company[child_id]
|
|
from_currency = id2company[child_company_id].currency
|
|
res[account_id] += currency_obj.compute(cursor, user,
|
|
from_currency, account_sum.get(child_id, Decimal('0.0')),
|
|
to_currency, round=True, context=context)
|
|
|
|
youngest_fiscalyear = None
|
|
for fiscalyear in fiscalyear_obj.browse(cursor, user, fiscalyear_ids,
|
|
context=context):
|
|
if not youngest_fiscalyear \
|
|
or youngest_fiscalyear.start_date > fiscalyear.start_date:
|
|
youngest_fiscalyear = fiscalyear
|
|
|
|
fiscalyear = None
|
|
if youngest_fiscalyear:
|
|
fiscalyear_ids = fiscalyear_obj.search(cursor, user, [
|
|
('end_date', '<=', youngest_fiscalyear.start_date),
|
|
('company', '=', youngest_fiscalyear.company),
|
|
], order=[('end_date', 'DESC')], limit=1, context=context)
|
|
if fiscalyear_ids:
|
|
fiscalyear = fiscalyear_obj.browse(cursor, user,
|
|
fiscalyear_ids[0], context=context)
|
|
|
|
if fiscalyear:
|
|
if fiscalyear.state == 'close':
|
|
deferral_ids = deferral_obj.search(cursor, user, [
|
|
('fiscalyear', '=', fiscalyear.id),
|
|
('account', 'in', ids),
|
|
], context=context)
|
|
id2deferral = {}
|
|
for deferral in deferral_obj.browse(cursor, user, deferral_ids,
|
|
context=context):
|
|
id2deferral[deferral.account.id] = deferral
|
|
|
|
for account_id in ids:
|
|
if account_id in id2deferral:
|
|
deferral = id2deferral[account_id]
|
|
res[account_id] += deferral.debit - deferral.credit
|
|
else:
|
|
ctx = context.copy()
|
|
ctx['fiscalyear'] = fiscalyear.id
|
|
if 'date' in context:
|
|
del context['date']
|
|
res2 = self.get_balance(cursor, user, ids, name, arg,
|
|
context=ctx)
|
|
for account_id in ids:
|
|
res[account_id] += res2[account_id]
|
|
|
|
for account_id in ids:
|
|
company_id = account2company[account_id]
|
|
to_currency = id2company[company_id].currency
|
|
res[account_id] = currency_obj.round(cursor, user, to_currency,
|
|
res[account_id])
|
|
return res
|
|
|
|
def get_credit_debit(self, cursor, user, ids, names, arg, context=None):
|
|
'''
|
|
Function to compute debit, credit for account ids.
|
|
|
|
:param cursor: the database cursor
|
|
:param user: the user id
|
|
:param ids: the ids of the account
|
|
:param names: the list of field name to compute
|
|
:param arg: optional argument
|
|
:param context: the context
|
|
:return: a dictionary with all field names as key and
|
|
a dictionary as value with id as key
|
|
'''
|
|
res = {}
|
|
move_line_obj = self.pool.get('account.move.line')
|
|
company_obj = self.pool.get('company.company')
|
|
currency_obj = self.pool.get('currency.currency')
|
|
fiscalyear_obj = self.pool.get('account.fiscalyear')
|
|
deferral_obj = self.pool.get('account.account.deferral')
|
|
|
|
if context is None:
|
|
context = {}
|
|
|
|
for name in names:
|
|
if name not in ('credit', 'debit'):
|
|
raise Exception('Bad argument')
|
|
res[name] = {}
|
|
|
|
line_query, fiscalyear_ids = move_line_obj.query_get(cursor, user,
|
|
context=context)
|
|
for i in range(0, len(ids), cursor.IN_MAX):
|
|
sub_ids = ids[i:i + cursor.IN_MAX]
|
|
red_sql, red_ids = reduce_ids('a.id', sub_ids)
|
|
cursor.execute('SELECT a.id, ' + \
|
|
','.join('SUM(COALESCE(l.' + name + ', 0))'
|
|
for name in names) + ' ' \
|
|
'FROM account_account a ' \
|
|
'LEFT JOIN account_move_line l ' \
|
|
'ON (a.id = l.account) ' \
|
|
'WHERE a.kind != \'view\' ' \
|
|
'AND ' + red_sql + ' ' \
|
|
'AND ' + line_query + ' ' \
|
|
'AND a.active ' \
|
|
'GROUP BY a.id', red_ids)
|
|
for row in cursor.fetchall():
|
|
account_id = row[0]
|
|
for i in range(len(names)):
|
|
# SQLite uses float for SUM
|
|
if not isinstance(row[i + 1], Decimal):
|
|
res[names[i]][account_id] = Decimal(str(row[i + 1]))
|
|
else:
|
|
res[names[i]][account_id] = row[i + 1]
|
|
|
|
account2company = {}
|
|
id2company = {}
|
|
accounts = self.browse(cursor, user, ids, context=context)
|
|
for account in accounts:
|
|
account2company[account.id] = account.company.id
|
|
id2company[account.company.id] = account.company
|
|
|
|
for account_id in ids:
|
|
for name in names:
|
|
res[name].setdefault(account_id, Decimal('0.0'))
|
|
|
|
youngest_fiscalyear = None
|
|
for fiscalyear in fiscalyear_obj.browse(cursor, user, fiscalyear_ids,
|
|
context=context):
|
|
if not youngest_fiscalyear \
|
|
or youngest_fiscalyear.start_date > fiscalyear.start_date:
|
|
youngest_fiscalyear = fiscalyear
|
|
|
|
fiscalyear = None
|
|
if youngest_fiscalyear:
|
|
fiscalyear_ids = fiscalyear_obj.search(cursor, user, [
|
|
('end_date', '<=', youngest_fiscalyear.start_date),
|
|
('company', '=', youngest_fiscalyear.company),
|
|
], order=[('end_date', 'DESC')], limit=1, context=context)
|
|
if fiscalyear_ids:
|
|
fiscalyear = fiscalyear_obj.browse(cursor, user,
|
|
fiscalyear_ids[0], context=context)
|
|
|
|
if fiscalyear:
|
|
if fiscalyear.state == 'close':
|
|
deferral_ids = deferral_obj.search(cursor, user, [
|
|
('fiscalyear', '=', fiscalyear.id),
|
|
('account', 'in', ids),
|
|
], context=context)
|
|
id2deferral = {}
|
|
for deferral in deferral_obj.browse(cursor, user, deferral_ids,
|
|
context=context):
|
|
id2deferral[deferral.account.id] = deferral
|
|
|
|
for account_id in ids:
|
|
if account_id in id2deferral:
|
|
deferral = id2deferral[account_id]
|
|
for name in names:
|
|
res[name][account_id] += deferral[name]
|
|
else:
|
|
ctx = context.copy()
|
|
ctx['fiscalyear'] = fiscalyear.id
|
|
if 'date' in ctx:
|
|
del ctx['date']
|
|
res2 = self.get_credit_debit(cursor, user, ids, names, arg,
|
|
context=ctx)
|
|
for account_id in ids:
|
|
for name in names:
|
|
res[name][account_id] += res2[name][account_id]
|
|
|
|
for account_id in ids:
|
|
company_id = account2company[account_id]
|
|
currency = id2company[company_id].currency
|
|
for name in names:
|
|
res[name][account_id] = currency_obj.round(cursor, user,
|
|
currency, res[name][account_id])
|
|
return res
|
|
|
|
def get_rec_name(self, cursor, user, ids, name, arg, context=None):
|
|
if not ids:
|
|
return {}
|
|
res = {}
|
|
for account in self.browse(cursor, user, ids, context=context):
|
|
if account.code:
|
|
res[account.id] = account.code + ' - ' + account.name
|
|
else:
|
|
res[account.id] = account.name
|
|
return res
|
|
|
|
def search_rec_name(self, cursor, user, name, args, context=None):
|
|
args2 = []
|
|
i = 0
|
|
while i < len(args):
|
|
ids = self.search(cursor, user, [
|
|
('code', args[i][1], args[i][2]),
|
|
], limit=1, context=context)
|
|
if ids:
|
|
args2.append(('code', args[i][1], args[i][2]))
|
|
else:
|
|
args2.append((self._rec_name, args[i][1], args[i][2]))
|
|
i += 1
|
|
return args2
|
|
|
|
def copy(self, cursor, user, ids, default=None, context=None):
|
|
if default is None:
|
|
default = {}
|
|
default['left'] = 0
|
|
default['right'] = 0
|
|
res = super(Account, self).copy(cursor, user, ids, default=default,
|
|
context=context)
|
|
self._rebuild_tree(cursor, user, 'parent', False, 0)
|
|
return res
|
|
|
|
def write(self, cursor, user, ids, vals, context=None):
|
|
if not vals.get('active', True):
|
|
move_line_obj = self.pool.get('account.move.line')
|
|
account_ids = self.search(cursor, user, [
|
|
('parent', 'child_of', ids),
|
|
], context=context)
|
|
if move_line_obj.search(cursor, user, [
|
|
('account', 'in', account_ids),
|
|
], context=context):
|
|
vals = vals.copy()
|
|
del vals['active']
|
|
return super(Account, self).write(cursor, user, ids, vals,
|
|
context=context)
|
|
|
|
def delete(self, cursor, user, ids, context=None):
|
|
move_line_obj = self.pool.get('account.move.line')
|
|
if isinstance(ids, (int, long)):
|
|
ids = [ids]
|
|
account_ids = self.search(cursor, user, [
|
|
('parent', 'child_of', ids),
|
|
], context=context)
|
|
if move_line_obj.search(cursor, user, [
|
|
('account', 'in', account_ids),
|
|
], context=context):
|
|
self.raise_user_error(cursor,
|
|
'delete_account_containing_move_lines', context=context)
|
|
return super(Account, self).delete(cursor, user, account_ids,
|
|
context=context)
|
|
|
|
def update_account(self, cursor, user, account, context=None,
|
|
template2account=None, template2type=None):
|
|
'''
|
|
Update recursively accounts based on template.
|
|
|
|
:param cursor: the database cursor
|
|
:param user: the user id
|
|
:param account: an account id or the BrowseRecord of the account
|
|
:param context: the context
|
|
:param template2account: a dictionary with template id as key
|
|
and account id as value, used to convert template id
|
|
into account. The dictionary is filled with new accounts
|
|
:param template2type: a dictionary with type template id as key
|
|
and type id as value, used to convert type template id
|
|
into type.
|
|
'''
|
|
template_obj = self.pool.get('account.account.template')
|
|
lang_obj = self.pool.get('ir.lang')
|
|
|
|
if template2account is None:
|
|
template2account = {}
|
|
|
|
if template2type is None:
|
|
template2type = {}
|
|
|
|
if isinstance(account, (int, long)):
|
|
account = self.browse(cursor, user, account, context=context)
|
|
|
|
if account.template:
|
|
vals = template_obj._get_account_value(cursor, user,
|
|
account.template, context=context, account=account)
|
|
if account.type.id != template2type.get(account.template.type.id,
|
|
False):
|
|
vals['type'] = template2type.get(account.template.type.id,
|
|
False)
|
|
if vals:
|
|
self.write(cursor, user, account.id, vals, context=context)
|
|
|
|
prev_lang = account._context.get('language') or 'en_US'
|
|
ctx = context.copy()
|
|
for lang in lang_obj.get_translatable_languages(cursor, user,
|
|
context=context):
|
|
if lang == prev_lang:
|
|
continue
|
|
ctx['language'] = lang
|
|
account.setLang(lang)
|
|
data = template_obj._get_account_value(cursor, user,
|
|
account.template, context=ctx, account=account)
|
|
if data:
|
|
self.write(cursor, user, account.id, data, context=ctx)
|
|
account.setLang(prev_lang)
|
|
template2account[account.template.id] = account.id
|
|
|
|
for child in account.childs:
|
|
self.update_account(cursor, user, child, context=context,
|
|
template2account=template2account,
|
|
template2type=template2type)
|
|
|
|
def update_account_taxes(self, cursor, user, account, template2account,
|
|
template2tax, context=None):
|
|
'''
|
|
Update recursively account taxes base on template.
|
|
|
|
:param cursor: the database cursor
|
|
:param user: the user id
|
|
:param account: the account id or the BrowseRecord of account
|
|
:param template2account: a dictionary with template id as key
|
|
and account id as value, used to convert template id into
|
|
account.
|
|
:param template2tax: a dictionary with tax template id as key
|
|
and tax id as value, used to convert tax template id into
|
|
tax.
|
|
:param context: the context
|
|
'''
|
|
if template2account is None:
|
|
template2account = {}
|
|
|
|
if template2tax is None:
|
|
template2tax = {}
|
|
|
|
if isinstance(account, (int, long)):
|
|
account = self.browse(cursor, user, account, context=context)
|
|
|
|
if account.template:
|
|
if account.template.taxes:
|
|
tax_ids = [template2tax[x.id] for x in account.template.taxes
|
|
if x.id in template2tax]
|
|
old_tax_ids = [x.id for x in account.taxes]
|
|
for tax_id in tax_ids:
|
|
if tax_id not in old_tax_ids:
|
|
self.write(cursor, user, account.id, {
|
|
'taxes': [
|
|
('add', template2tax[x.id]) \
|
|
for x in account.template.taxes \
|
|
if x.id in template2tax],
|
|
}, context=context)
|
|
break
|
|
|
|
for child in account.childs:
|
|
self.update_account_taxes(cursor, user, child, template2account,
|
|
template2tax, context=context)
|
|
|
|
Account()
|
|
|
|
|
|
class AccountDeferral(ModelSQL, ModelView):
|
|
'''
|
|
Account Deferral
|
|
|
|
It is used to deferral the debit/credit of account by fiscal year.
|
|
'''
|
|
_name = 'account.account.deferral'
|
|
_description = 'Account Deferral'
|
|
|
|
account = fields.Many2One('account.account', 'Account', required=True,
|
|
select=1)
|
|
fiscalyear = fields.Many2One('account.fiscalyear', 'Fiscal Year',
|
|
required=True, select=1)
|
|
debit = fields.Numeric('Debit', digits=(16, Eval('currency_digits', 2)),
|
|
depends=['currency_digits'])
|
|
credit = fields.Numeric('Credit', digits=(16, Eval('currency_digits', 2)),
|
|
depends=['currency_digits'])
|
|
currency_digits = fields.Function('get_currency_digits', type='integer',
|
|
string='Currency Digits')
|
|
|
|
def __init__(self):
|
|
super(AccountDeferral, self).__init__()
|
|
self._sql_constraints += [
|
|
('deferral_uniq', 'UNIQUE(account, fiscalyear)',
|
|
'Deferral must be unique by account and fiscal year'),
|
|
]
|
|
self._error_messages.update({
|
|
'write_deferral': 'You can not modify Account Deferral records',
|
|
})
|
|
|
|
def get_currency_digits(self, cursor, user, ids, name, arg, context=None):
|
|
res = {}
|
|
for deferral in self.browse(cursor, user, ids, context=context):
|
|
res[deferral.id] = deferral.account.currency_digits
|
|
return res
|
|
|
|
def get_rec_name(self, cursor, user, ids, name, arg, context=None):
|
|
if not ids:
|
|
return {}
|
|
res = {}
|
|
for deferral in self.browse(cursor, user, ids, context=context):
|
|
res[deferral.id] = deferral.account.rec_name + ' - ' + \
|
|
deferral.fiscalyear.rec_name
|
|
return res
|
|
|
|
def search_rec_name(self, cursor, user, name, args, context=None):
|
|
args2 = []
|
|
i = 0
|
|
while i < len(args):
|
|
ids = self.search(cursor, user, ['OR',
|
|
('account.rec_name', args[i][1], args[i][2]),
|
|
('fiscalyear.rec_name', args[i][1], args[i][2]),
|
|
], context=context)
|
|
args2.append(('id', 'in', ids))
|
|
i += 1
|
|
return args2
|
|
|
|
def write(self, cursor, user, ids, vals, context=None):
|
|
self.raise_user_error(cursor, 'write_deferral', context=context)
|
|
|
|
AccountDeferral()
|
|
|
|
|
|
class OpenChartAccountInit(ModelView):
|
|
'Open Chart Account Init'
|
|
_name = 'account.account.open_chart_account.init'
|
|
_description = __doc__
|
|
fiscalyear = fields.Many2One('account.fiscalyear', 'Fiscal Year',
|
|
help='Leave empty for all open fiscal year')
|
|
posted = fields.Boolean('Posted Move', help='Show only posted move')
|
|
|
|
def default_posted(self, cursor, user, context=None):
|
|
return False
|
|
|
|
OpenChartAccountInit()
|
|
|
|
|
|
class OpenChartAccount(Wizard):
|
|
'Open Chart Of Account'
|
|
_name = 'account.account.open_chart_account'
|
|
states = {
|
|
'init': {
|
|
'result': {
|
|
'type': 'form',
|
|
'object': 'account.account.open_chart_account.init',
|
|
'state': [
|
|
('end', 'Cancel', 'tryton-cancel'),
|
|
('open', 'Open', 'tryton-ok', True),
|
|
],
|
|
},
|
|
},
|
|
'open': {
|
|
'result': {
|
|
'type': 'action',
|
|
'action': '_action_open_chart',
|
|
'state': 'end',
|
|
},
|
|
},
|
|
}
|
|
|
|
def _action_open_chart(self, cursor, user, data, context=None):
|
|
model_data_obj = self.pool.get('ir.model.data')
|
|
act_window_obj = self.pool.get('ir.action.act_window')
|
|
act_window_id = model_data_obj.get_id(cursor, user, 'account',
|
|
'act_account_tree2', context=context)
|
|
res = act_window_obj.read(cursor, user, act_window_id, context=context)
|
|
res['pyson_context'] = PYSONEncoder().encode({
|
|
'fiscalyear': data['form']['fiscalyear'],
|
|
'posted': data['form']['posted'],
|
|
})
|
|
return res
|
|
|
|
OpenChartAccount()
|
|
|
|
|
|
class PrintGeneralLegderInit(ModelView):
|
|
'Print General Ledger'
|
|
_name = 'account.account.print_general_ledger.init'
|
|
_description = __doc__
|
|
fiscalyear = fields.Many2One('account.fiscalyear', 'Fiscal Year',
|
|
required=True, on_change=['fiscalyear'])
|
|
start_period = fields.Many2One('account.period', 'Start Period',
|
|
domain=[
|
|
('fiscalyear', '=', Eval('fiscalyear')),
|
|
('start_date', '<=', (Eval('end_period'), 'start_date')),
|
|
])
|
|
end_period = fields.Many2One('account.period', 'End Period',
|
|
domain=[
|
|
('fiscalyear', '=', Eval('fiscalyear')),
|
|
('start_date', '>=', (Eval('start_period'), 'start_date'))
|
|
])
|
|
company = fields.Many2One('company.company', 'Company', required=True)
|
|
posted = fields.Boolean('Posted Move', help='Show only posted move')
|
|
empty_account = fields.Boolean('Empty Account',
|
|
help='With account without move')
|
|
|
|
def default_fiscalyear(self, cursor, user, context=None):
|
|
fiscalyear_obj = self.pool.get('account.fiscalyear')
|
|
if context is None:
|
|
context = {}
|
|
fiscalyear_id = fiscalyear_obj.find(cursor, user,
|
|
context.get('company', False), exception=False, context=context)
|
|
if fiscalyear_id:
|
|
return fiscalyear_id
|
|
return False
|
|
|
|
def default_company(self, cursor, user, context=None):
|
|
if context is None:
|
|
context = {}
|
|
if context.get('company'):
|
|
return context['company']
|
|
return False
|
|
|
|
def default_posted(self, cursor, user, context=None):
|
|
return False
|
|
|
|
def default_empty_account(self, cursor, user, context=None):
|
|
return False
|
|
|
|
def on_change_fiscalyear(self, cursor, user, ids, vals, context=None):
|
|
return {
|
|
'start_period': False,
|
|
'end_period': False,
|
|
}
|
|
|
|
PrintGeneralLegderInit()
|
|
|
|
|
|
class PrintGeneralLegder(Wizard):
|
|
'Print General Legder'
|
|
_name = 'account.account.print_general_ledger'
|
|
states = {
|
|
'init': {
|
|
'result': {
|
|
'type': 'form',
|
|
'object': 'account.account.print_general_ledger.init',
|
|
'state': [
|
|
('end', 'Cancel', 'tryton-cancel'),
|
|
('print', 'Print', 'tryton-print', True),
|
|
],
|
|
},
|
|
},
|
|
'print': {
|
|
'result': {
|
|
'type': 'print',
|
|
'report': 'account.account.general_ledger',
|
|
'state': 'end',
|
|
},
|
|
},
|
|
}
|
|
|
|
PrintGeneralLegder()
|
|
|
|
|
|
class GeneralLegder(Report):
|
|
_name = 'account.account.general_ledger'
|
|
|
|
def parse(self, cursor, user, report, objects, datas, context):
|
|
if context is None:
|
|
context = {}
|
|
context = context.copy()
|
|
account_obj = self.pool.get('account.account')
|
|
period_obj = self.pool.get('account.period')
|
|
company_obj = self.pool.get('company.company')
|
|
|
|
company = company_obj.browse(cursor, user,
|
|
datas['form']['company'], context=context)
|
|
|
|
account_ids = account_obj.search(cursor, user, [
|
|
('company', '=', datas['form']['company']),
|
|
('kind', '!=', 'view'),
|
|
], order=[('code', 'ASC'), ('id', 'ASC')], context=context)
|
|
|
|
start_period_ids = [0]
|
|
if datas['form']['start_period']:
|
|
start_period = period_obj.browse(cursor, user,
|
|
datas['form']['start_period'], context=context)
|
|
start_period_ids = period_obj.search(cursor, user, [
|
|
('fiscalyear', '=', datas['form']['fiscalyear']),
|
|
('end_date', '<=', start_period.start_date),
|
|
], context=context)
|
|
|
|
start_context = context.copy()
|
|
start_context['fiscalyear'] = datas['form']['fiscalyear']
|
|
start_context['periods'] = start_period_ids
|
|
start_context['posted'] = datas['form']['posted']
|
|
start_accounts = account_obj.browse(cursor, user, account_ids,
|
|
context=start_context)
|
|
id2start_account = {}
|
|
for account in start_accounts:
|
|
id2start_account[account.id] = account
|
|
|
|
end_period_ids = []
|
|
if datas['form']['end_period']:
|
|
end_period = period_obj.browse(cursor, user,
|
|
datas['form']['end_period'], context=context)
|
|
end_period_ids = period_obj.search(cursor, user, [
|
|
('fiscalyear', '=', datas['form']['fiscalyear']),
|
|
('end_date', '<=', end_period.start_date),
|
|
], context=context)
|
|
if datas['form']['end_period'] not in end_period_ids:
|
|
end_period_ids.append(datas['form']['end_period'])
|
|
else:
|
|
end_period_ids = period_obj.search(cursor, user, [
|
|
('fiscalyear', '=', datas['form']['fiscalyear']),
|
|
], context=context)
|
|
|
|
end_context = context.copy()
|
|
end_context['fiscalyear'] = datas['form']['fiscalyear']
|
|
end_context['periods'] = end_period_ids
|
|
end_context['posted'] = datas['form']['posted']
|
|
end_accounts = account_obj.browse(cursor, user, account_ids,
|
|
context=end_context)
|
|
id2end_account = {}
|
|
for account in end_accounts:
|
|
id2end_account[account.id] = account
|
|
|
|
periods = period_obj.browse(cursor, user, end_period_ids,
|
|
context=context)
|
|
periods.sort(lambda x, y: cmp(x.start_date, y.start_date))
|
|
context['start_period'] = periods[0]
|
|
periods.sort(lambda x, y: cmp(x.end_date, y.end_date))
|
|
context['end_period'] = periods[-1]
|
|
|
|
if not datas['form']['empty_account']:
|
|
to_remove = []
|
|
account_id2lines = self.get_lines(cursor, user, account_ids,
|
|
end_period_ids, datas['form']['posted'], context)
|
|
for account_id in account_ids:
|
|
if account_id not in account_id2lines:
|
|
to_remove.append(account_id)
|
|
for account_id in to_remove:
|
|
account_ids.remove(account_id)
|
|
|
|
context['accounts'] = account_obj.browse(cursor, user, account_ids,
|
|
context=context)
|
|
context['id2start_account'] = id2start_account
|
|
context['id2end_account'] = id2end_account
|
|
context['digits'] = company.currency.digits
|
|
account_id2lines = self.lines(cursor, user, account_ids,
|
|
list(set(end_period_ids).difference(
|
|
set(start_period_ids))), datas['form']['posted'], context)
|
|
context['lines'] = lambda account_id: account_id2lines[account_id]
|
|
context['company'] = company
|
|
|
|
return super(GeneralLegder, self).parse(cursor, user, report, objects,
|
|
datas, context)
|
|
|
|
def get_lines(self, cursor, user, account_ids, period_ids, posted,
|
|
context):
|
|
move_line_obj = self.pool.get('account.move.line')
|
|
clause = [
|
|
('account', 'in', account_ids),
|
|
('period', 'in', period_ids),
|
|
('state', '!=', 'draft'),
|
|
]
|
|
if posted:
|
|
clause.append(('move.state', '=', 'posted'))
|
|
move_ids = move_line_obj.search(cursor, user, clause,
|
|
order=[], context=context)
|
|
res = {}
|
|
for move in move_line_obj.browse(cursor, user, move_ids,
|
|
context=context):
|
|
res.setdefault(move.account.id, []).append(move)
|
|
return res
|
|
|
|
def lines(self, cursor, user, account_ids, period_ids, posted, context):
|
|
move_line_obj = self.pool.get('account.move.line')
|
|
move_obj = self.pool.get('account.move')
|
|
res = dict(((account_id, []) for account_id in account_ids))
|
|
account_id2lines = self.get_lines(cursor, user, account_ids,
|
|
period_ids, posted, context)
|
|
|
|
state_selections = dict(move_obj.fields_get(cursor, user,
|
|
fields_names=['state'], context=context)['state']['selection'])
|
|
|
|
for account_id, lines in account_id2lines.iteritems():
|
|
lines.sort(lambda x, y: cmp(x.date, y.date))
|
|
balance = Decimal('0.0')
|
|
for line in lines:
|
|
balance += line.debit - line.credit
|
|
res[account_id].append({
|
|
'date': line.date,
|
|
'debit': line.debit,
|
|
'credit': line.credit,
|
|
'balance': balance,
|
|
'name': line.name,
|
|
'state': state_selections.get(line.move.state, line.move.state),
|
|
})
|
|
return res
|
|
|
|
GeneralLegder()
|
|
|
|
|
|
class PrintTrialBalanceInit(ModelView):
|
|
'Print Trial Balance Init'
|
|
_name = 'account.account.print_trial_balance.init'
|
|
_description = __doc__
|
|
fiscalyear = fields.Many2One('account.fiscalyear', 'Fiscal Year',
|
|
required=True, on_change=['fiscalyear'],
|
|
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'])
|
|
end_period = fields.Many2One('account.period', 'End Period',
|
|
domain=[
|
|
('fiscalyear', '=', Eval('fiscalyear')),
|
|
('start_date', '>=', (Eval('start_period'), 'start_date'))
|
|
],
|
|
depends=['start_period'])
|
|
company = fields.Many2One('company.company', 'Company', required=True)
|
|
posted = fields.Boolean('Posted Move', help='Show only posted move')
|
|
empty_account = fields.Boolean('Empty Account',
|
|
help='With account without move')
|
|
|
|
def default_fiscalyear(self, cursor, user, context=None):
|
|
fiscalyear_obj = self.pool.get('account.fiscalyear')
|
|
if context is None:
|
|
context = {}
|
|
fiscalyear_id = fiscalyear_obj.find(cursor, user,
|
|
context.get('company', False), exception=False, context=context)
|
|
if fiscalyear_id:
|
|
return fiscalyear_id
|
|
return False
|
|
|
|
def default_company(self, cursor, user, context=None):
|
|
if context is None:
|
|
context = {}
|
|
if context.get('company'):
|
|
return context['company']
|
|
return False
|
|
|
|
def default_posted(self, cursor, user, context=None):
|
|
return False
|
|
|
|
def default_empty_account(self, cursor, user, context=None):
|
|
return False
|
|
|
|
def on_change_fiscalyear(self, cursor, user, ids, vals, context=None):
|
|
return {
|
|
'start_period': False,
|
|
'end_period': False,
|
|
}
|
|
|
|
PrintTrialBalanceInit()
|
|
|
|
|
|
class PrintTrialBalance(Wizard):
|
|
'Print Trial Balance'
|
|
_name = 'account.account.print_trial_balance'
|
|
states = {
|
|
'init': {
|
|
'result': {
|
|
'type': 'form',
|
|
'object': 'account.account.print_trial_balance.init',
|
|
'state': [
|
|
('end', 'Cancel', 'tryton-cancel'),
|
|
('print', 'Print', 'tryton-print', True),
|
|
],
|
|
},
|
|
},
|
|
'print': {
|
|
'result': {
|
|
'type': 'print',
|
|
'report': 'account.account.trial_balance',
|
|
'state': 'end',
|
|
},
|
|
},
|
|
}
|
|
|
|
PrintTrialBalance()
|
|
|
|
|
|
class TrialBalance(Report):
|
|
_name = 'account.account.trial_balance'
|
|
|
|
def parse(self, cursor, user, report, objects, datas, context):
|
|
if context is None:
|
|
context = {}
|
|
context = context.copy()
|
|
account_obj = self.pool.get('account.account')
|
|
period_obj = self.pool.get('account.period')
|
|
company_obj = self.pool.get('company.company')
|
|
|
|
company = company_obj.browse(cursor, user,
|
|
datas['form']['company'], context=context)
|
|
|
|
account_ids = account_obj.search(cursor, user, [
|
|
('company', '=', datas['form']['company']),
|
|
('kind', '!=', 'view'),
|
|
], context=context)
|
|
|
|
start_period_ids = [0]
|
|
if datas['form']['start_period']:
|
|
start_period = period_obj.browse(cursor, user,
|
|
datas['form']['start_period'], context=context)
|
|
start_period_ids = period_obj.search(cursor, user, [
|
|
('fiscalyear', '=', datas['form']['fiscalyear']),
|
|
('end_date', '<=', start_period.start_date),
|
|
], context=context)
|
|
|
|
end_period_ids = []
|
|
if datas['form']['end_period']:
|
|
end_period = period_obj.browse(cursor, user,
|
|
datas['form']['end_period'], context=context)
|
|
end_period_ids = period_obj.search(cursor, user, [
|
|
('fiscalyear', '=', datas['form']['fiscalyear']),
|
|
('end_date', '<=', end_period.start_date),
|
|
], context=context)
|
|
end_period_ids = list(set(end_period_ids).difference(
|
|
set(start_period_ids)))
|
|
if datas['form']['end_period'] not in end_period_ids:
|
|
end_period_ids.append(datas['form']['end_period'])
|
|
else:
|
|
end_period_ids = period_obj.search(cursor, user, [
|
|
('fiscalyear', '=', datas['form']['fiscalyear']),
|
|
], context=context)
|
|
end_period_ids = list(set(end_period_ids).difference(
|
|
set(start_period_ids)))
|
|
|
|
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)
|
|
|
|
if not datas['form']['empty_account']:
|
|
to_remove = []
|
|
for account in accounts:
|
|
if account.debit == Decimal('0.0') \
|
|
and account.credit == Decimal('0.0'):
|
|
to_remove.append(account)
|
|
for account in to_remove:
|
|
accounts.remove(account)
|
|
|
|
periods = period_obj.browse(cursor, user, end_period_ids,
|
|
context=context)
|
|
|
|
context['accounts'] = accounts
|
|
context['start_period'] = periods[0]
|
|
context['end_period'] = periods[-1]
|
|
context['company'] = company
|
|
context['digits'] = company.currency.digits
|
|
context['sum'] = lambda accounts, field: self.sum(cursor, user,
|
|
accounts, field, context)
|
|
|
|
return super(TrialBalance, self).parse(cursor, user, report, objects,
|
|
datas, context)
|
|
|
|
def sum(self, cursor, user, accounts, field, context):
|
|
amount = Decimal('0.0')
|
|
for account in accounts:
|
|
amount += account[field]
|
|
return amount
|
|
|
|
TrialBalance()
|
|
|
|
|
|
class OpenBalanceSheetInit(ModelView):
|
|
'Open Balance Sheet Init'
|
|
_name = 'account.account.open_balance_sheet.init'
|
|
_description = __doc__
|
|
date = fields.Date('Date', required=True)
|
|
company = fields.Many2One('company.company', 'Company', required=True)
|
|
posted = fields.Boolean('Posted Move', help='Show only posted move')
|
|
|
|
def default_date(self, cursor, user, context=None):
|
|
date_obj = self.pool.get('ir.date')
|
|
return date_obj.today(cursor, user, context=context)
|
|
|
|
def default_company(self, cursor, user, context=None):
|
|
if context is None:
|
|
context = {}
|
|
if context.get('company'):
|
|
return context['company']
|
|
return False
|
|
|
|
def default_posted(self, cursor, user, context=None):
|
|
return False
|
|
|
|
OpenBalanceSheetInit()
|
|
|
|
|
|
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', 'tryton-cancel'),
|
|
('open', 'Open', 'tryton-ok', True),
|
|
],
|
|
},
|
|
},
|
|
'open': {
|
|
'result': {
|
|
'type': 'action',
|
|
'action': '_action_open',
|
|
'state': 'end',
|
|
},
|
|
},
|
|
}
|
|
|
|
def _action_open(self, cursor, user, datas, 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')
|
|
lang_obj = self.pool.get('ir.lang')
|
|
|
|
company = company_obj.browse(cursor, user, datas['form']['company'],
|
|
context=context)
|
|
for code in [context.get('language', False) or 'en_US', 'en_US']:
|
|
lang_ids = lang_obj.search(cursor, user, [
|
|
('code', '=', code),
|
|
], context=context)
|
|
if lang_ids:
|
|
break
|
|
lang = lang_obj.browse(cursor, user, lang_ids[0], context=context)
|
|
|
|
date = lang_obj.strftime(datas['form']['date'], lang.code, lang.date)
|
|
|
|
act_window_id = model_data_obj.get_id(cursor, user, 'account',
|
|
'act_account_balance_sheet_tree', context=context)
|
|
res = act_window_obj.read(cursor, user, act_window_id, context=context)
|
|
res['pyson_context'] = PYSONEncoder().encode({
|
|
'date': Date(datas['form']['date'].year,
|
|
datas['form']['date'].month,
|
|
datas['form']['date'].day),
|
|
'posted': datas['form']['posted'],
|
|
'company': datas['form']['company'],
|
|
})
|
|
res['name'] = res['name'] + ' - '+ date + ' - ' + company.name
|
|
return res
|
|
|
|
OpenBalanceSheet()
|
|
|
|
|
|
class OpenIncomeStatementInit(ModelView):
|
|
'Open Income Statement Init'
|
|
_name = 'account.account.open_income_statement.init'
|
|
_description = __doc__
|
|
fiscalyear = fields.Many2One('account.fiscalyear', 'Fiscal Year',
|
|
required=True, on_change=['fiscalyear'],
|
|
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'])
|
|
end_period = fields.Many2One('account.period', 'End Period',
|
|
domain=[
|
|
('fiscalyear', '=', Eval('fiscalyear')),
|
|
('start_date', '>=', (Eval('start_period'), 'start_date')),
|
|
],
|
|
depends=['start_period'])
|
|
company = fields.Many2One('company.company', 'Company', required=True)
|
|
posted = fields.Boolean('Posted Move', help='Show only posted move')
|
|
|
|
def default_fiscalyear(self, cursor, user, context=None):
|
|
fiscalyear_obj = self.pool.get('account.fiscalyear')
|
|
if context is None:
|
|
context = {}
|
|
fiscalyear_id = fiscalyear_obj.find(cursor, user,
|
|
context.get('company', False), exception=False, context=context)
|
|
if fiscalyear_id:
|
|
return fiscalyear_id
|
|
return False
|
|
|
|
def default_company(self, cursor, user, context=None):
|
|
if context is None:
|
|
context = {}
|
|
if context.get('company'):
|
|
return context['company']
|
|
return False
|
|
|
|
def default_posted(self, cursor, user, context=None):
|
|
return False
|
|
|
|
def on_change_fiscalyear(self, cursor, user, ids, vals, context=None):
|
|
return {
|
|
'start_period': False,
|
|
'end_period': False,
|
|
}
|
|
|
|
OpenIncomeStatementInit()
|
|
|
|
|
|
class OpenIncomeStatement(Wizard):
|
|
'Open Income Statement'
|
|
_name = 'account.account.open_income_statement'
|
|
states = {
|
|
'init': {
|
|
'result': {
|
|
'type': 'form',
|
|
'object': 'account.account.open_income_statement.init',
|
|
'state': [
|
|
('end', 'Cancel', 'tryton-cancel'),
|
|
('open', 'Open', 'tryton-ok', True),
|
|
],
|
|
},
|
|
},
|
|
'open': {
|
|
'result': {
|
|
'type': 'action',
|
|
'action': '_action_open',
|
|
'state': 'end',
|
|
},
|
|
},
|
|
}
|
|
|
|
def _action_open(self, cursor, user, datas, 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')
|
|
period_obj = self.pool.get('account.period')
|
|
|
|
start_period_ids = [0]
|
|
if datas['form']['start_period']:
|
|
start_period = period_obj.browse(cursor, user,
|
|
datas['form']['start_period'], context=context)
|
|
start_period_ids = period_obj.search(cursor, user, [
|
|
('fiscalyear', '=', datas['form']['fiscalyear']),
|
|
('end_date', '<=', start_period.start_date),
|
|
], context=context)
|
|
|
|
end_period_ids = []
|
|
if datas['form']['end_period']:
|
|
end_period = period_obj.browse(cursor, user,
|
|
datas['form']['end_period'], context=context)
|
|
end_period_ids = period_obj.search(cursor, user, [
|
|
('fiscalyear', '=', datas['form']['fiscalyear']),
|
|
('end_date', '<=', end_period.start_date),
|
|
], context=context)
|
|
end_period_ids = list(set(end_period_ids).difference(
|
|
set(start_period_ids)))
|
|
if datas['form']['end_period'] not in end_period_ids:
|
|
end_period_ids.append(datas['form']['end_period'])
|
|
else:
|
|
end_period_ids = period_obj.search(cursor, user, [
|
|
('fiscalyear', '=', datas['form']['fiscalyear']),
|
|
], context=context)
|
|
end_period_ids = list(set(end_period_ids).difference(
|
|
set(start_period_ids)))
|
|
|
|
act_window_id = model_data_obj.get_id(cursor, user, 'account',
|
|
'act_account_income_statement_tree', context=context)
|
|
res = act_window_obj.read(cursor, user, model_data.db_id, context=context)
|
|
res['pyson_context'] = PYSONEncoder().encode({
|
|
'periods': end_period_ids,
|
|
'posted': datas['form']['posted'],
|
|
'company': datas['form']['company'],
|
|
})
|
|
return res
|
|
|
|
OpenIncomeStatement()
|
|
|
|
|
|
class CreateChartAccountInit(ModelView):
|
|
'Create Chart Account Init'
|
|
_name = 'account.account.create_chart_account.init'
|
|
_description = __doc__
|
|
|
|
CreateChartAccountInit()
|
|
|
|
|
|
class CreateChartAccountAccount(ModelView):
|
|
'Create Chart Account Account'
|
|
_name = 'account.account.create_chart_account.account'
|
|
_description = __doc__
|
|
company = fields.Many2One('company.company', 'Company', required=True)
|
|
account_template = fields.Many2One('account.account.template',
|
|
'Account Template', required=True, domain=[('parent', '=', False)])
|
|
|
|
def default_company(self, cursor, user, context=None):
|
|
if context is None:
|
|
context = {}
|
|
if context.get('company'):
|
|
return context['company']
|
|
return False
|
|
|
|
CreateChartAccountAccount()
|
|
|
|
|
|
class CreateChartAccountPropertites(ModelView):
|
|
'Create Chart Account Properties'
|
|
_name = 'account.account.create_chart_account.properties'
|
|
_description = __doc__
|
|
company = fields.Many2One('company.company', 'Company')
|
|
account_receivable = fields.Many2One('account.account',
|
|
'Default Receivable Account',
|
|
domain=[
|
|
('kind', '=', 'receivable'),
|
|
('company', '=', Eval('company')),
|
|
],
|
|
depends=['company'])
|
|
account_payable = fields.Many2One('account.account',
|
|
'Default Payable Account',
|
|
domain=[
|
|
('kind', '=', 'payable'),
|
|
('company', '=', Eval('company')),
|
|
],
|
|
depends=['company'])
|
|
|
|
CreateChartAccountPropertites()
|
|
|
|
|
|
class CreateChartAccount(Wizard):
|
|
'Create chart account from template'
|
|
_name = 'account.account.create_chart_account'
|
|
states = {
|
|
'init': {
|
|
'result': {
|
|
'type': 'form',
|
|
'object': 'account.account.create_chart_account.init',
|
|
'state': [
|
|
('end', 'Cancel', 'tryton-cancel'),
|
|
('account', 'Ok', 'tryton-ok', True),
|
|
],
|
|
},
|
|
},
|
|
'account': {
|
|
'result': {
|
|
'type': 'form',
|
|
'object': 'account.account.create_chart_account.account',
|
|
'state': [
|
|
('end', 'Cancel', 'tryton-cancel'),
|
|
('create_account', 'Create', 'tryton-ok', True),
|
|
],
|
|
},
|
|
},
|
|
'create_account': {
|
|
'actions': ['_action_create_account'],
|
|
'result': {
|
|
'type': 'form',
|
|
'object': 'account.account.create_chart_account.properties',
|
|
'state': [
|
|
('end', 'Cancel', 'tryton-cancel'),
|
|
('create_properties', 'Create', 'tryton-ok', True),
|
|
],
|
|
},
|
|
},
|
|
'create_properties': {
|
|
'result': {
|
|
'type': 'action',
|
|
'action': '_action_create_properties',
|
|
'state': 'end',
|
|
},
|
|
},
|
|
}
|
|
|
|
def _action_create_account(self, cursor, user, datas, context=None):
|
|
account_type_template_obj = \
|
|
self.pool.get('account.account.type.template')
|
|
account_template_obj = self.pool.get('account.account.template')
|
|
tax_code_template_obj = self.pool.get('account.tax.code.template')
|
|
tax_template_obj = self.pool.get('account.tax.template')
|
|
tax_rule_template_obj = self.pool.get('account.tax.rule.template')
|
|
tax_rule_line_template_obj = \
|
|
self.pool.get('account.tax.rule.line.template')
|
|
|
|
context=context.copy()
|
|
context['language'] = 'en_US'
|
|
|
|
account_template = account_template_obj.browse(cursor, user,
|
|
datas['form']['account_template'], context=context)
|
|
|
|
# Create account types
|
|
template2type = {}
|
|
account_type_template_obj.create_type(cursor, user,
|
|
account_template.type, datas['form']['company'],
|
|
context=context, template2type=template2type)
|
|
|
|
# Create accounts
|
|
template2account = {}
|
|
account_template_obj.create_account(cursor, user,
|
|
account_template, datas['form']['company'],
|
|
context=context, template2account=template2account,
|
|
template2type=template2type)
|
|
|
|
# Create tax codes
|
|
template2tax_code = {}
|
|
tax_code_template_ids = tax_code_template_obj.search(cursor, user, [
|
|
('account', '=', datas['form']['account_template']),
|
|
('parent', '=', False),
|
|
], context=context)
|
|
for tax_code_template in tax_code_template_obj.browse(cursor, user,
|
|
tax_code_template_ids, context=context):
|
|
tax_code_template_obj.create_tax_code(cursor, user,
|
|
tax_code_template, datas['form']['company'],
|
|
context=context, template2tax_code=template2tax_code)
|
|
|
|
# Create taxes
|
|
template2tax = {}
|
|
tax_template_ids = tax_template_obj.search(cursor, user, [
|
|
('account', '=', datas['form']['account_template']),
|
|
('parent', '=', False),
|
|
], context=context)
|
|
for tax_template in tax_template_obj.browse(cursor, user,
|
|
tax_template_ids, context=context):
|
|
tax_template_obj.create_tax(cursor, user, tax_template,
|
|
datas['form']['company'],
|
|
template2tax_code=template2tax_code,
|
|
template2account=template2account,
|
|
context=context, template2tax=template2tax)
|
|
|
|
# Update taxes on accounts
|
|
account_template_obj.update_account_taxes(cursor, user,
|
|
account_template, template2account, template2tax, context=context)
|
|
|
|
# Create tax rules
|
|
template2rule = {}
|
|
tax_rule_template_ids = tax_rule_template_obj.search(cursor, user, [
|
|
('account', '=', datas['form']['account_template']),
|
|
], context=context)
|
|
for tax_rule_template in tax_rule_template_obj.browse(cursor, user,
|
|
tax_rule_template_ids, context=context):
|
|
tax_rule_template_obj.create_rule(cursor, user, tax_rule_template,
|
|
datas['form']['company'], context=context,
|
|
template2rule=template2rule)
|
|
|
|
# Create tax rule lines
|
|
template2rule_line = {}
|
|
tax_rule_line_template_ids = tax_rule_line_template_obj.search(cursor,
|
|
user, [
|
|
('rule.account', '=', datas['form']['account_template']),
|
|
], context=context)
|
|
for tax_rule_line_template in tax_rule_line_template_obj.browse(cursor,
|
|
user, tax_rule_line_template_ids, context=context):
|
|
tax_rule_line_template_obj.create_rule_line(cursor, user,
|
|
tax_rule_line_template, template2tax, template2rule,
|
|
context=context, template2rule_line=template2rule_line)
|
|
|
|
return {'company': datas['form']['company']}
|
|
|
|
def _action_create_properties(self, cursor, user, datas, context=None):
|
|
property_obj = self.pool.get('ir.property')
|
|
model_field_obj = self.pool.get('ir.model.field')
|
|
|
|
account_receivable_field_id = model_field_obj.search(cursor, user, [
|
|
('model.model', '=', 'party.party'),
|
|
('name', '=', 'account_receivable'),
|
|
], limit=1, context=context)[0]
|
|
property_ids = property_obj.search(cursor, user, [
|
|
('field', '=', account_receivable_field_id),
|
|
('res', '=', False),
|
|
('company', '=', datas['form']['company']),
|
|
], context=context)
|
|
property_obj.delete(cursor, 0, property_ids, context=context)
|
|
property_obj.create(cursor, 0, {
|
|
'name': 'account_receivable',
|
|
'field': account_receivable_field_id,
|
|
'value': 'account.account,' + \
|
|
str(datas['form']['account_receivable']),
|
|
'company': datas['form']['company'],
|
|
}, context=context)
|
|
|
|
account_payable_field_id = model_field_obj.search(cursor, user, [
|
|
('model.model', '=', 'party.party'),
|
|
('name', '=', 'account_payable'),
|
|
], limit=1, context=context)[0]
|
|
property_ids = property_obj.search(cursor, user, [
|
|
('field', '=', account_payable_field_id),
|
|
('res', '=', False),
|
|
('company', '=', datas['form']['company']),
|
|
], context=context)
|
|
property_obj.delete(cursor, 0, property_ids, context=context)
|
|
property_obj.create(cursor, 0, {
|
|
'name': 'account_payable',
|
|
'field': account_payable_field_id,
|
|
'value': 'account.account,' + \
|
|
str(datas['form']['account_payable']),
|
|
'company': datas['form']['company'],
|
|
}, context=context)
|
|
return {}
|
|
|
|
CreateChartAccount()
|
|
|
|
|
|
class UpdateChartAccountInit(ModelView):
|
|
'Update Chart Account from Template Init'
|
|
_name = 'account.account.update_chart_account.init'
|
|
_description = __doc__
|
|
account = fields.Many2One('account.account', 'Root Account',
|
|
required=True, domain=[('parent', '=', False)])
|
|
|
|
UpdateChartAccountInit()
|
|
|
|
|
|
class UpdateChartAccountStart(ModelView):
|
|
'Update Chart Account from Template Start'
|
|
_name = 'account.account.update_chart_account.start'
|
|
_description = __doc__
|
|
|
|
UpdateChartAccountStart()
|
|
|
|
|
|
class UpdateChartAccount(Wizard):
|
|
'Update Chart Account from Template'
|
|
_name = 'account.account.update_chart_account'
|
|
states = {
|
|
'init': {
|
|
'result': {
|
|
'type': 'form',
|
|
'object': 'account.account.update_chart_account.init',
|
|
'state': [
|
|
('end', 'Cancel', 'tryton-cancel'),
|
|
('start', 'Ok', 'tryton-ok', True),
|
|
],
|
|
},
|
|
},
|
|
'start': {
|
|
'actions': ['_action_update_account'],
|
|
'result': {
|
|
'type': 'form',
|
|
'object': 'account.account.update_chart_account.start',
|
|
'state': [
|
|
('end', 'Ok', 'tryton-ok', True),
|
|
],
|
|
},
|
|
},
|
|
}
|
|
|
|
def _action_update_account(self, cursor, user, datas, context=None):
|
|
account_type_obj = self.pool.get('account.account.type')
|
|
account_type_template_obj = \
|
|
self.pool.get('account.account.type.template')
|
|
account_obj = self.pool.get('account.account')
|
|
account_template_obj = self.pool.get('account.account.template')
|
|
tax_code_obj = self.pool.get('account.tax.code')
|
|
tax_code_template_obj = self.pool.get('account.tax.code.template')
|
|
tax_obj = self.pool.get('account.tax')
|
|
tax_template_obj = self.pool.get('account.tax.template')
|
|
tax_rule_obj = self.pool.get('account.tax.rule')
|
|
tax_rule_template_obj = self.pool.get('account.tax.rule.template')
|
|
tax_rule_line_obj = self.pool.get('account.tax.rule.line')
|
|
tax_rule_line_template_obj = \
|
|
self.pool.get('account.tax.rule.line.template')
|
|
|
|
account = account_obj.browse(cursor, user, datas['form']['account'],
|
|
context=context)
|
|
|
|
# Update account types
|
|
template2type = {}
|
|
account_type_obj.update_type(cursor, user, account.type,
|
|
context=context, template2type=template2type)
|
|
# Create missing account types
|
|
if account.type.template:
|
|
account_type_template_obj.create_type(cursor, user,
|
|
account.type.template, account.company.id, context=context,
|
|
template2type=template2type)
|
|
|
|
# Update accounts
|
|
template2account = {}
|
|
account_obj.update_account(cursor, user, account, context=context,
|
|
template2account=template2account, template2type=template2type)
|
|
# Create missing accounts
|
|
if account.template:
|
|
account_template_obj.create_account(cursor, user, account.template,
|
|
account.company.id, context=context,
|
|
template2account=template2account,
|
|
template2type=template2type)
|
|
|
|
# Update tax codes
|
|
template2tax_code = {}
|
|
tax_code_ids = tax_code_obj.search(cursor, user, [
|
|
('company', '=', account.company.id),
|
|
('parent', '=', False),
|
|
], context=context)
|
|
for tax_code in tax_code_obj.browse(cursor, user, tax_code_ids,
|
|
context=context):
|
|
tax_code_obj.update_tax_code(cursor, user, tax_code, context=context,
|
|
template2tax_code=template2tax_code)
|
|
# Create missing tax codes
|
|
if account.template:
|
|
tax_code_template_ids = tax_code_template_obj.search(cursor, user, [
|
|
('account', '=', account.template.id),
|
|
('parent', '=', False),
|
|
], context=context)
|
|
for tax_code_template in tax_code_template_obj.browse(cursor, user,
|
|
tax_code_template_ids, context=context):
|
|
tax_code_template_obj.create_tax_code(cursor, user,
|
|
tax_code_template, account.company.id, context=context,
|
|
template2tax_code=template2tax_code)
|
|
|
|
# Update taxes
|
|
template2tax = {}
|
|
tax_ids = tax_obj.search(cursor, user, [
|
|
('company', '=', account.company.id),
|
|
('parent', '=', False),
|
|
], context=context)
|
|
for tax in tax_obj.browse(cursor, user, tax_ids, context=context):
|
|
tax_obj.update_tax(cursor, user, tax,
|
|
template2tax_code=template2tax_code,
|
|
template2account=template2account,
|
|
context=context,
|
|
template2tax=template2tax)
|
|
# Create missing taxes
|
|
if account.template:
|
|
tax_template_ids = tax_template_obj.search(cursor, user, [
|
|
('account', '=', account.template.id),
|
|
('parent', '=', False),
|
|
], context=context)
|
|
for tax_template in tax_template_obj.browse(cursor, user,
|
|
tax_template_ids, context=context):
|
|
tax_template_obj.create_tax(cursor, user, tax_template,
|
|
account.company.id, template2tax_code=template2tax_code,
|
|
template2account=template2account, context=context,
|
|
template2tax=template2tax)
|
|
|
|
# Update taxes on accounts
|
|
account_obj.update_account_taxes(cursor, user, account,
|
|
template2account, template2tax, context=context)
|
|
|
|
# Update tax rules
|
|
template2rule = {}
|
|
tax_rule_ids = tax_rule_obj.search(cursor, user, [
|
|
('company', '=', account.company.id),
|
|
], context=context)
|
|
for tax_rule in tax_rule_obj.browse(cursor, user, tax_rule_ids,
|
|
context=context):
|
|
tax_rule_obj.update_rule(cursor, user, tax_rule, context=context,
|
|
template2rule=template2rule)
|
|
# Create missing tax rules
|
|
if account.template:
|
|
tax_rule_template_ids = tax_rule_template_obj.search(cursor, user, [
|
|
('account', '=', account.template.id),
|
|
], context=context)
|
|
for tax_rule_template in tax_rule_template_obj.browse(cursor, user,
|
|
tax_rule_template_ids, context=context):
|
|
tax_rule_template_obj.create_rule(cursor, user,
|
|
tax_rule_template, account.company.id, context=context,
|
|
template2rule=template2rule)
|
|
|
|
# Update tax rule lines
|
|
template2rule_line = {}
|
|
tax_rule_line_ids = tax_rule_line_obj.search(cursor, user, [
|
|
('rule.company', '=', account.company.id),
|
|
], context=context)
|
|
for tax_rule_line in tax_rule_line_obj.browse(cursor, user,
|
|
tax_rule_line_ids, context=context):
|
|
tax_rule_line_obj.update_rule_line(cursor, user, tax_rule_line,
|
|
template2tax, template2rule, context=context,
|
|
template2rule_line=template2rule_line)
|
|
# Create missing tax rule lines
|
|
if account.template:
|
|
tax_rule_line_template_ids = tax_rule_line_template_obj.search(
|
|
cursor, user, [
|
|
('rule.account', '=', account.template.id),
|
|
], context=context)
|
|
for tax_rule_line_template in tax_rule_line_template_obj.browse(
|
|
cursor, user, tax_rule_line_template_ids, context=context):
|
|
tax_rule_line_template_obj.create_rule_line(cursor, user,
|
|
tax_rule_line_template, template2tax, template2rule,
|
|
context=context, template2rule_line=template2rule_line)
|
|
return {}
|
|
|
|
UpdateChartAccount()
|
|
|
|
|
|
class OpenThirdPartyBalanceInit(ModelView):
|
|
'Open Third Party Balance Init'
|
|
_name = 'account.account.open_third_party_balance.init'
|
|
_description = __doc__
|
|
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')
|
|
|
|
|
|
def default_fiscalyear(self, cursor, user, context=None):
|
|
fiscalyear_obj = self.pool.get('account.fiscalyear')
|
|
if context is None:
|
|
context = {}
|
|
fiscalyear_id = fiscalyear_obj.find(cursor, user,
|
|
context.get('company', False), exception=False, context=context)
|
|
if fiscalyear_id:
|
|
return fiscalyear_id
|
|
return False
|
|
|
|
def default_posted(self, cursor, user, context=None):
|
|
return False
|
|
|
|
def default_company(self, cursor, user, context=None):
|
|
if context is None:
|
|
context = {}
|
|
if context.get('company'):
|
|
return context['company']
|
|
return False
|
|
|
|
OpenThirdPartyBalanceInit()
|
|
|
|
|
|
class OpenThirdPartyBalance(Wizard):
|
|
'Open Third Party Balance'
|
|
_name = 'account.account.open_third_party_balance'
|
|
states = {
|
|
'init': {
|
|
'result': {
|
|
'type': 'form',
|
|
'object': 'account.account.open_third_party_balance.init',
|
|
'state': [
|
|
('end', 'Cancel', 'tryton-cancel'),
|
|
('print', 'Print', 'tryton-ok', True),
|
|
],
|
|
},
|
|
},
|
|
'print': {
|
|
'result': {
|
|
'type': 'print',
|
|
'report': 'account.account.third_party_balance',
|
|
'state': 'end',
|
|
},
|
|
},
|
|
}
|
|
|
|
OpenThirdPartyBalance()
|
|
|
|
|
|
class ThirdPartyBalance(Report):
|
|
_name = 'account.account.third_party_balance'
|
|
|
|
def parse(self, cursor, user, report, objects, datas, context):
|
|
party_obj = self.pool.get('party.party')
|
|
move_line_obj = self.pool.get('account.move.line')
|
|
company_obj = self.pool.get('company.company')
|
|
date_obj = self.pool.get('ir.date')
|
|
context = context.copy()
|
|
|
|
company = company_obj.browse(cursor, user,
|
|
datas['form']['company'], context=context)
|
|
context['company'] = company
|
|
context['digits'] = company.currency.digits
|
|
context['fiscalyear'] = datas['form']['fiscalyear']
|
|
line_query, _ = move_line_obj.query_get(cursor, user, context=context)
|
|
if datas['form']['posted']:
|
|
posted_clause = "AND m.state = 'posted' "
|
|
else:
|
|
posted_clause = ""
|
|
|
|
cursor.execute('SELECT l.party, SUM(l.debit), SUM(l.credit) ' \
|
|
'FROM account_move_line l ' \
|
|
'JOIN account_move m ON (l.move = m.id) '
|
|
'JOIN account_account a ON (l.account = a.id) '
|
|
'WHERE l.party IS NOT NULL '\
|
|
'AND a.active ' \
|
|
'AND a.kind IN (\'payable\',\'receivable\') ' \
|
|
'AND l.reconciliation IS NULL ' \
|
|
'AND a.company = %s ' \
|
|
'AND (l.maturity_date <= %s ' \
|
|
'OR l.maturity_date IS NULL) '\
|
|
'AND ' + line_query + ' ' \
|
|
+ posted_clause + \
|
|
'GROUP BY l.party ' \
|
|
'HAVING (SUM(l.debit) != 0 OR SUM(l.credit) != 0)',
|
|
(datas['form']['company'], date_obj.today(cursor, user,
|
|
context=context)))
|
|
|
|
res = cursor.fetchall()
|
|
id2party = {}
|
|
for party in party_obj.browse(cursor, user, [x[0] for x in res],
|
|
context=context):
|
|
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']))
|
|
context['total_debit'] = sum((x['debit'] for x in objects))
|
|
context['total_credit'] = sum((x['credit'] for x in objects))
|
|
context['total_solde'] = sum((x['solde'] for x in objects))
|
|
|
|
return super(ThirdPartyBalance, self).parse(cursor, user, report,
|
|
objects, datas, context)
|
|
|
|
ThirdPartyBalance()
|
|
|
|
|
|
class OpenAgedBalanceInit(ModelView):
|
|
'Open Aged Balance Init'
|
|
_name = 'account.account.open_aged_balance.init'
|
|
_description = __doc__
|
|
company = fields.Many2One('company.company', 'Company', required=True)
|
|
fiscalyear = fields.Many2One('account.fiscalyear', 'Fiscal Year',
|
|
required=True)
|
|
balance_type = fields.Selection(
|
|
[('customer', 'Customer'), ('supplier', 'Supplier'), ('both', 'Both')],
|
|
"Type", required=True)
|
|
term1 = fields.Integer("First Term", required=True)
|
|
term2 = fields.Integer("Second Term", required=True)
|
|
term3 = fields.Integer("Third Term", required=True)
|
|
unit = fields.Selection(
|
|
[('day', 'Day'), ('month', 'Month')], "Unit", required=True)
|
|
posted = fields.Boolean('Posted Move', help='Show only posted move')
|
|
|
|
def default_fiscalyear(self, cursor, user, context=None):
|
|
fiscalyear_obj = self.pool.get('account.fiscalyear')
|
|
if context is None:
|
|
context = {}
|
|
fiscalyear_id = fiscalyear_obj.find(cursor, user,
|
|
context.get('company', False), exception=False, context=context)
|
|
if fiscalyear_id:
|
|
return fiscalyear_id
|
|
return False
|
|
|
|
def default_balance_type(self, cursor, user, context=None):
|
|
return "customer"
|
|
|
|
def default_posted(self, cursor, user, context=None):
|
|
return False
|
|
|
|
def default_term1(self, cursor, user, context=None):
|
|
return 30
|
|
|
|
def default_term2(self, cursor, user, context=None):
|
|
return 60
|
|
|
|
def default_term3(self, cursor, user, context=None):
|
|
return 90
|
|
|
|
def default_unit(self, cursor, user, context=None):
|
|
return 'day'
|
|
|
|
def default_company(self, cursor, user, context=None):
|
|
if context is None:
|
|
context = {}
|
|
if context.get('company'):
|
|
return context['company']
|
|
return False
|
|
|
|
OpenAgedBalanceInit()
|
|
|
|
|
|
class OpenAgedBalance(Wizard):
|
|
'Open Aged Party Balance'
|
|
_name = 'account.account.open_aged_balance'
|
|
|
|
states = {
|
|
'init': {
|
|
'result': {
|
|
'type': 'form',
|
|
'object': 'account.account.open_aged_balance.init',
|
|
'state': [
|
|
('end', 'Cancel', 'tryton-cancel'),
|
|
('print', 'Print', 'tryton-ok', True),
|
|
],
|
|
},
|
|
},
|
|
'print': {
|
|
'actions': ['check',],
|
|
'result': {
|
|
'type': 'print',
|
|
'report': 'account.account.aged_balance',
|
|
'state': 'end',
|
|
},
|
|
},
|
|
}
|
|
|
|
def __init__(self):
|
|
super(OpenAgedBalance, self).__init__()
|
|
self._error_messages.update({
|
|
'warning': 'Warning',
|
|
'term_overlap_desc': 'You cannot define overlapping terms'})
|
|
|
|
def check(self, cursor, user, datas, context=None):
|
|
if not (datas['form']['term1'] < datas['form']['term2'] \
|
|
< datas['form']['term3']):
|
|
self.raise_user_error(cursor, error="warning",
|
|
error_description="term_overlap_desc")
|
|
return datas['form']
|
|
|
|
OpenAgedBalance()
|
|
|
|
|
|
class AgedBalance(Report):
|
|
_name = 'account.account.aged_balance'
|
|
|
|
def parse(self, cursor, user, report, objects, datas, context):
|
|
party_obj = self.pool.get('party.party')
|
|
move_line_obj = self.pool.get('account.move.line')
|
|
company_obj = self.pool.get('company.company')
|
|
date_obj = self.pool.get('ir.date')
|
|
|
|
company = company_obj.browse(cursor, user,
|
|
datas['form']['company'], context=context)
|
|
context['digits'] = company.currency.digits
|
|
context['fiscalyear'] = datas['form']['fiscalyear']
|
|
context['posted'] = datas['form']['posted']
|
|
line_query, _ = move_line_obj.query_get(cursor, user, context=context)
|
|
|
|
terms = (datas['form']['term1'],
|
|
datas['form']['term2'],
|
|
datas['form']['term3'])
|
|
if datas['form']['unit'] == 'month':
|
|
coef = 30
|
|
else:
|
|
coef = 1
|
|
|
|
kind = {'both': ('payable','receivable'),
|
|
'supplier': ('payable',),
|
|
'customer': ('receivable',),
|
|
}[datas['form']['balance_type']]
|
|
|
|
res = {}
|
|
for position,term in enumerate(terms):
|
|
if position == 0:
|
|
term_query = '(l.maturity_date <= %s '\
|
|
'OR l.maturity_date IS NULL) '
|
|
term_args = (date_obj.today(cursor, user, context=context) + \
|
|
datetime.timedelta(days=term*coef),)
|
|
else:
|
|
term_query = '(l.maturity_date <= %s '\
|
|
'AND l.maturity_date >= %s) '
|
|
term_args = (
|
|
date_obj.today(cursor, user, context=context) + \
|
|
datetime.timedelta(days=term*coef),
|
|
date_obj.today(cursor, user, context=context) + \
|
|
datetime.timedelta(days=terms[position-1]*coef),
|
|
)
|
|
|
|
cursor.execute('SELECT l.party, SUM(l.debit) - SUM(l.credit) ' \
|
|
'FROM account_move_line l ' \
|
|
'JOIN account_move m ON (l.move = m.id) '
|
|
'JOIN account_account a ON (l.account = a.id) '
|
|
'WHERE l.party IS NOT NULL '\
|
|
'AND a.active ' \
|
|
'AND a.kind IN ('+ ','.join(('%s',) * len(kind)) + ") "\
|
|
'AND l.reconciliation IS NULL ' \
|
|
'AND a.company = %s ' \
|
|
'AND '+ term_query+\
|
|
'AND ' + line_query + ' ' \
|
|
'GROUP BY l.party ' \
|
|
'HAVING (SUM(l.debit) - SUM(l.credit) != 0)',
|
|
kind + (datas['form']['company'],) + term_args)
|
|
for party, solde in cursor.fetchall():
|
|
if party in res:
|
|
res[party][position] = solde
|
|
else:
|
|
res[party] = [(i[0] == position) and solde \
|
|
or Decimal("0.0") for i in enumerate(terms)]
|
|
party_ids = party_obj.search(cursor, user, [
|
|
('id', 'in', [k for k in res.iterkeys()]),
|
|
], context=context)
|
|
parties = party_obj.browse(cursor, user, party_ids, context=context)
|
|
|
|
context['main_title'] = datas['form']['balance_type']
|
|
context['unit'] = datas['form']['unit']
|
|
for i in range(3):
|
|
context['total' + str(i)] = sum((v[i] for v in res.itervalues()))
|
|
context['term' + str(i)] = terms[i]
|
|
|
|
context['company'] = company
|
|
context['parties']= [{
|
|
'name': p.rec_name,
|
|
'amount0': res[p.id][0],
|
|
'amount1': res[p.id][1],
|
|
'amount2': res[p.id][2],
|
|
} for p in parties]
|
|
|
|
return super(AgedBalance, self).parse(cursor, user, report, objects,
|
|
datas, context)
|
|
|
|
AgedBalance()
|