From e9f3f92a8c92282628fa163ef5412e9d998e2b2e Mon Sep 17 00:00:00 2001 From: Fabien Pinckaers Date: Fri, 25 May 2007 06:52:02 +0000 Subject: [PATCH] New modules: Account simulation You can create as many simulation level as needed You can check journals as simulation journals or real journals You can use and print report Very usefull for IFRS, multiple manner to asset some entries Asset management module Multiple ventilations for an asset Link with the accounting L10N_CH Removed ZIP code by default Account cleaned Use a function for a domain on computed fields and visibility bzr revid: fp@tinyerp.com-e382e83f36b19555b678c670d62fad7a2eef1416 --- addons/account/account.py | 17 +- addons/account/account_move_line.py | 5 + addons/account/account_view.xml | 35 +- addons/account/invoice.py | 56 +-- addons/account/partner.py | 12 +- addons/account/transfer.py | 6 +- addons/account/wizard/wizard_pay_invoice.py | 2 - addons/account_asset/__init__.py | 31 ++ addons/account_asset/__terp__.py | 23 ++ addons/account_asset/account_asset.py | 329 ++++++++++++++++++ addons/account_asset/account_asset_invoice.py | 54 +++ .../account_asset_invoice_view.xml | 22 ++ .../account_asset/account_asset_sequence.py | 17 + addons/account_asset/account_asset_view.xml | 273 +++++++++++++++ addons/account_asset/account_asset_wizard.py | 12 + addons/account_asset/account_asset_wizard.xml | 31 ++ addons/account_asset/wizard/__init__.py | 31 ++ .../wizard/wizard_asset_close.py | 56 +++ .../wizard/wizard_asset_compute.py | 109 ++++++ .../wizard/wizard_asset_modify.py | 93 +++++ addons/account_simulation/__init__.py | 30 ++ addons/account_simulation/__terp__.py | 20 ++ .../account_simulation/account_simulation.py | 88 +++++ .../account_simulation_demo.xml | 16 + .../account_simulation_view.xml | 79 +++++ addons/account_simulation/wizard/__init__.py | 29 ++ .../wizard/wizard_account_chart.py | 81 +++++ .../account_tax_include/invoice_tax_incl.py | 23 +- addons/l10n_ch/__terp__.py | 2 +- 29 files changed, 1516 insertions(+), 66 deletions(-) create mode 100644 addons/account_asset/__init__.py create mode 100644 addons/account_asset/__terp__.py create mode 100644 addons/account_asset/account_asset.py create mode 100644 addons/account_asset/account_asset_invoice.py create mode 100644 addons/account_asset/account_asset_invoice_view.xml create mode 100644 addons/account_asset/account_asset_sequence.py create mode 100644 addons/account_asset/account_asset_view.xml create mode 100644 addons/account_asset/account_asset_wizard.py create mode 100644 addons/account_asset/account_asset_wizard.xml create mode 100644 addons/account_asset/wizard/__init__.py create mode 100644 addons/account_asset/wizard/wizard_asset_close.py create mode 100644 addons/account_asset/wizard/wizard_asset_compute.py create mode 100644 addons/account_asset/wizard/wizard_asset_modify.py create mode 100644 addons/account_simulation/__init__.py create mode 100644 addons/account_simulation/__terp__.py create mode 100644 addons/account_simulation/account_simulation.py create mode 100644 addons/account_simulation/account_simulation_demo.xml create mode 100644 addons/account_simulation/account_simulation_view.xml create mode 100644 addons/account_simulation/wizard/__init__.py create mode 100644 addons/account_simulation/wizard/wizard_account_chart.py diff --git a/addons/account/account.py b/addons/account/account.py index 7113b189a52..869daa85867 100644 --- a/addons/account/account.py +++ b/addons/account/account.py @@ -144,9 +144,9 @@ class account_account(osv.osv): def _credit(self, cr, uid, ids, field_name, arg, context={}): if not 'fiscalyear' in context: context['fiscalyear'] = self.pool.get('account.fiscalyear').find(cr, uid) - acc_set = ",".join(map(str, ids)) - cr.execute("SELECT a.id, COALESCE(SUM(l.credit*a.sign),0) FROM account_account a LEFT JOIN account_move_line l ON (a.id=l.account_id) WHERE a.type!='view' AND a.id IN (%s) AND l.active AND l.state<>'draft' AND l.period_id in (SELECT id from account_period WHERE fiscalyear_id=%d) GROUP BY a.id" % (acc_set, context['fiscalyear'])) + query = self.pool.get('account.move.line')._query_get(cr, uid, context=context) + cr.execute(("SELECT a.id, COALESCE(SUM(l.credit*a.sign),0) FROM account_account a LEFT JOIN account_move_line l ON (a.id=l.account_id) WHERE a.type!='view' AND a.id IN (%s) AND "+query+" GROUP BY a.id") % (acc_set, )) res2 = cr.fetchall() res = {} for id in ids: @@ -160,7 +160,8 @@ class account_account(osv.osv): context['fiscalyear'] = self.pool.get('account.fiscalyear').find(cr, uid) acc_set = ",".join(map(str, ids)) - cr.execute("SELECT a.id, COALESCE(SUM(l.debit*a.sign),0) FROM account_account a LEFT JOIN account_move_line l ON (a.id=l.account_id) WHERE a.type!='view' AND a.id IN (%s) and l.active AND l.state<>'draft' AND l.period_id in (SELECT id from account_period WHERE fiscalyear_id=%d) GROUP BY a.id" % (acc_set, context['fiscalyear'])) + query = self.pool.get('account.move.line')._query_get(cr, uid, context=context) + cr.execute(("SELECT a.id, COALESCE(SUM(l.debit*a.sign),0) FROM account_account a LEFT JOIN account_move_line l ON (a.id=l.account_id) WHERE a.type!='view' AND a.id IN (%s) and "+query+" GROUP BY a.id") % (acc_set, )) res2 = cr.fetchall() res = {} for id in ids: @@ -175,7 +176,8 @@ class account_account(osv.osv): ids2 = self.search(cr, uid, [('parent_id', 'child_of', ids)]) acc_set = ",".join(map(str, ids2)) - cr.execute("SELECT a.id, COALESCE(SUM((l.debit-l.credit)),0) FROM account_account a LEFT JOIN account_move_line l ON (a.id=l.account_id) WHERE a.id IN (%s) and l.active AND l.state<>'draft' AND l.period_id in (SELECT id from account_period WHERE fiscalyear_id=%d) GROUP BY a.id" % (acc_set, context['fiscalyear'])) + query = self.pool.get('account.move.line')._query_get(cr, uid, context=context) + cr.execute(("SELECT a.id, COALESCE(SUM((l.debit-l.credit)),0) FROM account_account a LEFT JOIN account_move_line l ON (a.id=l.account_id) WHERE a.id IN (%s) and "+query+" GROUP BY a.id") % (acc_set, )) res = {} for account_id, sum in cr.fetchall(): res[account_id] = round(sum,2) @@ -293,7 +295,6 @@ class account_account(osv.osv): return super(account_account, self).copy(cr, uid, id, default, context=context) account_account() - class account_journal_view(osv.osv): _name = "account.journal.view" _description = "Journal View" @@ -326,7 +327,6 @@ class account_journal_column(osv.osv): _order = "sequence" account_journal_column() - class account_journal(osv.osv): _name = "account.journal" _description = "Journal" @@ -462,6 +462,11 @@ class account_period(osv.osv): 'state': lambda *a: 'draft', } _order = "date_start" + def next(self, cr, uid, period, step, context={}): + ids = self.search(cr, uid, [('date_start','>',period.date_start)]) + if len(ids)>=step: + return ids[step-1] + return False def find(self, cr, uid, dt=None, context={}): if not dt: diff --git a/addons/account/account_move_line.py b/addons/account/account_move_line.py index 5c5a7f422f9..62bdcbf7438 100644 --- a/addons/account/account_move_line.py +++ b/addons/account/account_move_line.py @@ -36,6 +36,11 @@ class account_move_line(osv.osv): _name = "account.move.line" _description = "Entry lines" + def _query_get(self, cr, uid, obj='l', context={}): + if not 'fiscalyear' in context: + context['fiscalyear'] = self.pool.get('account.fiscalyear').find(cr, uid) + return "l.active AND l.state<>'draft' AND l.period_id in (SELECT id from account_period WHERE fiscalyear_id=%d)" % (context['fiscalyear'] ,) + def default_get(self, cr, uid, fields, context={}): data = self._default_get(cr, uid, fields, context) for f in data.keys(): diff --git a/addons/account/account_view.xml b/addons/account/account_view.xml index 39b4e536bd2..0152296abd4 100644 --- a/addons/account/account_view.xml +++ b/addons/account/account_view.xml @@ -531,6 +531,8 @@ + + @@ -744,6 +746,7 @@ + @@ -763,22 +766,22 @@ - + - - + + - + - - + + @@ -786,7 +789,7 @@ - + @@ -808,29 +811,29 @@ - + - + - + - - + + - + - + - + @@ -870,7 +873,7 @@ - + diff --git a/addons/account/invoice.py b/addons/account/invoice.py index 7c9354e2611..ef8530c7fac 100644 --- a/addons/account/invoice.py +++ b/addons/account/invoice.py @@ -394,20 +394,7 @@ class account_invoice(osv.osv): date = inv.date_invoice part = inv.partner_id.id - line = map(lambda x:(0,0,{ - 'date':date, - 'date_maturity': x.get('date_maturity', False), - 'partner_id':part, - 'name':x['name'], - 'debit':x['price']>0 and x['price'], - 'credit':x['price']<0 and -x['price'], - 'account_id':x['account_id'], - 'analytic_lines':x.get('analytic_lines', []), - 'amount_currency':x.get('amount_currency', False), - 'currency_id':x.get('currency_id', False), - 'tax_code_id': x.get('tax_code_id', False), - 'tax_amount': x.get('tax_amount', False), - 'ref':x.get('ref',False) }) ,iml) + line = map(lambda x:(0,0,self.line_get_convert(cr, uid, x, part, date, context={})) ,iml) journal_id = inv.journal_id.id #self._get_journal(cr, uid, {'type': inv['type']}) journal = self.pool.get('account.journal').browse(cr, uid, journal_id) @@ -427,6 +414,23 @@ class account_invoice(osv.osv): self._log_event(cr, uid, ids) return True + def line_get_convert(self, cr, uid, x, part, date, context={}): + return { + 'date':date, + 'date_maturity': x.get('date_maturity', False), + 'partner_id':part, + 'name':x['name'], + 'debit':x['price']>0 and x['price'], + 'credit':x['price']<0 and -x['price'], + 'account_id':x['account_id'], + 'analytic_lines':x.get('analytic_lines', []), + 'amount_currency':x.get('amount_currency', False), + 'currency_id':x.get('currency_id', False), + 'tax_code_id': x.get('tax_code_id', False), + 'tax_amount': x.get('tax_amount', False), + 'ref':x.get('ref',False) + } + def action_number(self, cr, uid, ids, *args): cr.execute('SELECT id, type, number, move_id FROM account_invoice WHERE id IN ('+','.join(map(str,ids))+')') for (id, invtype, number, move_id) in cr.fetchall(): @@ -705,17 +709,7 @@ class account_invoice_line(osv.osv): cur = inv.currency_id for line in inv.invoice_line: - res.append( { - 'type':'src', - 'name':line.name, - 'price_unit':line.price_unit, - 'quantity':line.quantity, - 'price':line.price_subtotal, - 'account_id':line.account_id.id, - 'product_id':line.product_id.id, - 'uos_id':line.uos_id.id, - 'account_analytic_id':line.account_analytic_id.id, - }) + res.append( self.move_line_get_item(cr, uid, line, context)) for tax in tax_obj.compute(cr, uid, line.invoice_line_tax_id, (line.price_unit *(1.0-(line['discount'] or 0.0)/100.0)), line.quantity, inv.address_invoice_id.id, line.product_id, inv.partner_id): if inv.type in ('out_invoice', 'in_invoice'): res[-1]['tax_code_id'] = tax['base_code_id'] @@ -725,6 +719,18 @@ class account_invoice_line(osv.osv): res[-1]['tax_amount'] = tax['price_unit'] * line['quantity'] * tax['ref_base_sign'] return res + def move_line_get_item(self, cr, uid, line, context={}): + return { + 'type':'src', + 'name':line.name, + 'price_unit':line.price_unit, + 'quantity':line.quantity, + 'price':line.price_subtotal, + 'account_id':line.account_id.id, + 'product_id':line.product_id.id, + 'uos_id':line.uos_id.id, + 'account_analytic_id':line.account_analytic_id.id, + } # # Set the tax field according to the account and the partner # diff --git a/addons/account/partner.py b/addons/account/partner.py index 2dda66d95cb..de1d162f703 100644 --- a/addons/account/partner.py +++ b/addons/account/partner.py @@ -41,7 +41,8 @@ class res_partner(osv.osv): for partner in self.browse(cr, uid, ids, context): id = partner.id acc = partner.property_account_receivable[0] - cr.execute("select sum(debit-credit) from account_move_line where account_id=%d and partner_id=%d and reconcile_id is null and state<>'draft'", (acc, id)) + query = self.pool.get('account.move.line')._query_get(cr, uid, context=context) + cr.execute(("select sum(debit-credit) from account_move_line l where account_id=%d and partner_id=%d and reconcile_id is null and "+query), (acc, id)) res[id]=cr.fetchone()[0] or 0.0 except: for id in ids: @@ -54,7 +55,8 @@ class res_partner(osv.osv): for partner in self.browse(cr, uid, ids, context): id = partner.id acc = partner.property_account_payable[0] - cr.execute("select sum(debit-credit) from account_move_line where account_id=%d and partner_id=%d and reconcile_id is null and state<>'draft'", (acc, id)) + query = self.pool.get('account.move.line')._query_get(cr, uid, context=context) + cr.execute(("select sum(debit-credit) from account_move_line where account_id=%d and partner_id=%d and reconcile_id is null and "+query), (acc, id)) res[id]=cr.fetchone()[0] or 0.0 except: for id in ids: @@ -65,7 +67,8 @@ class res_partner(osv.osv): if not len(args): return [] where = ' and '.join(map(lambda x: '(sum(debit-credit)'+x[1]+str(x[2])+')',args)) - cr.execute('select partner_id from account_move_line where account_id in (select id from account_account where type=%s) and reconcile_id is null and state<>\'draft\' and partner_id is not null group by partner_id having '+where, ('receivable',) ) + query = self.pool.get('account.move.line')._query_get(cr, uid, context={}) + cr.execute(('select partner_id from account_move_line l where account_id in (select id from account_account where type=%s) and reconcile_id is null and '+query+' and partner_id is not null group by partner_id having '+where), ('receivable',) ) res = cr.fetchall() if not len(res): return [('id','=','0')] @@ -74,8 +77,9 @@ class res_partner(osv.osv): def _debit_search(self, cr, uid, obj, name, args): if not len(args): return [] + query = self.pool.get('account.move.line')._query_get(cr, uid, context={}) where = ' and '.join(map(lambda x: '(sum(debit-credit)'+x[1]+str(x[2])+')',args)) - cr.execute('select partner_id from account_move_line where account_id in (select id from account_account where type=%s) and reconcile_id is null and state<>\'draft\'and partner_id is not null group by partner_id having '+where, ('payable',) ) + cr.execute(('select partner_id from account_move_line where account_id in (select id from account_account where type=%s) and reconcile_id is null and '+query+' partner_id is not null group by partner_id having '+where), ('payable',) ) res = cr.fetchall() if not len(res): return [('id','=','0')] diff --git a/addons/account/transfer.py b/addons/account/transfer.py index 325ca37a9d1..e50a2c8fcde 100644 --- a/addons/account/transfer.py +++ b/addons/account/transfer.py @@ -138,7 +138,8 @@ class account_transfer(osv.osv): value['account_dest_id'] = False # compute the amount this partner owe us (the sum of all move lines which have not been matched) - cr.execute("SELECT COALESCE(SUM(debit-credit),0) from account_move_line where account_id=%d and partner_id=%d and reconcile_id is null and state<>'draft'", (a, partner_id)) + query = self.pool.get('account.move.line')._query_get(cr, uid, context={}) + cr.execute(("SELECT COALESCE(SUM(debit-credit),0) from account_move_line l where account_id=%d and partner_id=%d and reconcile_id is null and "+query), (a, partner_id)) value['amount'] = cr.fetchone()[0] d = self._onchange_account_domain(cr,uid,ids,type, value['account_src_id'], value['account_dest_id']) @@ -150,7 +151,8 @@ class account_transfer(osv.osv): value['account_dest_id'] = a # compute the amount we owe this partner (the sum of all move lines which have not been matched) - cr.execute("SELECT COALESCE(SUM(debit-credit),0) from account_move_line where account_id=%d and partner_id=%d and reconcile_id is null and state<>'draft'", (a,partner_id)) + query = self.pool.get('account.move.line')._query_get(cr, uid, context={}) + cr.execute(("SELECT COALESCE(SUM(debit-credit),0) from account_move_line where account_id=%d and partner_id=%d and reconcile_id is null and "+query), (a,partner_id)) value['amount'] = -cr.fetchone()[0] # get the new domain diff --git a/addons/account/wizard/wizard_pay_invoice.py b/addons/account/wizard/wizard_pay_invoice.py index da578d235ca..ad98e32e785 100644 --- a/addons/account/wizard/wizard_pay_invoice.py +++ b/addons/account/wizard/wizard_pay_invoice.py @@ -27,8 +27,6 @@ import wizard import netsvc -import osv -import time import pooler pay_form = ''' diff --git a/addons/account_asset/__init__.py b/addons/account_asset/__init__.py new file mode 100644 index 00000000000..37483da67b5 --- /dev/null +++ b/addons/account_asset/__init__.py @@ -0,0 +1,31 @@ +############################################################################## +# +# Copyright (c) 2004 TINY SPRL. (http://tiny.be) All Rights Reserved. +# Fabien Pinckaers +# +# WARNING: This program as such is intended to be used by professional +# programmers who take the whole responsability of assessing all potential +# consequences resulting from its eventual inadequacies and bugs +# End users who are looking for a ready-to-use solution with commercial +# garantees and support are strongly adviced to contract a Free Software +# Service Company +# +# This program is Free Software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +############################################################################## + +import account_asset +import account_asset_invoice +import wizard diff --git a/addons/account_asset/__terp__.py b/addons/account_asset/__terp__.py new file mode 100644 index 00000000000..bf8b68c53fc --- /dev/null +++ b/addons/account_asset/__terp__.py @@ -0,0 +1,23 @@ +{ + "name" : "Asset management", + "version" : "1.0", + "depends" : ["account", "account_simulation"], + "author" : "Tiny", + "description": """Financial and accounting asset management.""", + "website" : "http://tinyerp.com/module_account.html", + "category" : "Generic Modules/Accounting", + "init_xml" : [ + ], + "demo_xml" : [ + ], + "update_xml" : [ + "account_asset_wizard.xml", + "account_asset_view.xml", + "account_asset_invoice_view.xml" + ], +# "translations" : { +# "fr": "i18n/french_fr.csv" +# }, + "active": False, + "installable": True +} diff --git a/addons/account_asset/account_asset.py b/addons/account_asset/account_asset.py new file mode 100644 index 00000000000..27677e2cc1d --- /dev/null +++ b/addons/account_asset/account_asset.py @@ -0,0 +1,329 @@ +############################################################################## +# +# Copyright (c) 2004-2006 TINY SPRL. (http://tiny.be) All Rights Reserved. +# +# $Id: product.py 1310 2005-09-08 20:40:15Z pinky $ +# +# WARNING: This program as such is intended to be used by professional +# programmers who take the whole responsability of assessing all potential +# consequences resulting from its eventual inadequacies and bugs +# End users who are looking for a ready-to-use solution with commercial +# garantees and support are strongly adviced to contract a Free Software +# Service Company +# +# This program is Free Software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +############################################################################## + +from osv import osv, fields +import time +class account_asset_category(osv.osv): + _name = 'account.asset.category' + _description = 'Asset category' + _columns = { + 'name': fields.char('Asset category', size=64, required=True, select=1), + 'code': fields.char('Asset code', size=16, select=1), + 'note': fields.text('Note'), + } +account_asset_category() + +class account_asset_asset(osv.osv): + _name = 'account.asset.asset' + _description = 'Asset' + +# def _balance(self, cr, uid, ids, field_name, arg, context={}): +# acc_set = ",".join(map(str, ids)) +# query = self.pool.get('account.move.line')._query_get(cr, uid, context=context) +# cr.execute(("SELECT a.id, COALESCE(SUM((l.debit-l.credit)),0) FROM account_asset_asset a LEFT JOIN account_move_line l ON (a.id=l.asset_account_id) WHERE a.id IN (%s) and "+query+" GROUP BY a.id") % (acc_set,)) +# res = {} +# for account_id, sum in cr.fetchall(): +# res[account_id] = round(sum,2) +# for id in ids: +# res[id] = round(res.get(id,0.0), 2) +# return res + def _get_period(self, cr, uid, context={}): + print context + periods = self.pool.get('account.period').find(cr, uid) + if periods: + return periods[0] + else: + return False + + def validate(self, cr, uid, ids, context={}): + for asset in self.browse(cr, uid, ids, context): + for prop in asset.property_ids: + if prop.state=='draft': + self.pool.get('account.asset.property').write(cr, uid, [prop.id], {'state':'open'}, context) + return self.write(cr, uid, ids, { + 'state':'normal' + }, context) + + def _amount_total(self, cr, uid, ids, name, args, context={}): + id_set=",".join(map(str,ids)) + cr.execute("""SELECT l.asset_id,abs(SUM(l.debit-l.credit)) AS amount FROM + account_move_line l + WHERE l.asset_id IN ("""+id_set+") GROUP BY l.asset_id ") + res=dict(cr.fetchall()) + for id in ids: + res.setdefault(id, 0.0) + return res + _columns = { + 'name': fields.char('Asset', size=64, required=True, select=1), + 'code': fields.char('Asset code', size=16, select=1), + 'note': fields.text('Note'), + 'category_id': fields.many2one('account.asset.category', 'Asset category', change_default=True), + 'localisation': fields.char('Localisation', size=32, select=2), + 'sequence': fields.integer('Sequence'), + 'parent_id': fields.many2one('account.asset.asset', 'Parent asset'), + 'child_ids': fields.one2many('account.asset.asset', 'parent_id', 'Childs asset'), + 'date': fields.date('Date', required=True), + 'period_id': fields.many2one('account.period', 'Period', required=True, readonly=True, states={'draft':[('readonly',False)]}), + 'state': fields.selection([('view','View'),('draft','Draft'),('normal','Normal'),('close','Close')], 'Global state', required=True), + 'active': fields.boolean('Active', select=2), + 'partner_id': fields.many2one('res.partner', 'Partner'), + 'entry_ids': fields.one2many('account.move.line', 'asset_id', 'Entries', readonly=True, states={'draft':[('readonly',False)]}), + 'property_ids': fields.one2many('account.asset.property', 'asset_id', 'Asset method name', readonly=True, states={'draft':[('readonly',False)]}), + 'value_total': fields.function(_amount_total, method=True, digits=(16,2),string='Total value'), + } + _defaults = { + 'code': lambda obj, cr, uid, context: obj.pool.get('ir.sequence').get(cr, uid, 'account.asset.code'), + 'date': lambda obj, cr, uid, context: time.strftime('%Y-%m-%d'), + 'active': lambda obj, cr, uid, context: True, + 'state': lambda obj, cr, uid, context: 'draft', + 'period_id': _get_period, + } + def _compute_period(self, cr, uid, property, context={}): + if len(property.entry_asset_ids or [])>=property.method_delay: + return False + if len(property.entry_asset_ids): + cp = property.entry_asset_ids[-1].period_id + cpid = self.pool.get('account.period').next(cr, uid, cp, property.method_period, context) + current_period = self.pool.get('account.period').browse(cr, uid, cpid, context) + + else: + current_period = property.asset_id.period_id + return current_period + + def _compute_move(self, cr, uid, property, period, context={}): + result = [] + total = 0.0 + for move in property.asset_id.entry_ids: + total += move.debit-move.credit + for move in property.entry_asset_ids: + total += move.debit-move.credit + periods = len(property.entry_asset_ids) - property.method_delay + if property.method == 'linear': + amount = total / periods + else: + amount = total / periods + + move_id = self.pool.get('account.move').create(cr, uid, { + 'journal_id': property.journal_id.id, + 'period_id': period.id, + 'name': property.name or property.asset_id.name, + 'ref': property.asset_id.code + }) + result = [move_id] + id = self.pool.get('account.move.line').create(cr, uid, { + 'name': property.name or property.asset_id.name, + 'move_id': move_id, + 'account_id': property.account_asset_id.id, + 'debit': amount>0 and amount or 0.0, + 'credit': amount<0 and -amount or 0.0, + 'ref': property.asset_id.code, + 'period_id': period.id, + 'journal_id': property.journal_id.id, + 'partner_id': property.asset_id.partner_id.id, + 'date': time.strftime('%Y-%m-%d'), + }) + self.pool.get('account.asset.property').write(cr, uid, [property.id], { + 'entry_asset_ids': [(4, id, [])] + }) + id = self.pool.get('account.move.line').create(cr, uid, { + 'name': property.name or property.asset_id.name, + 'move_id': move_id, + 'account_id': property.account_actif_id.id, + 'credit': amount>0 and amount or 0.0, + 'debit': amount<0 and -amount or 0.0, + 'ref': property.asset_id.code, + 'period_id': period.id, + 'journal_id': property.journal_id.id, + 'partner_id': property.asset_id.partner_id.id, + 'date': time.strftime('%Y-%m-%d'), + }) + self.pool.get('account.asset.property').write(cr, uid, [property.id], { + 'entry_actif_ids': [(4, id, False)] + }) + if property.method_delay - len(property.entry_asset_ids)<=1: + self.pool.get('account.asset.property')._close(cr, uid, property, context) + return result + return result + + def _compute_entries(self, cr, uid, asset, period_id, context={}): + result = [] + date_start = self.pool.get('account.period').browse(cr, uid, period_id, context).date_start + print 'compute entries', date_start + for property in asset.property_ids: + if property.state=='open': + print 'Property State Open' + period = self._compute_period(cr, uid, property, context) + print period + print period and period.date_start + if period and (period.date_start<=date_start): + result += self._compute_move(cr, uid, property, period, context) + return result +account_asset_asset() + +class account_asset_property(osv.osv): + def _amount_total(self, cr, uid, ids, name, args, context={}): + id_set=",".join(map(str,ids)) + cr.execute("""SELECT l.asset_id,abs(SUM(l.debit-l.credit)) AS amount FROM + account_asset_property p + left join + account_move_line l on (p.asset_id=l.asset_id) + WHERE p.id IN ("""+id_set+") GROUP BY l.asset_id ") + res=dict(cr.fetchall()) + for id in ids: + res.setdefault(id, 0.0) + return res + + def _amount_residual(self, cr, uid, ids, name, args, context={}): + id_set=",".join(map(str,ids)) + cr.execute("""SELECT + r.asset_property_id,abs(SUM(l.debit-l.credit)) AS amount + FROM + account_move_asset_entry_rel r + LEFT JOIN + account_move_line l on (r.move_id=l.id) + WHERE + r.asset_property_id IN ("""+id_set+") GROUP BY r.asset_property_id ") + res=dict(cr.fetchall()) + for prop in self.browse(cr, uid, ids, context): + res[prop.id] = prop.value_total - res.get(prop.id, 0.0) + for id in ids: + res.setdefault(id, 0.0) + return res + + def _close(self, cr, uid, property, context={}): + if property.state<>'close': + self.pool.get('account.asset.property').write(cr, uid, [property.id], { + 'state': 'close' + }) + property.state='close' + ok = property.asset_id.state=='open' + for prop in property.asset_id.property_ids: + ok = ok and prop.state=='close' + self.pool.get('account.asset.asset').write(cr, uid, [property.asset_id.id], { + 'state': 'close' + }, context) + return True + + _name = 'account.asset.property' + _description = 'Asset property' + _columns = { + 'name': fields.char('Method name', size=64, select=1), + 'type': fields.selection([('direct','Direct'),('indirect','Indirect')], 'Asset type', select=2, required=True), + 'asset_id': fields.many2one('account.asset.asset', 'Asset', required=True), + 'account_asset_id': fields.many2one('account.account', 'Asset account', required=True), + 'account_actif_id': fields.many2one('account.account', 'Actif account', required=True), + 'journal_id': fields.many2one('account.journal', 'Journal', required=True), + 'journal_analytic_id': fields.many2one('account.analytic.journal', 'Analytic journal'), + 'account_analytic_id': fields.many2one('account.analytic.journal', 'Analytic journal'), + + 'method': fields.selection([('linear','Linear'),('progressif','Progressive')], 'Assesment method', required=True), + 'method_time': fields.selection([('delay','Delay'),('end','Ending period')], 'Time Method', required=True), + 'method_delay': fields.integer('Number of interval', readonly=True, states={'draft':[('readonly',False)]}), + 'method_period': fields.integer('Period per interval', readonly=True, states={'draft':[('readonly',False)]}), + 'method_end': fields.date('Ending date'), + + 'date': fields.date('Date created'), + + 'entry_asset_ids': fields.many2many('account.move.line', 'account_move_asset_entry_rel', 'asset_property_id', 'move_id', 'Asset Entries'), + 'entry_actif_ids': fields.many2many('account.move.line', 'account_move_asset_actif_entry_rel', 'asset_property_id', 'move_id', 'Asset Entries'), + 'board_ids': fields.one2many('account.asset.board', 'asset_id', 'Asset board'), + + 'value_total': fields.function(_amount_total, method=True, digits=(16,2),string='Total value'), + 'value_residual': fields.function(_amount_residual, method=True, digits=(16,2), string='Residual value'), + 'state': fields.selection([('draft','Draft'), ('open','Open'), ('close','Close')], 'State', required=True), + 'history_ids': fields.one2many('account.asset.property.history', 'asset_property_id', 'History', readonly=True) + } + _defaults = { + 'type': lambda obj, cr, uid, context: 'direct', + 'state': lambda obj, cr, uid, context: 'draft', + 'method': lambda obj, cr, uid, context: 'linear', + 'method_time': lambda obj, cr, uid, context: 'delay', + 'method_delay': lambda obj, cr, uid, context: 5, + 'method_period': lambda obj, cr, uid, context: 12, + 'date': lambda obj, cr, uid, context: time.strftime('%Y-%m-%d') + } +account_asset_property() + +class account_move_line(osv.osv): + _inherit = 'account.move.line' + _columns = { + 'asset_id': fields.many2one('account.asset.asset', 'Asset', relate=True), + } +account_move_line() + +class account_asset_property_history(osv.osv): + _name = 'account.asset.property.history' + _description = 'Asset history' + _columns = { + 'name': fields.char('History name', size=64, select=1), + 'user_id': fields.many2one('res.users', 'User', required=True), + 'date': fields.date('Date', required=True), + 'asset_property_id': fields.many2one('account.asset.property', 'Property', required=True), + 'method_delay': fields.integer('Number of interval'), + 'method_period': fields.integer('Period per interval'), + 'method_end': fields.date('Ending date'), + 'note': fields.text('Note'), + } + _defaults = { + 'date': lambda *args: time.strftime('%Y-%m-%d'), + 'user_id': lambda self,cr, uid,ctx: uid + } +account_asset_property_history() + + +class account_asset_board(osv.osv): + _name = 'account.asset.board' + _description = 'Asset board' + _columns = { + 'name': fields.char('Asset name', size=64, required=True, select=1), + 'asset_id': fields.many2one('account.asset.property', 'Asset', required=True, select=1), + 'value_gross': fields.float('Gross value', required=True, select=1), + 'value_asset': fields.float('Asset Value', required=True, select=1), + 'value_asset_cumul': fields.float('Cumul. value', required=True, select=1), + 'value_net': fields.float('Net value', required=True, select=1), + } + _auto = False + def init(self, cr): + cr.execute(""" + create or replace view account_asset_board as ( + select + min(l.id) as id, + min(l.id) as asset_id, + 0.0 as value_gross, + 0.0 as value_asset, + 0.0 as value_asset_cumul, + 0.0 as value_net + from + account_move_line l + where + l.state <> 'draft' and + l.asset_id=3 + )""") +account_asset_board() + diff --git a/addons/account_asset/account_asset_invoice.py b/addons/account_asset/account_asset_invoice.py new file mode 100644 index 00000000000..b50cd3723b0 --- /dev/null +++ b/addons/account_asset/account_asset_invoice.py @@ -0,0 +1,54 @@ +############################################################################## +# +# Copyright (c) 2004-2006 TINY SPRL. (http://tiny.be) All Rights Reserved. +# +# $Id: product.py 1310 2005-09-08 20:40:15Z pinky $ +# +# WARNING: This program as such is intended to be used by professional +# programmers who take the whole responsability of assessing all potential +# consequences resulting from its eventual inadequacies and bugs +# End users who are looking for a ready-to-use solution with commercial +# garantees and support are strongly adviced to contract a Free Software +# Service Company +# +# This program is Free Software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +############################################################################## + +from osv import osv, fields +import time + +class account_invoice(osv.osv): + _inherit = 'account.invoice' + def line_get_convert(self, cr, uid, x, part, date, context={}): + print self + res = super(account_invoice, self).line_get_convert(cr, uid, x, part, date, context) + res['asset_id'] = x.get('asset_id', False) + return res +account_invoice() + +class account_invoice_line(osv.osv): + _inherit = 'account.invoice.line' + _columns = { + 'asset_id': fields.many2one('account.asset.asset', 'Asset'), + } + def move_line_get_item(self, cr, uid, line, context={}): + res = super(account_invoice_line, self).move_line_get_item(cr, uid, line, context) + res['asset_id'] = line.asset_id.id or False + if line.asset_id.id and (line.asset_id.state=='draft'): + self.pool.get('account.asset.asset').validate(cr, uid, [line.asset_id.id], context) + return res +account_invoice_line() + diff --git a/addons/account_asset/account_asset_invoice_view.xml b/addons/account_asset/account_asset_invoice_view.xml new file mode 100644 index 00000000000..5958893e670 --- /dev/null +++ b/addons/account_asset/account_asset_invoice_view.xml @@ -0,0 +1,22 @@ + + + + + #--------------------------------------------------------- + # Fiscal Year + #--------------------------------------------------------- + + + account.invoice.line.form + account.invoice.line + + form + + + + + + + + + diff --git a/addons/account_asset/account_asset_sequence.py b/addons/account_asset/account_asset_sequence.py new file mode 100644 index 00000000000..ed4458c841e --- /dev/null +++ b/addons/account_asset/account_asset_sequence.py @@ -0,0 +1,17 @@ + + + + + + Account asset + account.asset.code + + + Account asset + account.asset.code + + + + + + diff --git a/addons/account_asset/account_asset_view.xml b/addons/account_asset/account_asset_view.xml new file mode 100644 index 00000000000..6d493857016 --- /dev/null +++ b/addons/account_asset/account_asset_view.xml @@ -0,0 +1,273 @@ + + + + + + account.asset.category.form + account.asset.category + form + +
+ + + + + +
+ + + account.asset.category.tree + account.asset.category + tree + + + + + + + + + Asset category + account.asset.category + form + tree,form + + + + + + account.asset.property.tree + account.asset.property + tree + + + + + + + + + + + + + + + + account.asset.asset.form + account.asset.asset + form + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +