Merge lp:~openerp-dev/openobject-addons/addons-training-report-ysa into lp:~openobject-training/openobject-addons/training

Proposed by Yogesh (SerpentCS)
Status: Merged
Merged at revision: 2154
Proposed branch: lp:~openerp-dev/openobject-addons/addons-training-report-ysa
Merge into: lp:~openobject-training/openobject-addons/training
Diff against target: 1822 lines (+704/-699)
13 files modified
training_report/__init__.py (+1/-1)
training_report/__openerp__.py (+5/-1)
training_report/report/analytic_balance_year.py (+58/-90)
training_report/report_training_view.xml (+1/-8)
training_report/training_report.py (+100/-101)
training_report/training_report.xml (+1/-14)
training_report/wizard/__init__.py (+3/-3)
training_report/wizard/training_report_account_analytic_balance_year.py (+29/-31)
training_report/wizard/training_report_account_analytic_balance_year_view.xml (+35/-0)
training_report/wizard/training_report_course_profitability.py (+32/-35)
training_report/wizard/training_report_course_profitability_view.xml (+37/-0)
training_report/wizard/training_report_session_volume.py (+365/-415)
training_report/wizard/training_report_session_volume_view.xml (+37/-0)
To merge this branch: bzr merge lp:~openerp-dev/openobject-addons/addons-training-report-ysa
Reviewer Review Type Date Requested Status
Bhumika Shrimali Pending
Review via email: mp+53779@code.launchpad.net

Description of the change

training_report:- convert v5 to v6 and fix problem.

To post a comment you must log in.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'training_report/__init__.py'
2--- training_report/__init__.py 2009-08-24 08:58:54 +0000
3+++ training_report/__init__.py 2011-03-17 10:37:29 +0000
4@@ -23,5 +23,5 @@
5 import training_report
6 import report
7 import wizard
8+
9 # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
10-
11
12=== renamed file 'training_report/__terp__.py' => 'training_report/__openerp__.py'
13--- training_report/__terp__.py 2011-02-25 12:33:02 +0000
14+++ training_report/__openerp__.py 2011-03-17 10:37:29 +0000
15@@ -20,7 +20,6 @@
16 #
17 ##############################################################################
18
19-
20 {
21 'name': 'Training Management - Reporting',
22 'version': '1.0',
23@@ -36,6 +35,7 @@
24 'depends': [
25 'training',
26 'training_intra',
27+ 'training_exam',
28 ],
29 'init_xml': [],
30 'update_xml': [
31@@ -43,9 +43,13 @@
32 'security/ir.model.access.csv',
33 'report_training_view.xml',
34 'training_report.xml',
35+ 'wizard/training_report_account_analytic_balance_year_view.xml',
36+ 'wizard/training_report_course_profitability_view.xml',
37+ 'wizard/training_report_session_volume_view.xml',
38 ],
39 'demo_xml': [],
40 'installable': True,
41 'active': False,
42 }
43+
44 # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
45
46=== modified file 'training_report/report/analytic_balance_year.py'
47--- training_report/report/analytic_balance_year.py 2009-11-25 16:36:08 +0000
48+++ training_report/report/analytic_balance_year.py 2011-03-17 10:37:29 +0000
49@@ -20,10 +20,8 @@
50 #
51 ##############################################################################
52
53-import pooler
54 import time
55 from report import report_sxw
56-import datetime
57
58 class account_analytic_balance_year(report_sxw.rml_parse):
59 def __init__(self, cr, uid, name, context):
60@@ -43,12 +41,9 @@
61 })
62
63 def _lines_g(self, account_id, date1, date2):
64- year=[]
65- year.append(int(date1[0:4])-1)
66- year.append(int(date1[0:4]))
67 account_analytic_obj = self.pool.get('account.analytic.account')
68- ids = account_analytic_obj.search(self.cr, self.uid,
69- [('parent_id', 'child_of', [account_id])])
70+ year = [int(date1[0:4]) - 1, int(date1[0:4])]
71+ ids = account_analytic_obj.search(self.cr, self.uid, [('parent_id', 'child_of', [account_id])])
72 self.cr.execute("SELECT aa.name AS name, aa.code AS code, \
73 sum(aal.amount) AS balance, sum(aal.unit_amount) AS quantity \
74 FROM account_analytic_line AS aal, account_account AS aa \
75@@ -58,49 +53,46 @@
76 And date_part('year',date) in ("+ ','.join(map(str, year)) +") \
77 GROUP BY aal.general_account_id, aa.name, aa.code, aal.code ,date_part('year',date)\
78 ORDER BY aal.code", (date1[5:10], date2[5:10]))
79- res = self.cr.dictfetchall()
80+ result = self.cr.dictfetchall()
81
82- for r in res:
83- if r['balance'] > 0:
84- r['debit'] = r['balance']
85- r['credit'] = 0.0
86- elif r['balance'] < 0:
87- r['debit'] = 0.0
88- r['credit'] = -r['balance']
89+ for res in result:
90+ if res.get('balance') > 0:
91+ res.update({
92+ 'debit' : res.get('balance',0),
93+ 'credit' : 0.0
94+ })
95+ elif res.get('balance') < 0:
96+ res.update({
97+ 'debit' : 0.0,
98+ 'credit' : -res.get('balance',0)
99+ })
100 else:
101- r['balance'] == 0
102- r['debit'] = 0.0
103- r['credit'] = 0.0
104- return res
105+ res.update({
106+ 'balance' : 0.0,
107+ 'debit' : 0.0,
108+ 'credit' : -res.get('balance',0)
109+ })
110+ return result
111
112 def _get_year(self,date1,date2):
113- year=[]
114- year.append(str(int(date1[0:4])-1))
115- year.append(str(int(date1[0:4])))
116- return year
117+ return [str(int(date1[0:4])-1), str(int(date1[0:4]))]
118+
119 def _get_data(self, account_id, date1, date2):
120- res=[]
121- r={}
122- year=[]
123- year.append(str(int(date1[0:4])-1))
124- year.append(str(int(date1[0:4])))
125+ year = [str(int(date1[0:4])-1), str(int(date1[0:4]))]
126 debit = self._move_sum_debit(account_id, date1, date2)
127 credit = self._move_sum_credit(account_id, date1, date2)
128- amount=self._move_sum_balance(account_id, date1, date2)
129- r['debit']=debit
130- r['credit']=credit
131- r['amount']=amount
132- r['year']=year
133- return r
134+ amount = self._move_sum_balance(account_id, date1, date2)
135+ return {
136+ 'debit' : debit,
137+ 'credit' : credit,
138+ 'amount' : amount,
139+ 'year' : year
140+ }
141
142 def _move_sum_debit(self, account_id, date1, date2):
143- res=[]
144- year=[]
145- year.append(int(date1[0:4])-1)
146- year.append(int(date1[0:4]))
147 account_analytic_obj = self.pool.get('account.analytic.account')
148- ids = account_analytic_obj.search(self.cr, self.uid,
149- [('parent_id', 'child_of', [account_id])])
150+ year [int(date1[0:4])-1, int(date1[0:4])]
151+ ids = account_analytic_obj.search(self.cr, self.uid, [('parent_id', 'child_of', [account_id])])
152 self.cr.execute("SELECT sum(amount)\
153 FROM account_analytic_line \
154 WHERE account_id in ("+ ','.join(map(str, ids)) +") \
155@@ -108,66 +100,49 @@
156 and date_part('year',date) in ("+ ','.join(map(str, year)) +") \
157 group by date_part('year',date)",(date1[5:10], date2[5:10]))
158
159- res =self.cr.dictfetchall()
160- return res
161+ return self.cr.dictfetchall()
162
163 def _move_sum_credit(self, account_id, date1, date2):
164- year=[]
165- res=[]
166- year.append(int(date1[0:4])-1)
167- year.append(int(date1[0:4]))
168 account_analytic_obj = self.pool.get('account.analytic.account')
169- ids = account_analytic_obj.search(self.cr, self.uid,
170- [('parent_id', 'child_of', [account_id])])
171+ year = [int(date1[0:4])-1, int(date1[0:4])]
172+ ids = account_analytic_obj.search(self.cr, self.uid, [('parent_id', 'child_of', [account_id])])
173 self.cr.execute("SELECT -sum(amount) as sum \
174 FROM account_analytic_line \
175 WHERE account_id in ("+ ','.join(map(str, ids)) +") \
176 AND to_char(date, 'MM-DD')>=%s AND to_char(date, 'MM-DD')<=%s AND amount>0 \
177 and date_part('year',date) in ("+ ','.join(map(str, year)) +") \
178 group by date_part('year',date)",(date1[5:10], date2[5:10]))
179- res= self.cr.dictfetchall()
180- return res
181+ return self.cr.dictfetchall()
182
183 def _move_sum_balance(self, account_id, date1, date2):
184- res=[]
185- account_analytic_obj = self.pool.get('account.analytic.account')
186- ids = account_analytic_obj.search(self.cr, self.uid,
187- [('parent_id', 'child_of', [account_id])])
188+ result = []
189 debit = self._move_sum_debit(account_id, date1, date2)
190- temp =len(debit)
191 credit = self._move_sum_credit(account_id, date1, date2)
192- for i in range(temp):
193- res.append(debit[i]['sum']-credit[i]['sum'])
194- return res
195+ for index in range(len(debit)):
196+ result.append(debit[index]['sum'] - credit[index]['sum'])
197+ return result
198
199 def _move_sum_quantity(self, account_id, date1, date2):
200- year=[]
201- year.append(int(date1[0:4])-1)
202- year.append(int(date1[0:4]))
203 account_analytic_obj = self.pool.get('account.analytic.account')
204- ids = account_analytic_obj.search(self.cr, self.uid,
205- [('parent_id', 'child_of', [account_id])])
206+ year = [int(date1[0:4])-1, int(date1[0:4])]
207+ ids = account_analytic_obj.search(self.cr, self.uid, [('parent_id', 'child_of', [account_id])])
208 self.cr.execute("SELECT sum(unit_amount) as sum,date_part('year',date) as year \
209 FROM account_analytic_line \
210 WHERE account_id in ("+ ','.join(map(str, ids)) +") \
211 AND to_char(date, 'MM-DD')>=%s AND to_char(date, 'MM-DD')<=%s AND amount<0 \
212 and date_part('year',date) in ("+ ','.join(map(str, year)) +") \
213 group by date_part('year',date)",(date1[5:10], date2[5:10]))
214+
215 return self.cr.dictfetchall() or []
216
217-
218 def _sum_debit(self, accounts, date1, date2):
219-
220- year=[]
221- res=[]
222- year.append(int(date1[0:4])-1)
223- year.append(int(date1[0:4]))
224+ account_analytic_obj = self.pool.get('account.analytic.account')
225+ year = [int(date1[0:4])-1, int(date1[0:4])]
226 ids = map(lambda x: x.id, accounts)
227 if not len(ids):
228 return 0.0
229- account_analytic_obj = self.pool.get('account.analytic.account')
230- ids2 = account_analytic_obj.search(self.cr, self.uid,
231- [('parent_id', 'child_of', ids)])
232+
233+ ids2 = account_analytic_obj.search(self.cr, self.uid, [('parent_id', 'child_of', ids)])
234 self.cr.execute("SELECT sum(amount) as sum \
235 FROM account_analytic_line \
236 WHERE account_id in ("+ ','.join(map(str, ids2)) + " ) \
237@@ -175,20 +150,16 @@
238 and date_part('year',date) in ("+ ','.join(map(str, year)) + " ) \
239 group by date_part('year',date) ",
240 (date1[5:10], date2[5:10]))
241- res= self.cr.dictfetchall()
242- return res
243+
244+ return self.cr.dictfetchall()
245
246 def _sum_credit(self, accounts, date1, date2):
247- year=[]
248- year.append(int(date1[0:4])-1)
249- year.append(int(date1[0:4]))
250+ account_analytic_obj = self.pool.get('account.analytic.account')
251+ year = [int(date1[0:4])-1, int(date1[0:4])]
252 ids = map(lambda x: x.id, accounts)
253 if not len(ids):
254 return 0.0
255- ids = map(lambda x: x.id, accounts)
256- account_analytic_obj = self.pool.get('account.analytic.account')
257- ids2 = account_analytic_obj.search(self.cr, self.uid,
258- [('parent_id', 'child_of', ids)])
259+ ids2 = account_analytic_obj.search(self.cr, self.uid, [('parent_id', 'child_of', ids)])
260 self.cr.execute("SELECT -sum(amount) as sum \
261 FROM account_analytic_line \
262 WHERE account_id in ("+ ','.join(map(str, ids2)) +") \
263@@ -196,21 +167,18 @@
264 and date_part('year',date) in ("+ ','.join(map(str, year)) +") \
265 group by date_part('year',date) ",
266 (date1[5:10], date2[5:10]))
267- res= self.cr.dictfetchall()
268- return res
269+ return self.cr.dictfetchall()
270+
271 def _sum_balance(self, accounts, date1, date2):
272 debit = self._sum_debit(accounts, date1, date2) or 0.0
273 credit = self._sum_credit(accounts, date1, date2) or 0.0
274- res=[]
275- temp=len(debit)
276- for i in range(temp):
277- res.append(debit[i]['sum']-credit[i]['sum'])
278- return res
279-
280+ result = []
281+ for index in range(len(debit)):
282+ result.append(debit[index]['sum'] - credit[index]['sum'])
283+ return result
284
285 report_sxw.report_sxw('report.account.analytic.account.balance.year',
286 'account.analytic.account','addons/training_report/report/analytic_balance_year.rml',
287 parser=account_analytic_balance_year, header=False)
288
289-
290 # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
291
292=== modified file 'training_report/report_training_view.xml'
293--- training_report/report_training_view.xml 2010-10-05 14:48:03 +0000
294+++ training_report/report_training_view.xml 2011-03-17 10:37:29 +0000
295@@ -3,14 +3,6 @@
296 <data>
297 <menuitem id="menu_training_report" name="Reporting" parent="training.training_mi" sequence="100"/>
298
299- <wizard id="training_session_volume_report_wizard"
300- model="training.session"
301- menu="False"
302- name="training.session.volume.report"
303- string="Report Volume"/>
304-
305- <menuitem id="training_report_volume_mi" parent="menu_training_report" type="wizard" action="training_session_volume_report_wizard"/>
306-
307 <record model="ir.ui.view" id="training_report_wizard_form">
308 <field name="name">training_report_wizard</field>
309 <field name="model">training.report.wizard</field>
310@@ -84,5 +76,6 @@
311 </graph>
312 </field>
313 </record>
314+
315 </data>
316 </openerp>
317
318=== modified file 'training_report/training_report.py'
319--- training_report/training_report.py 2011-02-09 15:47:36 +0000
320+++ training_report/training_report.py 2011-03-17 10:37:29 +0000
321@@ -20,10 +20,9 @@
322 #
323 ##############################################################################
324
325+from osv import osv
326+from osv import fields
327 import time
328-import datetime
329-from osv import fields,osv
330-import tools
331 from tools.sql import drop_view_if_exists
332 import xlwt
333 import base64
334@@ -36,14 +35,14 @@
335 from training.training import training_course_kind_compute
336
337 # http://code.activestate.com/recipes/476197-first-last-day-of-the-month/#c1
338-def get_first_day(dt, d_years=0, d_months=0):
339- # d_years, d_months are "deltas" to apply to dt
340- y, m = dt.year + d_years, dt.month + d_months
341- a, m = divmod(m-1, 12)
342- return date(y+a, m+1, 1)
343+def get_first_day(date, date_years=0, date_months=0):
344+ # date_years, date_months are "deltas" to apply to date
345+ year, month = date.year + date_years, datet.month + date_months
346+ avg, month = divmod(month - 1, 12)
347+ return date(year + avg, month + 1, 1)
348
349-def get_last_day(dt):
350- return get_first_day(dt, 0, 1) + timedelta(-1)
351+def get_last_day(date):
352+ return get_first_day(date, 0, 1) + timedelta(-1)
353
354
355 class subscription_line(osv.osv):
356@@ -129,21 +128,11 @@
357 class training_report_wizard(osv.osv):
358 _name = 'training.report.wizard'
359
360-
361 _columns = {
362 'date_start' : fields.date('Date Start', required=True),
363 'date_stop' : fields.date('Date Stop', required=True),
364-
365- 'state' : fields.selection([('init', 'Init'),
366- ('result', 'Result')],
367- 'State',
368- required=True,
369- readonly=True),
370-
371- 'report' : fields.selection([(report_name, report['title']) for report_name, report in REPORTS.iteritems()],
372- 'Report',
373- required=True),
374-
375+ 'state' : fields.selection([('init', 'Init'),('result', 'Result')], 'State', required=True, readonly=True),
376+ 'report' : fields.selection([(report_name, report['title']) for report_name, report in REPORTS.iteritems()], 'Report', required=True),
377 'filename' : fields.char('Filename', size=128, readonly=True),
378 'file_data' : fields.binary('File', readonly=True),
379 }
380@@ -155,11 +144,14 @@
381 'state' : lambda *a: 'init',
382 }
383
384-
385 def action_close(self, cr, uid, ids, context=None):
386 return {'type' : 'ir.actions.act_window_close'}
387
388 def action_generate_report(self, cr, uid, ids, context=None):
389+ if not ids:
390+ return False
391+ if context is None:
392+ context = {}
393 def execute_query(group_column, column_name):
394 cr.execute("""
395 SELECT l.%(gc)s as %(cn)s,
396@@ -225,6 +217,7 @@
397 """ % {'gc': group_column, 'cn': column_name}
398 , (this.date_start, this.date_stop))
399 return cr.fetchall()
400+
401 def stream_write_row(row_id, values):
402 row = stream.row(row_id)
403 for idx, value in enumerate(values):
404@@ -277,14 +270,14 @@
405
406
407 if this.report == 'sale.partner':
408- for x in execute_query_invoice('partner_id', 'partner_id'):
409- row_id = write_to_xls(row_id, x)
410+ for temp in execute_query_invoice('partner_id', 'partner_id'):
411+ row_id = write_to_xls(row_id, temp)
412 elif this.report == 'sale.supplier':
413- for x in execute_query_invoice_supplier('partner_id', 'partner_id'):
414- row_id = write_to_xls(row_id, x)
415+ for temp in execute_query_invoice_supplier('partner_id', 'partner_id'):
416+ row_id = write_to_xls(row_id, temp)
417 elif this.report == 'sale.user':
418- for x in execute_query('create_uid', 'user_id'):
419- row_id = write_to_xls(row_id, x)
420+ for temp in execute_query('create_uid', 'user_id'):
421+ row_id = write_to_xls(row_id, temp)
422 elif this.report == 'sale.offer':
423 cr.execute("""
424 SELECT l.offer_id as offer_id,
425@@ -303,11 +296,11 @@
426 GROUP BY l.offer_id
427 """, (this.date_start, this.date_stop))
428
429- for x in cr.fetchall():
430- row_id = write_to_xls(row_id, x)
431+ for temp in cr.fetchall():
432+ row_id = write_to_xls(row_id, temp)
433 elif this.report == 'sale.product':
434- for x in execute_query('product_id', 'product_id'):
435- row_id = write_to_xls(row_id, x)
436+ for temp in execute_query('product_id', 'product_id'):
437+ row_id = write_to_xls(row_id, temp)
438 elif this.report == 'subscription.offer':
439 cr.execute("""
440 SELECT toff.id AS offer_id,
441@@ -328,8 +321,8 @@
442 GROUP BY toff.id, toff.kind
443 ORDER BY turnover DESC
444 """, (this.date_start, this.date_stop))
445- for x in cr.fetchall():
446- row_id = write_to_xls(row_id, x)
447+ for temp in cr.fetchall():
448+ row_id = write_to_xls(row_id, temp)
449
450 wb.save(strIO)
451
452@@ -383,6 +376,7 @@
453 'offer_kind': fields.char('Offer Kind', size=16, readonly=True,),
454 'analytic_account_id': fields.many2one('account.analytic.account', 'Analytic Account', readonly=True,),
455 }
456+
457 training_report_intra_session_seance_view()
458
459 class training_report_session_stats_view(osv.osv):
460@@ -444,45 +438,47 @@
461 }
462
463 def init(self, cr):
464- drop_view_if_exists(cr, 'training_report_seance_stats_view', cascade=True)
465+ drop_view_if_exists(cr, 'training_report_seance_purchase_stats_view')
466+ drop_view_if_exists(cr, 'training_report_seance_stats_view')
467 cr.execute("""CREATE OR REPLACE VIEW training_report_seance_stats_view AS (
468
469-select
470- tsea.id AS seance_id,
471- tsea.kind,
472- tsea.duration,
473- tsea.course_id,
474- tg.name AS group_name,
475- COALESCE(CASE WHEN (CASE WHEN tsea.manual THEN tsea.participant_count_manual ELSE count(tp.id) END ) <= 0 THEN 1 ELSE (CASE WHEN tsea.manual THEN tsea.participant_count_manual ELSE count(tp.id) END) END, 0) AS participant_count,
476- CASE WHEN tsea.kind = 'exam' THEN pp.id ELSE tct.product_id END AS product_id,
477- CASE WHEN tsea.kind = 'exam' THEN pt.standard_price ELSE pt2.standard_price END AS product_price,
478- COALESCE(tsea.duration * (CASE WHEN tsea.kind = 'exam' THEN pt.standard_price ELSE pt2.standard_price END) / (CASE WHEN (CASE WHEN tsea.manual THEN tsea.participant_count_manual ELSE count(tp.id) END ) <= 0 THEN 1 ELSE (CASE WHEN tsea.manual THEN tsea.participant_count_manual ELSE count(tp.id) END) END), 0.0) AS one_trainer_cost,
479-
480- COALESCE((tsea.duration * (CASE WHEN tsea.kind = 'exam' THEN pt.standard_price ELSE pt2.standard_price END) / (CASE WHEN (CASE WHEN tsea.manual THEN tsea.participant_count_manual ELSE count(tp.id) END ) <= 0 THEN 1 ELSE (CASE WHEN tsea.manual THEN tsea.participant_count_manual ELSE count(tp.id) END) END)) * (CASE WHEN tsea.kind = 'exam' AND tsea.course_id IS NULL THEN 2.0 ELSE 1.0 END), 0.0) AS trainer_cost
481-
482-
483-FROM
484- training_seance tsea
485-LEFT JOIN
486- training_participation tp ON (tp.group_id = tsea.group_id AND tp.seance_id = tsea.id)
487-INNER JOIN
488- product_product pp ON (pp.default_code = 'R50H')
489-LEFT JOIN
490- training_course tc ON (tsea.kind != 'exam' AND tsea.course_id = tc.id)
491-LEFT JOIN
492- training_course_type tct ON (tc.course_type_id = tct.id)
493-LEFT JOIN
494- training_group tg ON (tsea.group_id = tg.id)
495-LEFT JOIN
496- product_product pp2 ON (tct.product_id = pp2.id)
497-LEFT JOIN
498- product_template pt ON (pp.product_tmpl_id = pt.id)
499-LEFT JOIN
500- product_template pt2 ON (pp2.product_tmpl_id = pt2.id)
501-GROUP BY
502- tsea.id, tsea.kind, tsea.duration, tsea.course_id, tg.name, tsea.manual, tsea.participant_count_manual, pp.id, tct.product_id, pt.standard_price, pt2.standard_price
503-
504- )""")
505+ select
506+ tsea.id AS seance_id,
507+ tsea.kind,
508+ tsea.duration,
509+ tsea.course_id,
510+ tg.name AS group_name,
511+ COALESCE(CASE WHEN (CASE WHEN tsea.manual THEN tsea.participant_count_manual ELSE count(tp.id) END ) <= 0 THEN 1 ELSE (CASE WHEN tsea.manual THEN tsea.participant_count_manual ELSE count(tp.id) END) END, 0) AS participant_count,
512+ CASE WHEN tsea.kind = 'exam' THEN pp.id ELSE tct.product_id END AS product_id,
513+ CASE WHEN tsea.kind = 'exam' THEN pt.standard_price ELSE pt2.standard_price END AS product_price,
514+ COALESCE(tsea.duration * (CASE WHEN tsea.kind = 'exam' THEN pt.standard_price ELSE pt2.standard_price END) / (CASE WHEN (CASE WHEN tsea.manual THEN tsea.participant_count_manual ELSE count(tp.id) END ) <= 0 THEN 1 ELSE (CASE WHEN tsea.manual THEN tsea.participant_count_manual ELSE count(tp.id) END) END), 0.0) AS one_trainer_cost,
515+
516+ COALESCE((tsea.duration * (CASE WHEN tsea.kind = 'exam' THEN pt.standard_price ELSE pt2.standard_price END) / (CASE WHEN (CASE WHEN tsea.manual THEN tsea.participant_count_manual ELSE count(tp.id) END ) <= 0 THEN 1 ELSE (CASE WHEN tsea.manual THEN tsea.participant_count_manual ELSE count(tp.id) END) END)) * (CASE WHEN tsea.kind = 'exam' AND tsea.course_id IS NULL THEN 2.0 ELSE 1.0 END), 0.0) AS trainer_cost
517+
518+
519+ FROM
520+ training_seance tsea
521+ LEFT JOIN
522+ training_participation tp ON (tp.group_id = tsea.group_id AND tp.seance_id = tsea.id)
523+ INNER JOIN
524+ product_product pp ON (pp.default_code = 'R50H')
525+ LEFT JOIN
526+ training_course tc ON (tsea.kind != 'exam' AND tsea.course_id = tc.id)
527+ LEFT JOIN
528+ training_course_type tct ON (tc.course_type_id = tct.id)
529+ LEFT JOIN
530+ training_group tg ON (tsea.group_id = tg.id)
531+ LEFT JOIN
532+ product_product pp2 ON (tct.product_id = pp2.id)
533+ LEFT JOIN
534+ product_template pt ON (pp.product_tmpl_id = pt.id)
535+ LEFT JOIN
536+ product_template pt2 ON (pp2.product_tmpl_id = pt2.id)
537+ GROUP BY
538+ tsea.id, tsea.kind, tsea.duration, tsea.course_id, tg.name, tsea.manual, tsea.participant_count_manual, pp.id, tct.product_id, pt.standard_price, pt2.standard_price
539+
540+ )""")
541+
542 training_report_seance_stats_view()
543
544 class training_report_seance_purchase_stats_view(osv.osv):
545@@ -507,16 +503,17 @@
546 )""")
547
548 _columns = {
549- 'seance_id': fields.many2one('training.seance', 'Seance', readonly=True,),
550- 'product_id': fields.many2one('product.product', 'Product', readonly=True,),
551- 'total_qty': fields.integer('Total Product Quantity', readonly=True,),
552- 'attachment_id': fields.many2one('ir.attachment', 'Attachment', readonly=True,),
553- 'standard_price': fields.float('Product Standard Price', readonly=True,),
554+ 'seance_id': fields.many2one('training.seance', 'Seance', readonly=True),
555+ 'product_id': fields.many2one('product.product', 'Product', readonly=True),
556+ 'total_qty': fields.integer('Total Product Quantity', readonly=True),
557+ 'attachment_id': fields.many2one('ir.attachment', 'Attachment', readonly=True),
558+ 'standard_price': fields.float('Product Standard Price', readonly=True),
559 'attachment_price': fields.float('Attachment Price', readonly=True),
560 'price': fields.float('Purchase Line Price', readonly=True),
561 'procurement_method': fields.char('Procurement Method', size=16, readonly=True),
562 'procurement_price': fields.char('Procurement Price', size=16, readonly=True),
563 }
564+
565 training_report_seance_purchase_stats_view()
566
567 class training_report_costs_view(osv.osv):
568@@ -525,16 +522,16 @@
569 _auto = False
570
571 _columns = {
572- 'session_id': fields.many2one('training.session', 'Session', ),
573- 'session_date': fields.datetime('Session Date'),
574- 'seance_id': fields.many2one('training.seance', 'Seance', ),
575- 'seance_kind': fields.selection(training_course_kind_compute, 'Seance Kind', ),
576- 'seance_date': fields.datetime('Seance Date'),
577- 'offer_kind': fields.selection(training_offer_kind_compute, 'Offer Kind', ),
578- 'offer_id': fields.many2one('training.offer', 'Offer'),
579- 'computed_course_id': fields.many2one('training.course', 'Course', ),
580- 'computed_analytic_id': fields.many2one('account.analytic.account', 'Analytic Account', ),
581- 'product_line_id': fields.many2one('training.course_category', 'Product Line', ),
582+ 'session_id': fields.many2one('training.session', 'Session', readonly=True),
583+ 'session_date': fields.datetime('Session Date', readonly=True),
584+ 'seance_id': fields.many2one('training.seance', 'Seance', readonly=True),
585+ 'seance_kind': fields.selection(training_course_kind_compute, 'Seance Kind', readonly=True),
586+ 'seance_date': fields.datetime('Seance Date', readonly=True),
587+ 'offer_kind': fields.selection(training_offer_kind_compute, 'Offer Kind', readonly=True),
588+ 'offer_id': fields.many2one('training.offer', 'Offer', readonly=True),
589+ 'computed_course_id': fields.many2one('training.course', 'Course', readonly=True),
590+ 'computed_analytic_id': fields.many2one('account.analytic.account', 'Analytic Account', readonly=True),
591+ 'product_line_id': fields.many2one('training.course_category', 'Product Line', readonly=True),
592 }
593
594 def init(self, cr):
595@@ -577,20 +574,19 @@
596 for sess_stats in cr.dictfetchall():
597 sess_stats['duration'] = sess_stats['seances_duration']
598 cache_session[sess_stats['session_id']] = sess_stats
599+ return True
600
601 def docache_seance_populate(self, cr, uid, cache_seance, seance_ids):
602 if not seance_ids:
603 return
604-
605 query_seance_ids = ','.join(map(str, seance_ids))
606-
607 # pre-compute procurement price
608 seance_procs_cache = {}
609 for seance_id in seance_ids:
610 seance_procs_cache[seance_id] = {
611- 'proc_fix': 0.0,
612- 'proc_sub': 0.0,
613- }
614+ 'proc_fix': 0.0,
615+ 'proc_sub': 0.0,
616+ }
617 cr.execute("SELECT * FROM training_report_seance_purchase_stats_view trspsv WHERE seance_id IN (%s)" % (query_seance_ids))
618 for purch_stat in cr.dictfetchall():
619 price = purch_stat['price']
620@@ -610,6 +606,7 @@
621 seance_stats['sessions_ratio'] = {}
622
623 cache_seance[seance_stats['seance_id']] = seance_stats
624+ return True
625
626 def docache_session(self, cache_session, session):
627 if session.id not in cache_session:
628@@ -618,6 +615,7 @@
629 'subscription_count': session.confirmed_subscriptions,
630 'duration': (sum([ seance.duration for seance in session.seance_ids]) or 1.0) / (float(len(session.group_ids)) or 1.0)
631 }
632+ return True
633
634 def docache_seance(self, cr, uid, cache_seance, seance, context=None):
635 if seance.id not in cache_seance:
636@@ -662,6 +660,7 @@
637 'group': seance.group_id.name,
638 'sessions_ratio': {},
639 }
640+ return True
641
642 # print(" group class : %s" % (cache_seance[seance.id]['group']))
643 # print(" trainer cost : %s" % (cache_seance[seance.id]['trainer_cost']))
644@@ -669,16 +668,18 @@
645 # print(" participant cnt : %s" % (cache_seance[seance.id]['participants']))
646
647 def get_sale_price(self, cr, uid, theor_cost, context=None):
648+ if context is None:
649+ context = {}
650 offer_pool = self.pool.get('training.offer')
651 subl_pool = self.pool.get('training.subscription.line')
652 price = 0.0
653- if theor_cost['offer_kind'] == 'intra':
654- o = offer_pool.browse(cr, uid, theor_cost['offer_id'])
655- pcount = o.number_of_participants or 12
656- price = (o.sale_order_id and o.sale_order_id.amount_untaxed or 0.0) / pcount
657+ if theor_cost.get('offer_kind',False) == 'intra':
658+ offer_data = offer_pool.browse(cr, uid, theor_cost['offer_id'])
659+ participant_count = offer_data.number_of_participants or 12
660+ price = (offer_data.sale_order_id and offer_data.sale_order_id.amount_untaxed or 0.0) / participant_count
661 else:
662 #price = subl_pool.read(cr, uid, theor_cost['id'], ['price'])['price']
663- price = theor_cost['subl_price']
664+ price = theor_cost.get('subl_price')
665 return price
666
667 training_report_costs_view()
668@@ -716,7 +717,7 @@
669 }
670
671 def search(self, cr, uid, args, offset=0, limit=None, order=None, context=None, count=False):
672- if not context:
673+ if context is None:
674 context = {}
675 if context.get('date_filter', '') == 'current_year':
676 args.extend([('date','>=',time.strftime('%Y-01-01')),('date','<=',time.strftime('%Y-12-31'))])
677@@ -725,10 +726,8 @@
678 # month_start_dt = datetime.datetime(map(int, month_start.split('-')))
679 # month_end = get_last_day(month_start_dt, d_month=1).strftime('%Y-%m-%d')
680 # args.extend
681- r = super(training_report_confirmed_subscription_count, self).search(cr, uid, args, offset=offset, limit=limit, order=order, context=context, count=count)
682- return r
683+ return super(training_report_confirmed_subscription_count, self).search(cr, uid, args, offset=offset, limit=limit, order=order, context=context, count=count)
684
685 training_report_confirmed_subscription_count()
686
687 # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
688-
689
690=== modified file 'training_report/training_report.xml'
691--- training_report/training_report.xml 2009-11-25 16:36:08 +0000
692+++ training_report/training_report.xml 2011-03-17 10:37:29 +0000
693@@ -1,6 +1,7 @@
694 <?xml version="1.0" encoding="UTF-8"?>
695 <openerp>
696 <data>
697+
698 <report auto="False"
699 id="account_analytic_account_balance"
700 menu="False"
701@@ -9,12 +10,6 @@
702 rml="/training_report/report/analytic_balance_year.rml"
703 string="Analytic Balance Year"/>
704
705- <wizard id="account_analytic_account_balance_report_year"
706- keyword="client_print_multi"
707- model="account.analytic.account"
708- name="account.analytic.account.balance.year.report"
709- string="Analytic Balance Year"/>
710-
711 <report auto="False"
712 id="course_profitability"
713 menu="False"
714@@ -24,13 +19,5 @@
715 rml="training_report/report/course_profitability.rml"
716 />
717
718- <wizard id="course_profitability_report"
719- keyword="client_print_multi"
720- model="training.course"
721- name="training.course.profitability.report"
722- string="Course Profitablility"/>
723-
724-
725-
726 </data>
727 </openerp>
728
729=== modified file 'training_report/wizard/__init__.py'
730--- training_report/wizard/__init__.py 2010-03-10 20:55:08 +0000
731+++ training_report/wizard/__init__.py 2011-03-17 10:37:29 +0000
732@@ -21,9 +21,9 @@
733 ##############################################################################
734
735
736-import wizard_account_analytic_balance_report_year_to_date
737-import wizard_course_profitability
738-import wizard_session_volume
739+import training_report_account_analytic_balance_year
740+import training_report_course_profitability
741+import training_report_session_volume
742
743 # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
744
745
746=== renamed file 'training_report/wizard/wizard_account_analytic_balance_report_year_to_date.py' => 'training_report/wizard/training_report_account_analytic_balance_year.py'
747--- training_report/wizard/wizard_account_analytic_balance_report_year_to_date.py 2009-11-25 16:36:08 +0000
748+++ training_report/wizard/training_report_account_analytic_balance_year.py 2011-03-17 10:37:29 +0000
749@@ -20,38 +20,36 @@
750 #
751 ##############################################################################
752
753+
754+from osv import osv
755+from osv import fields
756 import time
757-import wizard
758-import datetime
759-
760-dates_form = '''<?xml version="1.0"?>
761-<form string="Select period">
762- <field name="date1"/>
763- <field name="date2"/>
764-</form>'''
765-
766-dates_fields = {
767- 'date1': {'string':'Start of period', 'type':'date', 'required':True, 'default': lambda *a: time.strftime('%Y-01-01')},
768- 'date2': {'string':'End of period', 'type':'date', 'required':True, 'default': lambda *a: time.strftime('%Y-%m-%d')},
769-}
770-
771-
772-class wizard_report(wizard.interface):
773-
774-
775- states = {
776- 'init': {
777- 'actions': [],
778- 'result': {'type':'form', 'arch':dates_form, 'fields':dates_fields, 'state':[('end','Cancel'), ('report','Print')]}
779- },
780- 'report': {
781- 'actions': [],
782- 'result': {'type':'print', 'report':'account.analytic.account.balance.year', 'state':'end'}
783+
784+class training_report_account_analytic_balance_year(osv.osv_memory):
785+ _name = 'training.report.account.analytic.balance.year'
786+ _columns = {
787+ 'date1' : fields.date('Start of period', required=True),
788+ 'date2' : fields.date('End of period', required=True),
789+ }
790+
791+ _defaults = {
792+ 'date1': lambda *a: time.strftime('%Y-01-01'),
793+ 'date2': lambda *a: time.strftime('%Y-%m-%d'),
794+ }
795+
796+ def action_report(self, cr, uid, ids, context=None):
797+ if context is None:
798+ context = {}
799+ datas = {'form':{}, 'ids': context.get('active_ids', [])}
800+ res = self.read(cr, uid, ids, ['date1', 'date2'], context)
801+ res = res and res[0] or {}
802+ datas['form'].update(res)
803+ return {
804+ 'type': 'ir.actions.report.xml',
805+ 'report_name': 'account.analytic.account.balance.year',
806+ 'datas': datas,
807 }
808- }
809-wizard_report('account.analytic.account.balance.year.report')
810-
811-
812+
813+training_report_account_analytic_balance_year()
814
815 # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
816-
817
818=== added file 'training_report/wizard/training_report_account_analytic_balance_year_view.xml'
819--- training_report/wizard/training_report_account_analytic_balance_year_view.xml 1970-01-01 00:00:00 +0000
820+++ training_report/wizard/training_report_account_analytic_balance_year_view.xml 2011-03-17 10:37:29 +0000
821@@ -0,0 +1,35 @@
822+<openerp>
823+ <data>
824+
825+ <record model="ir.ui.view" id="training_report_account_analytic_balance_year_form">
826+ <field name="name">training.report.account.analytic.balance.year.form</field>
827+ <field name="model">training.report.account.analytic.balance.year</field>
828+ <field name="type">form</field>
829+ <field name="arch" type="xml">
830+ <form string="Analytic Balance Year">
831+ <field name="date1"/>
832+ <field name="date2"/>
833+ <separator colspan="4" />
834+ <group colspan="4" col="2">
835+ <button string="Cancel" special="cancel" type="object" icon="gtk-cancel"/>
836+ <button name="action_report" string="Print" type="object" icon="gtk-print"/>
837+ </group>
838+ </form>
839+ </field>
840+ </record>
841+
842+ <record model="ir.actions.act_window" id="training_report_account_analytic_balance_year_form_act">
843+ <field name="name">Analytic Balance Year</field>
844+ <field name="res_model">training.report.account.analytic.balance.year</field>
845+ <field name="view_type">form</field>
846+ <field name="view_mode">form</field>
847+ <field name="target">new</field>
848+ </record>
849+
850+ <act_window id="action_act_training_report_account_analytic_balance_year"
851+ key2="client_action_multi" name="Analytic Balance Year"
852+ res_model="training.report.account.analytic.balance.year" src_model="account.analytic.account"
853+ view_mode="form" target="new" view_type="form"/>
854+
855+ </data>
856+</openerp>
857
858=== renamed file 'training_report/wizard/wizard_course_profitability.py' => 'training_report/wizard/training_report_course_profitability.py'
859--- training_report/wizard/wizard_course_profitability.py 2009-11-25 16:36:08 +0000
860+++ training_report/wizard/training_report_course_profitability.py 2011-03-17 10:37:29 +0000
861@@ -20,42 +20,39 @@
862 #
863 ##############################################################################
864
865+
866+from osv import osv
867+from osv import fields
868 import time
869-import wizard
870-import datetime
871-
872-dates_form = '''<?xml version="1.0"?>
873-<form string="Select period">
874- <field name="date1"/>
875- <field name="date2"/>
876- <field name="analytic_account"/>
877- <field name="analytic_fix_cost"/>
878-</form>'''
879-
880-dates_fields = {
881- 'date1': {'string':'Start of period', 'type':'date', 'required':True, 'default': lambda *a: time.strftime('%Y-01-01')},
882- 'date2': {'string':'End of period', 'type':'date', 'required':True, 'default': lambda *a: time.strftime('%Y-%m-%d')},
883- 'analytic_account':{'string':'Analytic Account', 'type':'many2one','relation': 'account.analytic.account', 'required':True},
884- 'analytic_fix_cost':{'string':'Analytic Fix Cost', 'type':'float'},
885-}
886-
887-
888-class wizard_report(wizard.interface):
889-
890-
891- states = {
892- 'init': {
893- 'actions': [],
894- 'result': {'type':'form', 'arch':dates_form, 'fields':dates_fields, 'state':[('end','Cancel'), ('report','Print')]}
895- },
896- 'report': {
897- 'actions': [],
898- 'result': {'type':'print', 'report':'training.course.profitability', 'state':'end'}
899+
900+class training_report_course_profitability(osv.osv_memory):
901+ _name = 'training.report.course.profitability'
902+ _columns = {
903+ 'date1' : fields.date('Start of period', required=True),
904+ 'date2' : fields.date('End of period', required=True),
905+ 'analytic_account' : fields.many2one('account.analytic.account', 'Analytic Account', required=True),
906+ 'analytic_fix_cost' : fields.float('Analytic Fix Cost'),
907+ }
908+
909+
910+ _defaults = {
911+ 'date1': lambda *a: time.strftime('%Y-01-01'),
912+ 'date2': lambda *a: time.strftime('%Y-%m-%d'),
913+ }
914+
915+ def action_report(self, cr, uid, ids, context=None):
916+ if context is None:
917+ context = {}
918+ datas = {'form':{}, 'ids': context.get('active_ids', [])}
919+ res = self.read(cr, uid, ids, ['date1', 'date2', 'analytic_account', 'analytic_fix_cost'], context)
920+ res = res and res[0] or {}
921+ datas['form'].update(res)
922+ return {
923+ 'type': 'ir.actions.report.xml',
924+ 'report_name': 'training.course.profitability',
925+ 'datas': datas,
926 }
927- }
928-wizard_report('training.course.profitability.report')
929-
930-
931+
932+training_report_course_profitability()
933
934 # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
935-
936
937=== added file 'training_report/wizard/training_report_course_profitability_view.xml'
938--- training_report/wizard/training_report_course_profitability_view.xml 1970-01-01 00:00:00 +0000
939+++ training_report/wizard/training_report_course_profitability_view.xml 2011-03-17 10:37:29 +0000
940@@ -0,0 +1,37 @@
941+<openerp>
942+ <data>
943+
944+ <record model="ir.ui.view" id="view_training_report_course_profitability_form">
945+ <field name="name">training.report.course.profitability.form</field>
946+ <field name="model">training.report.course.profitability</field>
947+ <field name="type">form</field>
948+ <field name="arch" type="xml">
949+ <form string="Course Profitablility">
950+ <field name="date1"/>
951+ <field name="date2"/>
952+ <field name="analytic_account"/>
953+ <field name="analytic_fix_cost"/>
954+ <separator colspan="4" />
955+ <group colspan="4" col="2">
956+ <button string="Cancel" special="cancel" type="object" icon="gtk-cancel"/>
957+ <button name="action_report" string="Print" type="object" icon="gtk-print"/>
958+ </group>
959+ </form>
960+ </field>
961+ </record>
962+
963+ <record model="ir.actions.act_window" id="training_report_course_profitability_form_act">
964+ <field name="name">Course Profitablility</field>
965+ <field name="res_model">training.report.course.profitability</field>
966+ <field name="view_type">form</field>
967+ <field name="view_mode">form</field>
968+ <field name="target">new</field>
969+ </record>
970+
971+ <act_window id="action_act_training_report_course_profitability"
972+ key2="client_action_multi" name="Course Profitablility"
973+ res_model="training.report.course.profitability" src_model="training.course"
974+ view_mode="form" target="new" view_type="form"/>
975+
976+ </data>
977+</openerp>
978
979=== renamed file 'training_report/wizard/wizard_session_volume.py' => 'training_report/wizard/training_report_session_volume.py'
980--- training_report/wizard/wizard_session_volume.py 2010-09-22 10:00:18 +0000
981+++ training_report/wizard/training_report_session_volume.py 2011-03-17 10:37:29 +0000
982@@ -20,433 +20,383 @@
983 #
984 ##############################################################################
985
986-import wizard
987+from osv import osv
988+from osv import fields
989 import time
990-import datetime
991-import pooler
992 import tools
993
994 from tools.translate import _
995 import mx.DateTime as dt
996
997-_aged_trial_form = """<?xml version="1.0"?>
998-<form string="Session Volume Report">
999- <separator string="Period" colspan="4" />
1000- <field name="date_start"/>
1001- <field name="date_stop"/>
1002- <separator string="Year" colspan="4" />
1003- <field name="year" />
1004- <separator string="Report" colspan="4" />
1005- <field name="kind" />
1006-</form>"""
1007-
1008-def first_day_of_previous_month():
1009- return dt.strptime((dt.today() - dt.RelativeDate(months=1)).strftime('%Y-%m-01'), '%Y-%m-%d')
1010-
1011-def last_day_of_previous_month():
1012- return first_day_of_previous_month() + dt.RelativeDate(months=1, seconds=-1)
1013-
1014-_aged_trial_fields = {
1015- 'date_start': {'string':'Start of period', 'type':'date', 'required':True, 'default': lambda *a: first_day_of_previous_month().strftime('%Y-%m-%d')},
1016- 'date_stop': {'string':'Stop of period', 'type':'date', 'required':True, 'default': lambda *a: last_day_of_previous_month().strftime('%Y-%m-%d')},
1017- 'year': {'string':'Year', 'type':'integer', 'required':True, 'default': lambda *a: -1},
1018- 'kind' : {'string' : 'Kind',
1019- 'type' : 'selection',
1020- 'selection' : [
1021+class training_report_session_volume(osv.osv_memory):
1022+ _name = 'training.report.session.volume'
1023+ _columns = {
1024+ 'date_start' : fields.date('Start of period', required=True),
1025+ 'date_stop' : fields.date('End of period', required=True),
1026+ 'year' : fields.integer('Year', required=True),
1027+ 'kind' : fields.selection([
1028 ('product_lines', 'Statistics by Product Lines'),
1029 ('theoretical_product_lines', 'Theoretical Statistics by Product Lines'),
1030 ('sessions', 'Sessions volume by State'),
1031 ('count_subscriptions_offer', 'Subscription Volume by State'),
1032 #('subscriptions_partner', 'Partner Amount of Subscriptions'),
1033- ],
1034- 'default' : lambda *a: 'product_lines'}
1035-}
1036-
1037-def previous_date(date, year):
1038- return dt.strptime(date, '%Y-%m-%d') + dt.RelativeDate(years=year)
1039-
1040-def previous_period(date_start, date_stop, year):
1041- return (previous_date(date_start, year), previous_date(date_stop, year))
1042-
1043-def compute_theoretical_product_lines(cr, uid, ids, context, date_start, date_stop, kind):
1044-# print(">>> --== Compute Theoretical Product Lines ==--")
1045- pool = pooler.get_pool(cr.dbname)
1046- session_pool = pool.get('training.session')
1047- subl_pool = pool.get('training.subscription.line')
1048- prodline_pool = pool.get('training.course_category')
1049- offer_pool = pool.get('training.offer')
1050- trcv_pool = pool.get('training.report.costs.view')
1051-
1052- cache_seance = {}
1053- cache_session = {}
1054- product_line = {} # dict containing cost + revenue per product lines
1055-
1056- query_base = "SELECT * FROM training_report_costs_view "
1057- query = "WHERE seance_date BETWEEN %s AND %s AND offer_kind = %s"
1058- query_args = (date_start, date_stop, kind)
1059-
1060- if kind == 'intra':
1061- cr.execute("SELECT DISTINCT(session_id) FROM training_report_intra_session_seance_view " + query, query_args)
1062- else:
1063- cr.execute("SELECT DISTINCT(session_id) FROM training_report_costs_view " + query, query_args)
1064- session_ids = [ x[0] for x in cr.fetchall() ]
1065- trcv_pool.docache_session_populate(cr, uid, cache_session, session_ids)
1066-
1067- if kind == 'intra':
1068- cr.execute("SELECT DISTINCT(seance_id) FROM training_report_intra_session_seance_view " + query, query_args)
1069- else:
1070- cr.execute("SELECT DISTINCT(seance_id) FROM training_report_costs_view " + query, query_args)
1071- seance_ids = [ x[0] for x in cr.fetchall() ]
1072- trcv_pool.docache_seance_populate(cr, uid, cache_seance, seance_ids)
1073-
1074- if kind != 'intra':
1075- cr.execute(query_base + query, query_args)
1076- for theor_cost in cr.dictfetchall():
1077- c_session_id = theor_cost['session_id']
1078- c_seance_id = theor_cost['seance_id']
1079-
1080- if c_session_id not in cache_seance[c_seance_id]['sessions_ratio']:
1081- # seance already cached, but we still need to update the session ratio
1082- session_total_duration = cache_session[theor_cost['session_id']]['duration']
1083- cache_seance[c_seance_id]['sessions_ratio'][c_session_id] = cache_seance[c_seance_id]['duration'] / session_total_duration
1084-
1085- # all things are cached now
1086- c_seance = cache_seance[theor_cost['seance_id']]
1087- c_prodline_id = theor_cost['product_line_id']
1088- if c_prodline_id not in product_line:
1089- plo = prodline_pool.browse(cr, uid, c_prodline_id)
1090- product_line[c_prodline_id] = {
1091- 'id': c_prodline_id,
1092- 'name': plo.name,
1093- 'costs': 0.0,
1094- 'revenues': 0.0,
1095- 'subscriptions': set(),
1096- }
1097- pl = product_line[c_prodline_id]
1098- pl['costs'] += c_seance['trainer_cost'] + c_seance['proc_cost']
1099- pl['revenues'] += c_seance['sessions_ratio'][theor_cost['session_id']] * trcv_pool.get_sale_price(cr, uid, theor_cost, context=context)
1100- pl['subscriptions'].add(theor_cost['id'])
1101- else: # kind == 'intra'
1102- cr.execute("SELECT * FROM training_report_intra_session_seance_view " + query, query_args)
1103- for theor_intra in cr.dictfetchall():
1104- c_session_id = theor_intra['session_id']
1105- c_seance_id = theor_intra['seance_id']
1106-
1107- if c_session_id not in cache_seance[c_seance_id]['sessions_ratio']:
1108- # seance already cached, but we still need to update the session ratio
1109- session_total_duration = cache_session[theor_intra['session_id']]['duration']
1110- cache_seance[c_seance_id]['sessions_ratio'][c_session_id] = cache_seance[c_seance_id]['duration'] / session_total_duration
1111-
1112- c_seance = cache_seance[theor_intra['seance_id']]
1113- c_session = cache_session[theor_intra['session_id']]
1114-
1115- c_session_ratio = cache_seance[c_seance_id]['sessions_ratio'][c_session_id]
1116-
1117- c_prodline_id = theor_intra['product_line_id']
1118- if c_prodline_id not in product_line:
1119- plo = prodline_pool.browse(cr, uid, c_prodline_id)
1120- product_line[c_prodline_id] = {
1121- 'id': c_prodline_id,
1122- 'name': plo.name,
1123- 'costs': 0.0,
1124- 'revenues': 0.0,
1125- 'subscriptions': set(),
1126- }
1127- pl = product_line[c_prodline_id]
1128- pl['costs'] += c_session_ratio * theor_intra['session_cost']
1129- pl['revenues'] += c_session_ratio * theor_intra['session_revenue']
1130- for x in xrange(1, theor_intra['number_of_participants'] + 1):
1131- pl['subscriptions'].add(x)
1132-
1133- res = []
1134- total = { 'revenues': 0.0, 'costs': 0.0 }
1135- for p, v in product_line.iteritems():
1136- res.append(v)
1137- v['subscriptions'] = len(v['subscriptions'])
1138- v['margin'] = (v['revenues'] / (v['costs'] or 1.0)) * 100
1139- v['balance'] = (v['revenues'] - v['costs'])
1140- total['revenues'] += v['revenues']
1141- total['costs'] += v['costs']
1142-
1143- total['balance'] = total['revenues'] - total['costs']
1144- total['margin'] = (total['revenues'] / (total['costs'] or 1.0)) * 100
1145-
1146- return {
1147- 'product_lines': res,
1148- 'total': total,
1149- 'date_start': date_start,
1150- 'date_stop': date_stop,
1151- 'kind': kind,
1152- }
1153-
1154-def compute_product_lines_exam(cr, uid, ids, context, date_start, date_stop):
1155- res = []
1156-
1157-
1158- pool = pooler.get_pool(cr.dbname)
1159-
1160- tsl_proxy = pool.get('training.subscription.line')
1161-
1162- tsl_ids = tsl_proxy.search(cr, uid,
1163- [
1164- ('state', 'not in', ('draft', 'cancelled')),
1165- ('date', '>=', "%s 00:00:00" % (date_start)),
1166- ('date', '<=', "%s 23:59:59" % (date_stop)),
1167- ('kind', '=', 'exam'),
1168- ],
1169- context=context)
1170-
1171- product_lines = {}
1172-
1173- for sl in tsl_proxy.browse(cr, uid, tsl_ids, context=context):
1174-
1175- if not (sl.course_id and sl.course_id.category_id):
1176- continue
1177-
1178- product_line_id = sl.course_id.category_id
1179-
1180- product_lines.setdefaults(product_line_id, [])
1181-
1182- if sl.invoice_line_id and sl.invoice_id:
1183- product_lines[product_line_id].append(sl)
1184-
1185-
1186-def compute_product_lines(cr, uid, ids, context, date_start, date_stop, kind):
1187- res = []
1188-
1189- pool = pooler.get_pool(cr.dbname)
1190- tsl_proxy = pool.get('training.subscription.line')
1191-
1192- tsl_ids = tsl_proxy.search(cr, uid,
1193- [
1194- ('state', 'not in', ('draft', 'cancelled')),
1195- ('date', '>=', "%s 00:00:00" % (date_start)),
1196- ('date', '<=', "%s 23:59:59" % (date_stop)),
1197- ('kind', '=', kind),
1198- ],
1199- context=context)
1200-
1201- product_lines = {}
1202-
1203- for sl in tsl_proxy.browse(cr, uid, tsl_ids, context=context):
1204-
1205- session_id = sl.session_id
1206- invoice_id = sl.invoice_id
1207-
1208- product_line_id = sl.session_id.offer_id.product_line_id
1209-
1210- product_lines.setdefault(product_line_id,
1211- {
1212- 'invoices' : set(),
1213- 'sessions' : {},
1214- 'subscription_count' : 0,
1215- 'exams' : {},
1216- }
1217- )
1218-
1219- product_lines[product_line_id]['subscription_count'] += 1
1220-
1221- if invoice_id and sl.invoice_line_id:
1222- product_lines[product_line_id]['invoices'].add(invoice_id)
1223-
1224- if sl.session_id not in product_lines[product_line_id]['sessions']:
1225-
1226- po_pool = pool.get('purchase.order')
1227- sl_sess_seance_ids = [ seance.id for seance in session_id.seance_ids ]
1228- sl_sess_po = po_pool.search(cr, uid, [('seance_id','in',sl_sess_seance_ids)], context=context)
1229- value = sum(po.invoice_id and po.invoice_id.amount_untaxed or po.amount_untaxed
1230- for po in po_pool.browse(cr, uid, sl_sess_po, context=context))
1231- #value = sum(po.procurement_id.purchase_id.amount_total
1232- # for seance in session_id.seance_ids
1233- # for po in seance.purchase_line_ids
1234- # if po.procurement_id and po.procurement_id.purchase_id)
1235-
1236- value += sum(request.purchase_order_id.amount_untaxed
1237- for request in session_id.request_ids
1238- if request.purchase_order_id and request.state in ('accepted', 'done'))
1239-
1240- product_lines[product_line_id]['sessions'][sl.session_id] = value
1241-
1242- if sl.kind == 'exam' and sl.course_id and sl.course_id.category_id:
1243- product_lines[product_line_id]['exams'].setdefault(sl.course_id.category_id, {'subscription_count' : 0,
1244- 'price' : 0.0,
1245- }
1246- )
1247- product_line = product_lines[product_line_id]['exams'][sl.course_id.category_id]
1248- product_line['subscription_count'] += 1
1249- product_line['price'] += sl.price
1250-
1251- for pl, data in product_lines.iteritems():
1252- subscription_count = data['subscription_count']
1253-
1254- pl_input = sum(invoice_id.amount_untaxed for invoice_id in data['invoices'])
1255- pl_output = sum( data['sessions'].values() or [0.0])
1256-
1257- pl_balance = pl_input - pl_output
1258-
1259- pl_margin = (pl_input / (pl_output or 1.0)) * 100
1260-
1261- pl_average_price = subscription_count > 0 and (pl_input / subscription_count) or 0
1262- pl_yield = subscription_count > 0 and (pl_balance / subscription_count) or 0
1263-
1264- if ((-0.00001 < pl_input < 0.00001) or (-0.00001 < pl_output < 0.00001)):
1265- pl_margin = _('N/A')
1266+ ], 'Kind', required=True)
1267+ }
1268+
1269+ _defaults = {
1270+ 'date_start': lambda self, cr, uid, context: self.first_day_of_previous_month(cr, uid, context).strftime('%Y-%m-%d'),
1271+ 'date_stop': lambda self, cr, uid, context: self.last_day_of_previous_month(cr, uid, context).strftime('%Y-%m-%d'),
1272+ 'year': lambda *a: -1,
1273+ 'kind': lambda *a: 'product_lines',
1274+ }
1275+
1276+
1277+ def first_day_of_previous_month(self, cr, uid, context=None):
1278+ return dt.strptime((dt.today() - dt.RelativeDate(months=1)).strftime('%Y-%m-01'), '%Y-%m-%d')
1279+
1280+ def last_day_of_previous_month(self, cr, uid, context=None):
1281+ return self.first_day_of_previous_month(cr, uid, context) + dt.RelativeDate(months=1, seconds=-1)
1282+
1283+ def previous_date(self, cr, uid, date, year, context=None):
1284+ return dt.strptime(date, '%Y-%m-%d') + dt.RelativeDate(years=year)
1285+
1286+ def previous_period(self, cr, uid, date_start, date_stop, year, context=None):
1287+ return (self.previous_date(cr, uid, date_start, year,context), self.previous_date(cr, uid, date_stop, year, context))
1288+
1289+ def compute_theoretical_product_lines(self, cr, uid, ids, date_start, date_stop, kind, context=None):
1290+ if context is None:
1291+ context = {}
1292+ session_pool = self.pool.get('training.session')
1293+ subl_pool = self.pool.get('training.subscription.line')
1294+ prodline_pool = self.pool.get('training.course_category')
1295+ offer_pool = self.pool.get('training.offer')
1296+ trcv_pool = self.pool.get('training.report.costs.view')
1297+
1298+ cache_seance = {}
1299+ cache_session = {}
1300+ product_line = {} # dict containing cost + revenue per product lines
1301+
1302+ query_base = "SELECT * FROM training_report_costs_view "
1303+ query = "WHERE seance_date BETWEEN %s AND %s AND offer_kind = %s"
1304+ query_args = (date_start, date_stop, kind)
1305+
1306+ if kind == 'intra':
1307+ cr.execute("SELECT DISTINCT(session_id) FROM training_report_intra_session_seance_view " + query, query_args)
1308+ else:
1309+ cr.execute("SELECT DISTINCT(session_id) FROM training_report_costs_view " + query, query_args)
1310+ session_ids = [ x[0] for x in cr.fetchall() ]
1311+ trcv_pool.docache_session_populate(cr, uid, cache_session, session_ids)
1312+
1313+ if kind == 'intra':
1314+ cr.execute("SELECT DISTINCT(seance_id) FROM training_report_intra_session_seance_view " + query, query_args)
1315+ else:
1316+ cr.execute("SELECT DISTINCT(seance_id) FROM training_report_costs_view " + query, query_args)
1317+ seance_ids = [ x[0] for x in cr.fetchall() ]
1318+ trcv_pool.docache_seance_populate(cr, uid, cache_seance, seance_ids)
1319+
1320+ if kind != 'intra':
1321+ cr.execute(query_base + query, query_args)
1322+ for theor_cost in cr.dictfetchall():
1323+ c_session_id = theor_cost['session_id']
1324+ c_seance_id = theor_cost['seance_id']
1325+
1326+ if c_session_id not in cache_seance[c_seance_id]['sessions_ratio']:
1327+ # seance already cached, but we still need to update the session ratio
1328+ session_total_duration = cache_session[theor_cost['session_id']]['duration']
1329+ cache_seance[c_seance_id]['sessions_ratio'][c_session_id] = cache_seance[c_seance_id]['duration'] / session_total_duration
1330+
1331+ # all things are cached now
1332+ c_seance = cache_seance[theor_cost['seance_id']]
1333+ c_prodline_id = theor_cost['product_line_id']
1334+ if c_prodline_id not in product_line:
1335+ plo = prodline_pool.browse(cr, uid, c_prodline_id)
1336+ product_line[c_prodline_id] = {
1337+ 'id': c_prodline_id,
1338+ 'name': plo.name,
1339+ 'costs': 0.0,
1340+ 'revenues': 0.0,
1341+ 'subscriptions': set(),
1342+ }
1343+ pl = product_line[c_prodline_id]
1344+ pl['costs'] += c_seance['trainer_cost'] + c_seance['proc_cost']
1345+ pl['revenues'] += c_seance['sessions_ratio'][theor_cost['session_id']] * trcv_pool.get_sale_price(cr, uid, theor_cost, context=context)
1346+ pl['subscriptions'].add(theor_cost['id'])
1347+ else: # kind == 'intra'
1348+ cr.execute("SELECT * FROM training_report_intra_session_seance_view " + query, query_args)
1349+ for theor_intra in cr.dictfetchall():
1350+ c_session_id = theor_intra['session_id']
1351+ c_seance_id = theor_intra['seance_id']
1352+
1353+ if c_session_id not in cache_seance[c_seance_id]['sessions_ratio']:
1354+ # seance already cached, but we still need to update the session ratio
1355+ session_total_duration = cache_session[theor_intra['session_id']]['duration']
1356+ cache_seance[c_seance_id]['sessions_ratio'][c_session_id] = cache_seance[c_seance_id]['duration'] / session_total_duration
1357+
1358+ c_seance = cache_seance[theor_intra['seance_id']]
1359+ c_session = cache_session[theor_intra['session_id']]
1360+
1361+ c_session_ratio = cache_seance[c_seance_id]['sessions_ratio'][c_session_id]
1362+
1363+ c_prodline_id = theor_intra['product_line_id']
1364+ if c_prodline_id not in product_line:
1365+ plo = prodline_pool.browse(cr, uid, c_prodline_id)
1366+ product_line[c_prodline_id] = {
1367+ 'id': c_prodline_id,
1368+ 'name': plo.name,
1369+ 'costs': 0.0,
1370+ 'revenues': 0.0,
1371+ 'subscriptions': set(),
1372+ }
1373+ pl = product_line[c_prodline_id]
1374+ pl['costs'] += c_session_ratio * theor_intra['session_cost']
1375+ pl['revenues'] += c_session_ratio * theor_intra['session_revenue']
1376+ for x in xrange(1, theor_intra['number_of_participants'] + 1):
1377+ pl['subscriptions'].add(x)
1378+
1379+ res = []
1380+ total = { 'revenues': 0.0, 'costs': 0.0 }
1381+ for p, v in product_line.iteritems():
1382+ res.append(v)
1383+ v['subscriptions'] = len(v['subscriptions'])
1384+ v['margin'] = (v['revenues'] / (v['costs'] or 1.0)) * 100
1385+ v['balance'] = (v['revenues'] - v['costs'])
1386+ total['revenues'] += v['revenues']
1387+ total['costs'] += v['costs']
1388+
1389+ total['balance'] = total['revenues'] - total['costs']
1390+ total['margin'] = (total['revenues'] / (total['costs'] or 1.0)) * 100
1391+
1392+ return {
1393+ 'product_lines': res,
1394+ 'total': total,
1395+ 'date_start': date_start,
1396+ 'date_stop': date_stop,
1397+ 'kind': kind,
1398+ }
1399+
1400+# def compute_product_lines_exam(self, cr, uid, ids, date_start, date_stop, context=None):
1401+# if context is None:
1402+# context = {}
1403+# tsl_proxy = self.pool.get('training.subscription.line')
1404+# tsl_ids = tsl_proxy.search(cr, uid,
1405+# [
1406+# ('state', 'not in', ('draft', 'cancelled')),
1407+# ('date', '>=', "%s 00:00:00" % (date_start)),
1408+# ('date', '<=', "%s 23:59:59" % (date_stop)),
1409+# ('kind', '=', 'exam'),
1410+# ],
1411+# context=context)
1412+#
1413+# product_lines = {}
1414+# for sl in tsl_proxy.browse(cr, uid, tsl_ids, context=context):
1415+# if not (sl.course_id and sl.course_id.category_id):
1416+# continue
1417+# product_line_id = sl.course_id.category_id
1418+# product_lines.setdefaults(product_line_id, [])
1419+# if sl.invoice_line_id and sl.invoice_id:
1420+# product_lines[product_line_id].append(sl)
1421+# return True
1422+
1423+ def compute_product_lines(self, cr, uid, ids, date_start, date_stop, kind, context=None):
1424+ if context is None:
1425+ context = {}
1426+ res = []
1427+ tsl_proxy = self.pool.get('training.subscription.line')
1428+ tsl_ids = tsl_proxy.search(cr, uid,
1429+ [
1430+ ('state', 'not in', ('draft', 'cancelled')),
1431+ ('date', '>=', "%s 00:00:00" % (date_start)),
1432+ ('date', '<=', "%s 23:59:59" % (date_stop)),
1433+ ('kind', '=', kind),
1434+ ],
1435+ context=context)
1436+ product_lines = {}
1437+ for sl in tsl_proxy.browse(cr, uid, tsl_ids, context=context):
1438+ session_id = sl.session_id
1439+ invoice_id = sl.invoice_id
1440+ product_line_id = sl.session_id.offer_id.product_line_id
1441+ product_lines.setdefault(product_line_id,
1442+ {
1443+ 'invoices' : set(),
1444+ 'sessions' : {},
1445+ 'subscription_count' : 0,
1446+ 'exams' : {},
1447+ })
1448+ product_lines[product_line_id]['subscription_count'] += 1
1449+
1450+ if invoice_id and sl.invoice_line_id:
1451+ product_lines[product_line_id]['invoices'].add(invoice_id)
1452+
1453+ if sl.session_id not in product_lines[product_line_id]['sessions']:
1454+
1455+ po_pool = self.pool.get('purchase.order')
1456+ sl_sess_seance_ids = [ seance.id for seance in session_id.seance_ids ]
1457+ sl_sess_po = po_pool.search(cr, uid, [('seance_id','in',sl_sess_seance_ids)], context=context)
1458+ value = sum(po.invoice_id and po.invoice_id.amount_untaxed or po.amount_untaxed
1459+ for po in po_pool.browse(cr, uid, sl_sess_po, context=context))
1460+ #value = sum(po.procurement_id.purchase_id.amount_total
1461+ # for seance in session_id.seance_ids
1462+ # for po in seance.purchase_line_ids
1463+ # if po.procurement_id and po.procurement_id.purchase_id)
1464+
1465+ value += sum(request.purchase_order_id.amount_untaxed
1466+ for request in session_id.request_ids
1467+ if request.purchase_order_id and request.state in ('accepted', 'done'))
1468+
1469+ product_lines[product_line_id]['sessions'][sl.session_id] = value
1470+
1471+ if sl.kind == 'exam' and sl.course_id and sl.course_id.category_id:
1472+ product_lines[product_line_id]['exams'].setdefault(sl.course_id.category_id, {'subscription_count' : 0,
1473+ 'price' : 0.0,
1474+ })
1475+ product_line = product_lines[product_line_id]['exams'][sl.course_id.category_id]
1476+ product_line['subscription_count'] += 1
1477+ product_line['price'] += sl.price
1478+
1479+ for pl, data in product_lines.iteritems():
1480+ subscription_count = data['subscription_count']
1481+ pl_input = sum(invoice_id.amount_untaxed for invoice_id in data['invoices'])
1482+ pl_output = sum( data['sessions'].values() or [0.0])
1483+ pl_balance = pl_input - pl_output
1484+ pl_margin = (pl_input / (pl_output or 1.0)) * 100
1485+ pl_average_price = subscription_count > 0 and (pl_input / subscription_count) or 0
1486+ pl_yield = subscription_count > 0 and (pl_balance / subscription_count) or 0
1487+
1488+ if ((-0.00001 < pl_input < 0.00001) or (-0.00001 < pl_output < 0.00001)):
1489+ pl_margin = _('N/A')
1490+
1491+ values = {
1492+ 'id' : pl.id,
1493+ 'name' : pl.name,
1494+ 'input' : pl_input,
1495+ 'output' : pl_output,
1496+ 'balance' : pl_balance,
1497+ 'subscription_count' : subscription_count,
1498+ 'margin' : pl_margin,
1499+ 'average_price' : pl_average_price,
1500+ 'yield' : pl_yield,
1501+ 'exams' : [(category.name, vals['subscription_count'], vals['price']) for category, vals in data['exams'].iteritems()]
1502+ }
1503+
1504+ res.append(values)
1505
1506 values = {
1507- 'id' : pl.id,
1508- 'name' : pl.name,
1509- 'input' : pl_input,
1510- 'output' : pl_output,
1511- 'balance' : pl_balance,
1512- 'subscription_count' : subscription_count,
1513- 'margin' : pl_margin,
1514- 'average_price' : pl_average_price,
1515- 'yield' : pl_yield,
1516- 'exams' : [(category.name, vals['subscription_count'], vals['price']) for category, vals in data['exams'].iteritems()]
1517- }
1518-
1519- res.append(values)
1520-
1521- values = {
1522- 'subscription' : sum(line['subscription_count'] for line in res),
1523- 'input' : sum(line['input'] for line in res),
1524- 'output' : sum(line['output'] for line in res),
1525- }
1526-
1527- values['balance'] = values['input'] - values['output']
1528- if (-0.00001 < values['input'] < 0.00001) or (-0.00001 < values['output'] < 0.00001):
1529- values['margin'] = _('N/A')
1530- else:
1531- values['margin'] = (values['input'] / (values['output'] or 1.0)) * 100.0
1532- values['average_price'] = values['subscription'] > 0 and (values['input'] / values['subscription']) or 0
1533- values['yield'] = values['subscription'] > 0 and (values['balance'] / values['subscription']) or 0
1534-
1535- return {
1536- 'product_lines' : res,
1537- 'total' : values,
1538- 'date_start' : date_start,
1539- 'date_stop' : date_stop,
1540- 'kind' : kind,
1541- }
1542-
1543-def compute_sessions(cr, uid, ids, context, date_start, date_stop):
1544- return {
1545- 'lines' : [],
1546- 'date_start' : date_start,
1547- 'date_stop' : date_stop,
1548- }
1549-
1550-def compute_subscrtiption_partner(cr, uid, ids, context, date_start, date_stop):
1551- cr.execute("""
1552- SELECT res.name, coalesce(sum(tsl.price), 0.0) as total_price
1553- FROM training_subscription_line tsl,
1554- res_partner res,
1555- training_session s
1556- WHERE res.id = tsl.partner_id
1557- AND tsl.session_id = s.id
1558- AND tsl.state IN ('confirmed', 'done')
1559- AND s.date BETWEEN %s AND %s
1560- GROUP BY tsl.partner_id,res.name
1561- ORDER BY total_price DESC
1562- """, (date_start, date_stop))
1563-
1564- return {
1565- 'lines' : [{'name' : name, 'price' : price} for name, price in cr.fetchall()],
1566- 'date_start' : date_start,
1567- 'date_stop' : date_stop,
1568- }
1569-
1570-def compute_count_subscriptions_offer(cr, uid, ids, context, date_start, date_stop):
1571- return {
1572- 'lines' : [],
1573- 'date_start' : date_start,
1574- 'date_stop' : date_stop,
1575- }
1576-
1577-def _select(self, cr, uid, data, context=None):
1578- functions = {
1579- 'sessions' : compute_sessions,
1580- 'count_subscriptions_offer' : compute_count_subscriptions_offer,
1581- 'subscriptions_partner' : compute_subscrtiption_partner,
1582- }
1583-
1584- date_start = data['form']['date_start']
1585- date_stop = data['form']['date_stop']
1586-
1587- old_date_start, old_date_stop = previous_period(date_start, date_stop, data['form']['year'])
1588-
1589- old_date_start = old_date_start.strftime('%Y-%m-%d')
1590- old_date_stop = old_date_stop.strftime('%Y-%m-%d')
1591-
1592- if data['form']['kind'] == 'product_lines':
1593- for kind in ('standard', 'exam', 'intra'):
1594- data['form']['selected_period_%s' % kind] = compute_product_lines(cr, uid, data, context, date_start, date_stop, kind)
1595- data['form']['old_period_%s' % kind] = compute_product_lines(cr, uid, data, context, old_date_start, old_date_stop, kind)
1596- elif data['form']['kind'] == 'theoretical_product_lines':
1597- for kind in ('standard', 'exam', 'intra'):
1598- data['form']['selected_period_%s' % kind] = compute_theoretical_product_lines(cr, uid, data, context, date_start, date_stop, kind)
1599- else:
1600- function = functions[data['form']['kind']]
1601- data['form']['selected_period'] = function(cr, uid, data, context, date_start, date_stop)
1602- data['form']['old_period'] = function(cr, uid, data, context, old_date_start, old_date_stop)
1603-
1604- print(">>> _select :: got dataz" % (data))
1605- return data['form']
1606-
1607-class wizard_report(wizard.interface):
1608- def _select_report(self, cr, uid, data, context=None):
1609- return "report_%s" % (data['form']['kind'],)
1610-
1611- states = {
1612- 'init': {
1613- 'result': {'type':'form',
1614- 'arch':_aged_trial_form,
1615- 'fields':_aged_trial_fields,
1616- 'state':[('end','Cancel'),('choice','Print')]},
1617- },
1618- 'choice' : {
1619- 'actions' : [],
1620- 'result' : { 'type' : 'choice', 'next_state' : _select_report },
1621- },
1622- 'report_product_lines': {
1623- 'actions': [_select],
1624- 'result': {'type' : 'print',
1625- 'report' : 'training.session.volume',
1626- 'state' : 'end'},
1627- },
1628- 'report_theoretical_product_lines': {
1629- 'actions': [_select],
1630- 'result': {
1631- 'type': 'print',
1632- 'report': 'training.session.volume.theoretical',
1633- 'state': 'end',
1634- },
1635- },
1636- 'report_sessions' : {
1637- 'actions' : [_select],
1638- 'result' : {
1639- 'type' : 'print',
1640- 'report' : 'training.session.report',
1641- 'state' : 'end',
1642- },
1643- },
1644- 'report_count_subscriptions_offer' : {
1645- 'actions' : [_select],
1646- 'result' : {
1647- 'type' : 'print',
1648- 'report' : 'training.count.subscriptions.offer',
1649- 'state' : 'end',
1650- },
1651- },
1652- 'report_subscriptions_partner' : {
1653- 'actions' : [_select],
1654- 'result' : {
1655- 'type' : 'print',
1656- 'report' : 'training.subscriptions.partner',
1657- 'state' : 'end',
1658- }}
1659- }
1660-
1661-wizard_report('training.session.volume.report')
1662+ 'subscription' : sum(line['subscription_count'] for line in res),
1663+ 'input' : sum(line['input'] for line in res),
1664+ 'output' : sum(line['output'] for line in res),
1665+ }
1666+
1667+ values['balance'] = values['input'] - values['output']
1668+ if (-0.00001 < values['input'] < 0.00001) or (-0.00001 < values['output'] < 0.00001):
1669+ values['margin'] = _('N/A')
1670+ else:
1671+ values['margin'] = (values['input'] / (values['output'] or 1.0)) * 100.0
1672+ values['average_price'] = values['subscription'] > 0 and (values['input'] / values['subscription']) or 0
1673+ values['yield'] = values['subscription'] > 0 and (values['balance'] / values['subscription']) or 0
1674+
1675+ return {
1676+ 'product_lines' : res,
1677+ 'total' : values,
1678+ 'date_start' : date_start,
1679+ 'date_stop' : date_stop,
1680+ 'kind' : kind,
1681+ }
1682+
1683+ def compute_sessions(self, cr, uid, ids, date_start, date_stop, context):
1684+ return {
1685+ 'lines' : [],
1686+ 'date_start' : date_start,
1687+ 'date_stop' : date_stop,
1688+ }
1689+
1690+ def compute_subscrtiption_partner(self, cr, uid, ids, date_start, date_stop, context):
1691+ cr.execute("""
1692+ SELECT res.name, coalesce(sum(tsl.price), 0.0) as total_price
1693+ FROM training_subscription_line tsl,
1694+ res_partner res,
1695+ training_session s
1696+ WHERE res.id = tsl.partner_id
1697+ AND tsl.session_id = s.id
1698+ AND tsl.state IN ('confirmed', 'done')
1699+ AND s.date BETWEEN %s AND %s
1700+ GROUP BY tsl.partner_id,res.name
1701+ ORDER BY total_price DESC
1702+ """, (date_start, date_stop))
1703+
1704+ return {
1705+ 'lines' : [{'name' : name, 'price' : price} for name, price in cr.fetchall()],
1706+ 'date_start' : date_start,
1707+ 'date_stop' : date_stop,
1708+ }
1709+
1710+ def compute_count_subscriptions_offer(self, cr, uid, ids, date_start, date_stop, context):
1711+ return {
1712+ 'lines' : [],
1713+ 'date_start' : date_start,
1714+ 'date_stop' : date_stop,
1715+ }
1716+
1717+ def _select(self, cr, uid, data, context=None):
1718+ if context is None:
1719+ context = {}
1720+ functions = {
1721+ 'sessions' : self.compute_sessions,
1722+ 'count_subscriptions_offer' : self.compute_count_subscriptions_offer,
1723+ 'subscriptions_partner' : self.compute_subscrtiption_partner,
1724+ }
1725+
1726+ date_start = data['form']['date_start']
1727+ date_stop = data['form']['date_stop']
1728+
1729+ old_date_start, old_date_stop = self.previous_period(cr, uid, date_start, date_stop, data['form']['year'], context)
1730+
1731+ old_date_start = old_date_start.strftime('%Y-%m-%d')
1732+ old_date_stop = old_date_stop.strftime('%Y-%m-%d')
1733+
1734+ if data['form']['kind'] == 'product_lines':
1735+ for kind in ('standard', 'exam', 'intra'):
1736+ data['form']['selected_period_%s' % kind] = self.compute_product_lines(cr, uid, data, date_start, date_stop, kind, context)
1737+ data['form']['old_period_%s' % kind] = self.compute_product_lines(cr, uid, data, old_date_start, old_date_stop, kind, context)
1738+ elif data['form']['kind'] == 'theoretical_product_lines':
1739+ for kind in ('standard', 'exam', 'intra'):
1740+ data['form']['selected_period_%s' % kind] = self.compute_theoretical_product_lines(cr, uid, data, date_start, date_stop, kind, context)
1741+ else:
1742+ function = functions[data['form']['kind']]
1743+ data['form']['selected_period'] = function(cr, uid, data, date_start, date_stop, context)
1744+ data['form']['old_period'] = function(cr, uid, data, old_date_start, old_date_stop, context)
1745+
1746+ return data['form']
1747+
1748+ def action_print(self, cr, uid, ids, context=None):
1749+ if context is None:
1750+ context = {}
1751+ datas = {'form':{}, 'ids': context.get('active_ids', [])}
1752+ res = self.read(cr, uid, ids, ['date_start', 'date_stop', 'year', 'kind'], context)
1753+ res = res and res[0] or {}
1754+ datas['form'].update(res)
1755+
1756+ report_name = False
1757+ if res.get('kind',False) == 'product_lines':
1758+ report_name = 'training.session.volume'
1759+ elif res.get('kind',False) == 'theoretical_product_lines':
1760+ report_name = 'training.session.volume.theoretical'
1761+ elif res.get('kind',False) == 'sessions':
1762+ report_name = 'training.session.report'
1763+ elif res.get('kind',False) == 'count_subscriptions_offer':
1764+ report_name = 'training.count.subscriptions.offer'
1765+ elif res.get('kind',False) == 'subscriptions_partner':
1766+ report_name = 'training.subscriptions.partner'
1767+ if not report_name:
1768+ return {}
1769+
1770+ new_datas = self._select(cr, uid, datas, context)
1771+ datas['form'].update(new_datas)
1772+ return {
1773+ 'type': 'ir.actions.report.xml',
1774+ 'report_name': report_name,
1775+ 'datas': datas,
1776+ }
1777+
1778+training_report_session_volume()
1779
1780 # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
1781
1782=== added file 'training_report/wizard/training_report_session_volume_view.xml'
1783--- training_report/wizard/training_report_session_volume_view.xml 1970-01-01 00:00:00 +0000
1784+++ training_report/wizard/training_report_session_volume_view.xml 2011-03-17 10:37:29 +0000
1785@@ -0,0 +1,37 @@
1786+<openerp>
1787+ <data>
1788+
1789+ <record model="ir.ui.view" id="view_training_report_session_volume_form">
1790+ <field name="name">training.report.session.volume.form</field>
1791+ <field name="model">training.report.session.volume</field>
1792+ <field name="type">form</field>
1793+ <field name="arch" type="xml">
1794+ <form string="Session Volume Report">
1795+ <separator string="Period" colspan="4" />
1796+ <field name="date_start"/>
1797+ <field name="date_stop"/>
1798+ <separator string="Year" colspan="4" />
1799+ <field name="year" />
1800+ <separator string="Report" colspan="4" />
1801+ <field name="kind" />
1802+ <separator colspan="4" />
1803+ <group colspan="4" col="2">
1804+ <button string="Cancel" special="cancel" type="object" icon="gtk-cancel"/>
1805+ <button name="action_print" string="Print" type="object" icon="gtk-print"/>
1806+ </group>
1807+ </form>
1808+ </field>
1809+ </record>
1810+
1811+ <record model="ir.actions.act_window" id="action_training_report_session_volume_form_act">
1812+ <field name="name">Report Volume</field>
1813+ <field name="res_model">training.report.session.volume</field>
1814+ <field name="view_type">form</field>
1815+ <field name="view_mode">form</field>
1816+ <field name="target">new</field>
1817+ </record>
1818+
1819+ <menuitem id="training_report_volume_mi" parent="menu_training_report" action="action_training_report_session_volume_form_act"/>
1820+
1821+ </data>
1822+</openerp>

Subscribers

People subscribed via source and target branches