diff --git a/addons/account_analytic_plans/__init__.py b/addons/account_analytic_plans/__init__.py new file mode 100644 index 00000000000..db5d5411fd6 --- /dev/null +++ b/addons/account_analytic_plans/__init__.py @@ -0,0 +1,34 @@ +# -*- encoding: utf-8 -*- +############################################################################## +# +# 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_analytic_plans +import wizard +import report +# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: + diff --git a/addons/account_analytic_plans/__terp__.py b/addons/account_analytic_plans/__terp__.py new file mode 100644 index 00000000000..3fc3444e350 --- /dev/null +++ b/addons/account_analytic_plans/__terp__.py @@ -0,0 +1,48 @@ +# -*- encoding: utf-8 -*- +{ + "name" : "Multiple-plans management in analytic accounting", + "version" : "1.0", + "depends" : ["account", "base","product_analytic_default"], + "author" : "Tiny", + "description": """The goal is to allow several analytic plans, according to the general journal, + so that multiple analytic lines are created when the invoice is confirmed. + Second goal is to allow creating automatic analytic entries when writing general entries manually + through: Finance > Entries > By Journal. + + For example, the analytic structure: + Projects + »···Project 1 + »···»···SubProj 1.1 + »···»···SubProj 1.2 + »···Project 2 + Salesman + »···Eric + »···Fabien + + Here, we have two plans: Projects and Salesman. An invoice line must + be able to write analytic entries in the 2 plans: SubProj 1.1 and + Fabien. The amount can also be splitted, example: + + Plan1: + SubProject 1.1 : 50% + SubProject 1.2 : 50% + Plan2: + Eric: 100% + + So when this line of invoice will be confirmed, It must generate 3 + analytic lines. + """, + "website" : "http://tinyerp.com/module_account.html", + "category" : "Generic Modules/Accounting", + "init_xml" : [ + ], + "demo_xml" : [ + ], + "update_xml" : ["model_wizard.xml","account_analytic_plans_view.xml", + "account_analytic_plans_report.xml"], + + "active": False, + "installable": True +} +# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: + diff --git a/addons/account_analytic_plans/account_analytic_plans.py b/addons/account_analytic_plans/account_analytic_plans.py new file mode 100644 index 00000000000..80fffb36978 --- /dev/null +++ b/addons/account_analytic_plans/account_analytic_plans.py @@ -0,0 +1,404 @@ +# -*- encoding: utf-8 -*- +############################################################################## +# +# Copyright (c) 2004-2006 TINY SPRL. (http://tiny.be) All Rights Reserved. +# +# $Id: account.py 1005 2005-07-25 08:41:42Z nicoe $ +# +# 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 xml import dom + +from mx import DateTime +from mx.DateTime import now +import time + +import netsvc +from osv import fields, osv,orm +import ir + +import tools + +class one2many_mod2(fields.one2many): + def get(self, cr, obj, ids, name, user=None, offset=0, context=None, values=None): + if not context: + context = {} + res = {} + for id in ids: + res[id] = [] + ids2 = None + if 'journal_id' in context: + journal = obj.pool.get('account.journal').browse(cr, user, context['journal_id'], context) + pnum = int(name[7]) -1 + plan = journal.plan_id + if plan and len(plan.plan_ids)>pnum: + acc_id = plan.plan_ids[pnum].root_analytic_id.id + ids2 = obj.pool.get(self._obj).search(cr, user, [(self._fields_id,'in',ids),('analytic_account_id','child_of',[acc_id])], limit=self._limit) + if ids2 is None: + ids2 = obj.pool.get(self._obj).search(cr, user, [(self._fields_id,'in',ids)], limit=self._limit) + for r in obj.pool.get(self._obj)._read_flat(cr, user, ids2, [self._fields_id], context=context, load='_classic_write'): + res[r[self._fields_id]].append( r['id'] ) + return res + +class account_analytic_plan(osv.osv): + _name = "account.analytic.plan" + _description = "Analytic Plans" + _columns = { + 'name': fields.char('Analytic Plan', size=64, required=True, select=True,), + 'plan_ids': fields.one2many('account.analytic.plan.line','plan_id','Analytic Plans'), + } +account_analytic_plan() + +class account_analytic_plan_line(osv.osv): + _name = "account.analytic.plan.line" + _description = "Analytic Plan Lines" + _columns = { + 'plan_id':fields.many2one('account.analytic.plan','Analytic Plan'), + 'name': fields.char('Plan Name', size=64, required=True, select=True), + 'sequence':fields.integer('Sequence'), + 'root_analytic_id': fields.many2one('account.analytic.account','Root Account',help="Root account of this plan.",required=True), + 'min_required': fields.float('Minimum Allowed (%)'), + 'max_required': fields.float('Maximum Allowed (%)'), + } + _defaults = { + 'min_required': lambda *args: 100.0, + 'max_required': lambda *args: 100.0, + } + _order = "sequence,id" +account_analytic_plan_line() + +class account_analytic_plan_instance(osv.osv): + _name='account.analytic.plan.instance' + _description = 'Object for create analytic entries from invoice lines' + _columns={ + 'name':fields.char('Analytic Distribution',size=64), + 'code':fields.char('Distribution Code',size=16), + 'journal_id': fields.many2one('account.analytic.journal', 'Analytic Journal', required=True), + 'account_ids':fields.one2many('account.analytic.plan.instance.line','plan_id','Account Id'), + 'account1_ids':one2many_mod2('account.analytic.plan.instance.line','plan_id','Account1 Id'), + 'account2_ids':one2many_mod2('account.analytic.plan.instance.line','plan_id','Account2 Id'), + 'account3_ids':one2many_mod2('account.analytic.plan.instance.line','plan_id','Account3 Id'), + 'account4_ids':one2many_mod2('account.analytic.plan.instance.line','plan_id','Account4 Id'), + 'account5_ids':one2many_mod2('account.analytic.plan.instance.line','plan_id','Account5 Id'), + 'account6_ids':one2many_mod2('account.analytic.plan.instance.line','plan_id','Account6 Id'), + 'plan_id':fields.many2one('account.analytic.plan', "Model's Plan"), + } + def copy(self, cr, uid, id, default=None, context=None): + if not default: + default = {} + default.update({'account1_ids':False, 'account2_ids':False, 'account3_ids':False, + 'account4_ids':False, 'account5_ids':False, 'account6_ids':False}) + return super(account_analytic_plan_instance, self).copy(cr, uid, id, default, context) + + _defaults = { + 'plan_id': lambda *args: False, + } + def name_get(self, cr, uid, ids, context={}): + res = [] + for inst in self.browse(cr, uid, ids, context): + name = inst.name or '/' + if name and inst.code: + name=name+' ('+inst.code+')' + res.append((inst.id, name)) + return res + + def name_search(self, cr, uid, name, args=None, operator='ilike', context=None, limit=80): + args= args or [] + if name: + ids = self.search(cr, uid, [('code', '=', name)] + args, limit=limit, context=context or {}) + if not ids: + ids = self.search(cr, uid, [('name', operator, name)] + args, limit=limit, context=context or {}) + else: + ids = self.search(cr, uid, args, limit=limit, context=context or {}) + return self.name_get(cr, uid, ids, context or {}) + + def fields_view_get(self, cr, uid, view_id=None, view_type='form', context=None, toolbar=False): + wiz_id = self.pool.get('ir.actions.wizard').search(cr, uid, [("wiz_name","=","create.model")]) + res = super(account_analytic_plan_instance,self).fields_view_get(cr, uid, view_id, view_type, context, toolbar) + if (res['type']=='form'): + plan_id = False + if context.get('journal_id',False): + plan_id = self.pool.get('account.journal').browse(cr, uid, int(context['journal_id']), context).plan_id + elif context.get('plan_id',False): + plan_id = self.pool.get('account.analytic.plan').browse(cr, uid, int(context['plan_id']), context).plan_id + if plan_id: + i=1 + res['arch'] = """
+ + + +