[IMP] Upgrade the translations
[odoo/odoo.git] / addons / account_budget / crossovered_budget.py
1 # -*- encoding: utf-8 -*-
2 ##############################################################################
3 #
4 #    OpenERP, Open Source Management Solution   
5 #    Copyright (C) 2004-2009 Tiny SPRL (<http://tiny.be>). All Rights Reserved
6 #    $Id$
7 #
8 #    This program is free software: you can redistribute it and/or modify
9 #    it under the terms of the GNU General Public License as published by
10 #    the Free Software Foundation, either version 3 of the License, or
11 #    (at your option) any later version.
12 #
13 #    This program is distributed in the hope that it will be useful,
14 #    but WITHOUT ANY WARRANTY; without even the implied warranty of
15 #    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 #    GNU General Public License for more details.
17 #
18 #    You should have received a copy of the GNU General Public License
19 #    along with this program.  If not, see <http://www.gnu.org/licenses/>.
20 #
21 ##############################################################################
22 from osv import osv,fields
23 import tools
24 import netsvc
25 from mx import DateTime
26 import time
27 import datetime
28 from tools.translate import _
29
30
31 def strToDate(dt):
32         dt_date=datetime.date(int(dt[0:4]),int(dt[5:7]),int(dt[8:10]))
33         return dt_date
34
35 # ---------------------------------------------------------
36 # Budgets
37 # ---------------------------------------------------------
38 class account_budget_post(osv.osv):
39     _name = 'account.budget.post'
40     _description = 'Budgetary Position'
41     _columns = {
42         'code': fields.char('Code', size=64, required=True),
43         'name': fields.char('Name', size=256, required=True),
44         'dotation_ids': fields.one2many('account.budget.post.dotation', 'post_id', 'Spreading'),
45         'account_ids': fields.many2many('account.account', 'account_budget_rel', 'budget_id', 'account_id', 'Accounts'),
46         'crossovered_budget_line': fields.one2many('crossovered.budget.lines', 'general_budget_id', 'Budget Lines'),
47     }
48     _defaults = {
49     }
50
51     def spread(self, cr, uid, ids, fiscalyear_id=False, amount=0.0):
52         dobj = self.pool.get('account.budget.post.dotation')
53         for o in self.browse(cr, uid, ids):
54             # delete dotations for this post
55             dobj.unlink(cr, uid, dobj.search(cr, uid, [('post_id','=',o.id)]))
56
57             # create one dotation per period in the fiscal year, and spread the total amount/quantity over those dotations
58             fy = self.pool.get('account.fiscalyear').browse(cr, uid, [fiscalyear_id])[0]
59             num = len(fy.period_ids)
60             for p in fy.period_ids:
61                 dobj.create(cr, uid, {'post_id': o.id, 'period_id': p.id, 'amount': amount/num})
62         return True
63 account_budget_post()
64
65 class account_budget_post_dotation(osv.osv):
66     def _tot_planned(self, cr, uid, ids,name,args,context):
67         res={}
68         for line in self.browse(cr, uid, ids):
69             if line.period_id:
70                 obj_period=self.pool.get('account.period').browse(cr, uid,line.period_id.id)
71
72                 total_days=strToDate(obj_period.date_stop) - strToDate(obj_period.date_start)
73                 budget_id=line.post_id and line.post_id.id or False
74                 query="select id from crossovered_budget_lines where  general_budget_id= '"+ str(budget_id) + "' AND (date_from  >='"  +obj_period.date_start +"'  and date_from <= '"+obj_period.date_stop + "') OR (date_to  >='"  +obj_period.date_start +"'  and date_to <= '"+obj_period.date_stop + "') OR (date_from  <'"  +obj_period.date_start +"'  and date_to > '"+obj_period.date_stop + "')"
75                 cr.execute(query)
76                 res1=cr.fetchall()
77
78                 tot_planned=0.00
79                 for record in res1:
80                     obj_lines = self.pool.get('crossovered.budget.lines').browse(cr, uid,record[0])
81                     count_days = min(strToDate(obj_period.date_stop),strToDate(obj_lines.date_to)) - max(strToDate(obj_period.date_start), strToDate(obj_lines.date_from))
82                     days_in_period = count_days.days +1
83                     count_days = strToDate(obj_lines.date_to) - strToDate(obj_lines.date_from)
84                     total_days_of_rec = count_days.days +1
85                     tot_planned += obj_lines.planned_amount/total_days_of_rec* days_in_period
86                 res[line.id]=tot_planned
87             else:
88                 res[line.id]=0.00
89         return res
90
91     _name = 'account.budget.post.dotation'
92     _description = "Budget Dotation"
93     _columns = {
94         'name': fields.char('Name', size=64),
95         'post_id': fields.many2one('account.budget.post', 'Item', select=True),
96         'period_id': fields.many2one('account.period', 'Period'),
97         'amount': fields.float('Amount', digits=(16,2)),
98         'tot_planned':fields.function(_tot_planned,method=True, string='Total Planned Amount',type='float',store=True),
99     }
100
101 account_budget_post_dotation()
102
103 class crossovered_budget(osv.osv):
104     _name = "crossovered.budget"
105     _description = "Budget"
106
107     _columns = {
108         'name': fields.char('Name', size=50, required=True,states={'done':[('readonly',True)]}),
109         'code': fields.char('Code', size=20, required=True,states={'done':[('readonly',True)]}),
110         'creating_user_id': fields.many2one('res.users','Responsible User'),
111         'validating_user_id': fields.many2one('res.users','Validate User', readonly=True),
112         'date_from': fields.date('Start Date',required=True,states={'done':[('readonly',True)]}),
113         'date_to': fields.date('End Date',required=True,states={'done':[('readonly',True)]}),
114         'state' : fields.selection([('draft','Draft'),('confirm','Confirmed'),('validate','Validated'),('done','Done'),('cancel', 'Cancelled')], 'Status', select=True, required=True, readonly=True),
115         'crossovered_budget_line': fields.one2many('crossovered.budget.lines', 'crossovered_budget_id', 'Budget Lines',states={'done':[('readonly',True)]} ),
116     }
117
118     _defaults = {
119         'state': lambda *a: 'draft',
120         'creating_user_id': lambda self,cr,uid,context: uid,
121     }
122
123 #   def action_set_to_draft(self, cr, uid, ids, *args):
124 #       self.write(cr, uid, ids, {'state': 'draft'})
125 #       wf_service = netsvc.LocalService('workflow')
126 #       for id in ids:
127 #           wf_service.trg_create(uid, self._name, id, cr)
128 #       return True
129
130     def budget_confirm(self, cr, uid, ids, *args):
131         self.write(cr, uid, ids, {
132             'state':'confirm'
133         })
134         return True
135
136     def budget_validate(self, cr, uid, ids, *args):
137         self.write(cr, uid, ids, {
138             'state':'validate',
139             'validating_user_id': uid,
140         })
141         return True
142
143     def budget_cancel(self, cr, uid, ids, *args):
144
145         self.write(cr, uid, ids, {
146             'state':'cancel'
147         })
148         return True
149
150     def budget_done(self, cr, uid, ids, *args):
151         self.write(cr, uid, ids, {
152             'state':'done'
153         })
154         return True
155
156 crossovered_budget()
157
158 class crossovered_budget_lines(osv.osv):
159
160     def _prac_amt(self, cr, uid, ids,context={}):
161         res = {}
162         for line in self.browse(cr, uid, ids):
163             acc_ids = [x.id for x in line.general_budget_id.account_ids]
164             if not acc_ids:
165                 raise osv.except_osv(_('Error!'),_("The General Budget '%s' has no Accounts!") % str(line.general_budget_id.name))
166
167             date_to = line.date_to
168             date_from = line.date_from
169             if context.has_key('wizard_date_from'):
170                 date_from = context['wizard_date_from']
171             if context.has_key('wizard_date_to'):
172                 date_to = context['wizard_date_to']
173
174             cr.execute("select sum(amount) from account_analytic_line where account_id=%%s and (date "
175                        "between to_date(%%s,'yyyy-mm-dd') and to_date(%%s,'yyyy-mm-dd')) and "
176                        "general_account_id in (%s)" % ",".join(map(str,acc_ids)), (line.analytic_account_id.id, date_from, date_to ))
177             result = cr.fetchone()[0]
178             if result is None:
179                 result = 0.00
180             res[line.id] = result
181         return res
182
183     def _prac(self, cr, uid, ids,name,args,context):
184         res={}
185         for line in self.browse(cr, uid, ids):
186             res[line.id]=self._prac_amt(cr,uid,[line.id],context=context)[line.id]
187
188         return res
189
190     def _theo_amt(self, cr, uid, ids,context={}):
191         res = {}
192         for line in self.browse(cr, uid, ids):
193             today=datetime.datetime.today()
194             date_to = today.strftime("%Y-%m-%d")
195             date_from = line.date_from
196             if context.has_key('wizard_date_from'):
197                 date_from = context['wizard_date_from']
198             if context.has_key('wizard_date_to'):
199                 date_to = context['wizard_date_to']
200
201             if line.paid_date:
202                 if strToDate(line.date_to)<=strToDate(line.paid_date):
203                     theo_amt=0.00
204                 else:
205                     theo_amt=line.planned_amount
206             else:
207                 total=strToDate(line.date_to) - strToDate(line.date_from)
208                 elapsed = min(strToDate(line.date_to),strToDate(date_to)) - max(strToDate(line.date_from),strToDate(date_from))
209                 if strToDate(date_to) < strToDate(line.date_from):
210                     elapsed = strToDate(date_to) - strToDate(date_to)
211                 
212                 if total.days:
213                     theo_amt = float(elapsed.days/float(total.days))*line.planned_amount
214                 else:
215                     theo_amt = line.planned_amount
216
217             res[line.id]=theo_amt
218         return res
219
220     def _theo(self, cr, uid, ids,name,args,context):
221         res={}
222         for line in self.browse(cr, uid, ids):
223             res[line.id]=self._theo_amt(cr,uid,[line.id],context=context)[line.id]
224
225         return res
226
227     def _perc(self, cr, uid, ids,name,args,context):
228         res = {}
229         for line in self.browse(cr, uid, ids):
230             if line.theoritical_amount<>0.00:
231                 res[line.id]=float(line.practical_amount / line.theoritical_amount)*100
232             else:
233                 res[line.id]=0.00
234         return res
235     _name="crossovered.budget.lines"
236     _description = "Budget Lines"
237     _columns = {
238         'crossovered_budget_id': fields.many2one('crossovered.budget', 'Budget', ondelete='cascade', select=True, required=True),
239         'analytic_account_id': fields.many2one('account.analytic.account', 'Analytic Account',required=True),
240         'general_budget_id': fields.many2one('account.budget.post', 'Budgetary Position',required=True),
241         'date_from': fields.date('Start Date',required=True),
242         'date_to': fields.date('End Date',required=True),
243         'paid_date': fields.date('Paid Date'),
244         'planned_amount':fields.float('Planned Amount',required=True,digits=(16,2)),
245         'practical_amount':fields.function(_prac,method=True, string='Practical Amount',type='float',digits=(16,2)),
246         'theoritical_amount':fields.function(_theo,method=True, string='Theoritical Amount',type='float',digits=(16,2)),
247         'percentage':fields.function(_perc,method=True, string='Percentage',type='float'),
248     }
249 crossovered_budget_lines()
250
251 class account_analytic_account(osv.osv):
252     _name = 'account.analytic.account'
253     _inherit = 'account.analytic.account'
254
255     _columns = {
256     'crossovered_budget_line': fields.one2many('crossovered.budget.lines', 'analytic_account_id', 'Budget Lines'),
257     }
258
259 account_analytic_account()
260
261 # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
262