openerp-dev-web team mailing list archive
-
openerp-dev-web team
-
Mailing list archive
-
Message #04293
[Merge] lp:~openerp-dev/openobject-addons/addons-training-report-ysa into lp:~openobject-training/openobject-addons/training_with_history
Yogesh(Open ERP) has proposed merging lp:~openerp-dev/openobject-addons/addons-training-report-ysa into lp:~openobject-training/openobject-addons/training_with_history.
Requested reviews:
Bhumika (OpenERP) (sbh-openerp)
For more details, see:
https://code.launchpad.net/~openerp-dev/openobject-addons/addons-training-report-ysa/+merge/53779
training_report:- convert v5 to v6 and fix problem.
--
https://code.launchpad.net/~openerp-dev/openobject-addons/addons-training-report-ysa/+merge/53779
Your team OpenERP R&D Team is subscribed to branch lp:~openerp-dev/openobject-addons/addons-training-report-ysa.
=== modified file 'training_report/__init__.py'
--- training_report/__init__.py 2009-08-24 08:58:54 +0000
+++ training_report/__init__.py 2011-03-17 10:37:29 +0000
@@ -23,5 +23,5 @@
import training_report
import report
import wizard
+
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
-
=== renamed file 'training_report/__terp__.py' => 'training_report/__openerp__.py'
--- training_report/__terp__.py 2011-02-25 12:33:02 +0000
+++ training_report/__openerp__.py 2011-03-17 10:37:29 +0000
@@ -20,7 +20,6 @@
#
##############################################################################
-
{
'name': 'Training Management - Reporting',
'version': '1.0',
@@ -36,6 +35,7 @@
'depends': [
'training',
'training_intra',
+ 'training_exam',
],
'init_xml': [],
'update_xml': [
@@ -43,9 +43,13 @@
'security/ir.model.access.csv',
'report_training_view.xml',
'training_report.xml',
+ 'wizard/training_report_account_analytic_balance_year_view.xml',
+ 'wizard/training_report_course_profitability_view.xml',
+ 'wizard/training_report_session_volume_view.xml',
],
'demo_xml': [],
'installable': True,
'active': False,
}
+
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
=== modified file 'training_report/report/analytic_balance_year.py'
--- training_report/report/analytic_balance_year.py 2009-11-25 16:36:08 +0000
+++ training_report/report/analytic_balance_year.py 2011-03-17 10:37:29 +0000
@@ -20,10 +20,8 @@
#
##############################################################################
-import pooler
import time
from report import report_sxw
-import datetime
class account_analytic_balance_year(report_sxw.rml_parse):
def __init__(self, cr, uid, name, context):
@@ -43,12 +41,9 @@
})
def _lines_g(self, account_id, date1, date2):
- year=[]
- year.append(int(date1[0:4])-1)
- year.append(int(date1[0:4]))
account_analytic_obj = self.pool.get('account.analytic.account')
- ids = account_analytic_obj.search(self.cr, self.uid,
- [('parent_id', 'child_of', [account_id])])
+ year = [int(date1[0:4]) - 1, int(date1[0:4])]
+ ids = account_analytic_obj.search(self.cr, self.uid, [('parent_id', 'child_of', [account_id])])
self.cr.execute("SELECT aa.name AS name, aa.code AS code, \
sum(aal.amount) AS balance, sum(aal.unit_amount) AS quantity \
FROM account_analytic_line AS aal, account_account AS aa \
@@ -58,49 +53,46 @@
And date_part('year',date) in ("+ ','.join(map(str, year)) +") \
GROUP BY aal.general_account_id, aa.name, aa.code, aal.code ,date_part('year',date)\
ORDER BY aal.code", (date1[5:10], date2[5:10]))
- res = self.cr.dictfetchall()
+ result = self.cr.dictfetchall()
- for r in res:
- if r['balance'] > 0:
- r['debit'] = r['balance']
- r['credit'] = 0.0
- elif r['balance'] < 0:
- r['debit'] = 0.0
- r['credit'] = -r['balance']
+ for res in result:
+ if res.get('balance') > 0:
+ res.update({
+ 'debit' : res.get('balance',0),
+ 'credit' : 0.0
+ })
+ elif res.get('balance') < 0:
+ res.update({
+ 'debit' : 0.0,
+ 'credit' : -res.get('balance',0)
+ })
else:
- r['balance'] == 0
- r['debit'] = 0.0
- r['credit'] = 0.0
- return res
+ res.update({
+ 'balance' : 0.0,
+ 'debit' : 0.0,
+ 'credit' : -res.get('balance',0)
+ })
+ return result
def _get_year(self,date1,date2):
- year=[]
- year.append(str(int(date1[0:4])-1))
- year.append(str(int(date1[0:4])))
- return year
+ return [str(int(date1[0:4])-1), str(int(date1[0:4]))]
+
def _get_data(self, account_id, date1, date2):
- res=[]
- r={}
- year=[]
- year.append(str(int(date1[0:4])-1))
- year.append(str(int(date1[0:4])))
+ year = [str(int(date1[0:4])-1), str(int(date1[0:4]))]
debit = self._move_sum_debit(account_id, date1, date2)
credit = self._move_sum_credit(account_id, date1, date2)
- amount=self._move_sum_balance(account_id, date1, date2)
- r['debit']=debit
- r['credit']=credit
- r['amount']=amount
- r['year']=year
- return r
+ amount = self._move_sum_balance(account_id, date1, date2)
+ return {
+ 'debit' : debit,
+ 'credit' : credit,
+ 'amount' : amount,
+ 'year' : year
+ }
def _move_sum_debit(self, account_id, date1, date2):
- res=[]
- year=[]
- year.append(int(date1[0:4])-1)
- year.append(int(date1[0:4]))
account_analytic_obj = self.pool.get('account.analytic.account')
- ids = account_analytic_obj.search(self.cr, self.uid,
- [('parent_id', 'child_of', [account_id])])
+ year [int(date1[0:4])-1, int(date1[0:4])]
+ ids = account_analytic_obj.search(self.cr, self.uid, [('parent_id', 'child_of', [account_id])])
self.cr.execute("SELECT sum(amount)\
FROM account_analytic_line \
WHERE account_id in ("+ ','.join(map(str, ids)) +") \
@@ -108,66 +100,49 @@
and date_part('year',date) in ("+ ','.join(map(str, year)) +") \
group by date_part('year',date)",(date1[5:10], date2[5:10]))
- res =self.cr.dictfetchall()
- return res
+ return self.cr.dictfetchall()
def _move_sum_credit(self, account_id, date1, date2):
- year=[]
- res=[]
- year.append(int(date1[0:4])-1)
- year.append(int(date1[0:4]))
account_analytic_obj = self.pool.get('account.analytic.account')
- ids = account_analytic_obj.search(self.cr, self.uid,
- [('parent_id', 'child_of', [account_id])])
+ year = [int(date1[0:4])-1, int(date1[0:4])]
+ ids = account_analytic_obj.search(self.cr, self.uid, [('parent_id', 'child_of', [account_id])])
self.cr.execute("SELECT -sum(amount) as sum \
FROM account_analytic_line \
WHERE account_id in ("+ ','.join(map(str, ids)) +") \
AND to_char(date, 'MM-DD')>=%s AND to_char(date, 'MM-DD')<=%s AND amount>0 \
and date_part('year',date) in ("+ ','.join(map(str, year)) +") \
group by date_part('year',date)",(date1[5:10], date2[5:10]))
- res= self.cr.dictfetchall()
- return res
+ return self.cr.dictfetchall()
def _move_sum_balance(self, account_id, date1, date2):
- res=[]
- account_analytic_obj = self.pool.get('account.analytic.account')
- ids = account_analytic_obj.search(self.cr, self.uid,
- [('parent_id', 'child_of', [account_id])])
+ result = []
debit = self._move_sum_debit(account_id, date1, date2)
- temp =len(debit)
credit = self._move_sum_credit(account_id, date1, date2)
- for i in range(temp):
- res.append(debit[i]['sum']-credit[i]['sum'])
- return res
+ for index in range(len(debit)):
+ result.append(debit[index]['sum'] - credit[index]['sum'])
+ return result
def _move_sum_quantity(self, account_id, date1, date2):
- year=[]
- year.append(int(date1[0:4])-1)
- year.append(int(date1[0:4]))
account_analytic_obj = self.pool.get('account.analytic.account')
- ids = account_analytic_obj.search(self.cr, self.uid,
- [('parent_id', 'child_of', [account_id])])
+ year = [int(date1[0:4])-1, int(date1[0:4])]
+ ids = account_analytic_obj.search(self.cr, self.uid, [('parent_id', 'child_of', [account_id])])
self.cr.execute("SELECT sum(unit_amount) as sum,date_part('year',date) as year \
FROM account_analytic_line \
WHERE account_id in ("+ ','.join(map(str, ids)) +") \
AND to_char(date, 'MM-DD')>=%s AND to_char(date, 'MM-DD')<=%s AND amount<0 \
and date_part('year',date) in ("+ ','.join(map(str, year)) +") \
group by date_part('year',date)",(date1[5:10], date2[5:10]))
+
return self.cr.dictfetchall() or []
-
def _sum_debit(self, accounts, date1, date2):
-
- year=[]
- res=[]
- year.append(int(date1[0:4])-1)
- year.append(int(date1[0:4]))
+ account_analytic_obj = self.pool.get('account.analytic.account')
+ year = [int(date1[0:4])-1, int(date1[0:4])]
ids = map(lambda x: x.id, accounts)
if not len(ids):
return 0.0
- account_analytic_obj = self.pool.get('account.analytic.account')
- ids2 = account_analytic_obj.search(self.cr, self.uid,
- [('parent_id', 'child_of', ids)])
+
+ ids2 = account_analytic_obj.search(self.cr, self.uid, [('parent_id', 'child_of', ids)])
self.cr.execute("SELECT sum(amount) as sum \
FROM account_analytic_line \
WHERE account_id in ("+ ','.join(map(str, ids2)) + " ) \
@@ -175,20 +150,16 @@
and date_part('year',date) in ("+ ','.join(map(str, year)) + " ) \
group by date_part('year',date) ",
(date1[5:10], date2[5:10]))
- res= self.cr.dictfetchall()
- return res
+
+ return self.cr.dictfetchall()
def _sum_credit(self, accounts, date1, date2):
- year=[]
- year.append(int(date1[0:4])-1)
- year.append(int(date1[0:4]))
+ account_analytic_obj = self.pool.get('account.analytic.account')
+ year = [int(date1[0:4])-1, int(date1[0:4])]
ids = map(lambda x: x.id, accounts)
if not len(ids):
return 0.0
- ids = map(lambda x: x.id, accounts)
- account_analytic_obj = self.pool.get('account.analytic.account')
- ids2 = account_analytic_obj.search(self.cr, self.uid,
- [('parent_id', 'child_of', ids)])
+ ids2 = account_analytic_obj.search(self.cr, self.uid, [('parent_id', 'child_of', ids)])
self.cr.execute("SELECT -sum(amount) as sum \
FROM account_analytic_line \
WHERE account_id in ("+ ','.join(map(str, ids2)) +") \
@@ -196,21 +167,18 @@
and date_part('year',date) in ("+ ','.join(map(str, year)) +") \
group by date_part('year',date) ",
(date1[5:10], date2[5:10]))
- res= self.cr.dictfetchall()
- return res
+ return self.cr.dictfetchall()
+
def _sum_balance(self, accounts, date1, date2):
debit = self._sum_debit(accounts, date1, date2) or 0.0
credit = self._sum_credit(accounts, date1, date2) or 0.0
- res=[]
- temp=len(debit)
- for i in range(temp):
- res.append(debit[i]['sum']-credit[i]['sum'])
- return res
-
+ result = []
+ for index in range(len(debit)):
+ result.append(debit[index]['sum'] - credit[index]['sum'])
+ return result
report_sxw.report_sxw('report.account.analytic.account.balance.year',
'account.analytic.account','addons/training_report/report/analytic_balance_year.rml',
parser=account_analytic_balance_year, header=False)
-
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
=== modified file 'training_report/report_training_view.xml'
--- training_report/report_training_view.xml 2010-10-05 14:48:03 +0000
+++ training_report/report_training_view.xml 2011-03-17 10:37:29 +0000
@@ -3,14 +3,6 @@
<data>
<menuitem id="menu_training_report" name="Reporting" parent="training.training_mi" sequence="100"/>
- <wizard id="training_session_volume_report_wizard"
- model="training.session"
- menu="False"
- name="training.session.volume.report"
- string="Report Volume"/>
-
- <menuitem id="training_report_volume_mi" parent="menu_training_report" type="wizard" action="training_session_volume_report_wizard"/>
-
<record model="ir.ui.view" id="training_report_wizard_form">
<field name="name">training_report_wizard</field>
<field name="model">training.report.wizard</field>
@@ -84,5 +76,6 @@
</graph>
</field>
</record>
+
</data>
</openerp>
=== modified file 'training_report/training_report.py'
--- training_report/training_report.py 2011-02-09 15:47:36 +0000
+++ training_report/training_report.py 2011-03-17 10:37:29 +0000
@@ -20,10 +20,9 @@
#
##############################################################################
+from osv import osv
+from osv import fields
import time
-import datetime
-from osv import fields,osv
-import tools
from tools.sql import drop_view_if_exists
import xlwt
import base64
@@ -36,14 +35,14 @@
from training.training import training_course_kind_compute
# http://code.activestate.com/recipes/476197-first-last-day-of-the-month/#c1
-def get_first_day(dt, d_years=0, d_months=0):
- # d_years, d_months are "deltas" to apply to dt
- y, m = dt.year + d_years, dt.month + d_months
- a, m = divmod(m-1, 12)
- return date(y+a, m+1, 1)
+def get_first_day(date, date_years=0, date_months=0):
+ # date_years, date_months are "deltas" to apply to date
+ year, month = date.year + date_years, datet.month + date_months
+ avg, month = divmod(month - 1, 12)
+ return date(year + avg, month + 1, 1)
-def get_last_day(dt):
- return get_first_day(dt, 0, 1) + timedelta(-1)
+def get_last_day(date):
+ return get_first_day(date, 0, 1) + timedelta(-1)
class subscription_line(osv.osv):
@@ -129,21 +128,11 @@
class training_report_wizard(osv.osv):
_name = 'training.report.wizard'
-
_columns = {
'date_start' : fields.date('Date Start', required=True),
'date_stop' : fields.date('Date Stop', required=True),
-
- 'state' : fields.selection([('init', 'Init'),
- ('result', 'Result')],
- 'State',
- required=True,
- readonly=True),
-
- 'report' : fields.selection([(report_name, report['title']) for report_name, report in REPORTS.iteritems()],
- 'Report',
- required=True),
-
+ 'state' : fields.selection([('init', 'Init'),('result', 'Result')], 'State', required=True, readonly=True),
+ 'report' : fields.selection([(report_name, report['title']) for report_name, report in REPORTS.iteritems()], 'Report', required=True),
'filename' : fields.char('Filename', size=128, readonly=True),
'file_data' : fields.binary('File', readonly=True),
}
@@ -155,11 +144,14 @@
'state' : lambda *a: 'init',
}
-
def action_close(self, cr, uid, ids, context=None):
return {'type' : 'ir.actions.act_window_close'}
def action_generate_report(self, cr, uid, ids, context=None):
+ if not ids:
+ return False
+ if context is None:
+ context = {}
def execute_query(group_column, column_name):
cr.execute("""
SELECT l.%(gc)s as %(cn)s,
@@ -225,6 +217,7 @@
""" % {'gc': group_column, 'cn': column_name}
, (this.date_start, this.date_stop))
return cr.fetchall()
+
def stream_write_row(row_id, values):
row = stream.row(row_id)
for idx, value in enumerate(values):
@@ -277,14 +270,14 @@
if this.report == 'sale.partner':
- for x in execute_query_invoice('partner_id', 'partner_id'):
- row_id = write_to_xls(row_id, x)
+ for temp in execute_query_invoice('partner_id', 'partner_id'):
+ row_id = write_to_xls(row_id, temp)
elif this.report == 'sale.supplier':
- for x in execute_query_invoice_supplier('partner_id', 'partner_id'):
- row_id = write_to_xls(row_id, x)
+ for temp in execute_query_invoice_supplier('partner_id', 'partner_id'):
+ row_id = write_to_xls(row_id, temp)
elif this.report == 'sale.user':
- for x in execute_query('create_uid', 'user_id'):
- row_id = write_to_xls(row_id, x)
+ for temp in execute_query('create_uid', 'user_id'):
+ row_id = write_to_xls(row_id, temp)
elif this.report == 'sale.offer':
cr.execute("""
SELECT l.offer_id as offer_id,
@@ -303,11 +296,11 @@
GROUP BY l.offer_id
""", (this.date_start, this.date_stop))
- for x in cr.fetchall():
- row_id = write_to_xls(row_id, x)
+ for temp in cr.fetchall():
+ row_id = write_to_xls(row_id, temp)
elif this.report == 'sale.product':
- for x in execute_query('product_id', 'product_id'):
- row_id = write_to_xls(row_id, x)
+ for temp in execute_query('product_id', 'product_id'):
+ row_id = write_to_xls(row_id, temp)
elif this.report == 'subscription.offer':
cr.execute("""
SELECT toff.id AS offer_id,
@@ -328,8 +321,8 @@
GROUP BY toff.id, toff.kind
ORDER BY turnover DESC
""", (this.date_start, this.date_stop))
- for x in cr.fetchall():
- row_id = write_to_xls(row_id, x)
+ for temp in cr.fetchall():
+ row_id = write_to_xls(row_id, temp)
wb.save(strIO)
@@ -383,6 +376,7 @@
'offer_kind': fields.char('Offer Kind', size=16, readonly=True,),
'analytic_account_id': fields.many2one('account.analytic.account', 'Analytic Account', readonly=True,),
}
+
training_report_intra_session_seance_view()
class training_report_session_stats_view(osv.osv):
@@ -444,45 +438,47 @@
}
def init(self, cr):
- drop_view_if_exists(cr, 'training_report_seance_stats_view', cascade=True)
+ drop_view_if_exists(cr, 'training_report_seance_purchase_stats_view')
+ drop_view_if_exists(cr, 'training_report_seance_stats_view')
cr.execute("""CREATE OR REPLACE VIEW training_report_seance_stats_view AS (
-select
- tsea.id AS seance_id,
- tsea.kind,
- tsea.duration,
- tsea.course_id,
- tg.name AS group_name,
- 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,
- CASE WHEN tsea.kind = 'exam' THEN pp.id ELSE tct.product_id END AS product_id,
- CASE WHEN tsea.kind = 'exam' THEN pt.standard_price ELSE pt2.standard_price END AS product_price,
- 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,
-
- 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
-
-
-FROM
- training_seance tsea
-LEFT JOIN
- training_participation tp ON (tp.group_id = tsea.group_id AND tp.seance_id = tsea.id)
-INNER JOIN
- product_product pp ON (pp.default_code = 'R50H')
-LEFT JOIN
- training_course tc ON (tsea.kind != 'exam' AND tsea.course_id = tc.id)
-LEFT JOIN
- training_course_type tct ON (tc.course_type_id = tct.id)
-LEFT JOIN
- training_group tg ON (tsea.group_id = tg.id)
-LEFT JOIN
- product_product pp2 ON (tct.product_id = pp2.id)
-LEFT JOIN
- product_template pt ON (pp.product_tmpl_id = pt.id)
-LEFT JOIN
- product_template pt2 ON (pp2.product_tmpl_id = pt2.id)
-GROUP BY
- 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
-
- )""")
+ select
+ tsea.id AS seance_id,
+ tsea.kind,
+ tsea.duration,
+ tsea.course_id,
+ tg.name AS group_name,
+ 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,
+ CASE WHEN tsea.kind = 'exam' THEN pp.id ELSE tct.product_id END AS product_id,
+ CASE WHEN tsea.kind = 'exam' THEN pt.standard_price ELSE pt2.standard_price END AS product_price,
+ 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,
+
+ 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
+
+
+ FROM
+ training_seance tsea
+ LEFT JOIN
+ training_participation tp ON (tp.group_id = tsea.group_id AND tp.seance_id = tsea.id)
+ INNER JOIN
+ product_product pp ON (pp.default_code = 'R50H')
+ LEFT JOIN
+ training_course tc ON (tsea.kind != 'exam' AND tsea.course_id = tc.id)
+ LEFT JOIN
+ training_course_type tct ON (tc.course_type_id = tct.id)
+ LEFT JOIN
+ training_group tg ON (tsea.group_id = tg.id)
+ LEFT JOIN
+ product_product pp2 ON (tct.product_id = pp2.id)
+ LEFT JOIN
+ product_template pt ON (pp.product_tmpl_id = pt.id)
+ LEFT JOIN
+ product_template pt2 ON (pp2.product_tmpl_id = pt2.id)
+ GROUP BY
+ 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
+
+ )""")
+
training_report_seance_stats_view()
class training_report_seance_purchase_stats_view(osv.osv):
@@ -507,16 +503,17 @@
)""")
_columns = {
- 'seance_id': fields.many2one('training.seance', 'Seance', readonly=True,),
- 'product_id': fields.many2one('product.product', 'Product', readonly=True,),
- 'total_qty': fields.integer('Total Product Quantity', readonly=True,),
- 'attachment_id': fields.many2one('ir.attachment', 'Attachment', readonly=True,),
- 'standard_price': fields.float('Product Standard Price', readonly=True,),
+ 'seance_id': fields.many2one('training.seance', 'Seance', readonly=True),
+ 'product_id': fields.many2one('product.product', 'Product', readonly=True),
+ 'total_qty': fields.integer('Total Product Quantity', readonly=True),
+ 'attachment_id': fields.many2one('ir.attachment', 'Attachment', readonly=True),
+ 'standard_price': fields.float('Product Standard Price', readonly=True),
'attachment_price': fields.float('Attachment Price', readonly=True),
'price': fields.float('Purchase Line Price', readonly=True),
'procurement_method': fields.char('Procurement Method', size=16, readonly=True),
'procurement_price': fields.char('Procurement Price', size=16, readonly=True),
}
+
training_report_seance_purchase_stats_view()
class training_report_costs_view(osv.osv):
@@ -525,16 +522,16 @@
_auto = False
_columns = {
- 'session_id': fields.many2one('training.session', 'Session', ),
- 'session_date': fields.datetime('Session Date'),
- 'seance_id': fields.many2one('training.seance', 'Seance', ),
- 'seance_kind': fields.selection(training_course_kind_compute, 'Seance Kind', ),
- 'seance_date': fields.datetime('Seance Date'),
- 'offer_kind': fields.selection(training_offer_kind_compute, 'Offer Kind', ),
- 'offer_id': fields.many2one('training.offer', 'Offer'),
- 'computed_course_id': fields.many2one('training.course', 'Course', ),
- 'computed_analytic_id': fields.many2one('account.analytic.account', 'Analytic Account', ),
- 'product_line_id': fields.many2one('training.course_category', 'Product Line', ),
+ 'session_id': fields.many2one('training.session', 'Session', readonly=True),
+ 'session_date': fields.datetime('Session Date', readonly=True),
+ 'seance_id': fields.many2one('training.seance', 'Seance', readonly=True),
+ 'seance_kind': fields.selection(training_course_kind_compute, 'Seance Kind', readonly=True),
+ 'seance_date': fields.datetime('Seance Date', readonly=True),
+ 'offer_kind': fields.selection(training_offer_kind_compute, 'Offer Kind', readonly=True),
+ 'offer_id': fields.many2one('training.offer', 'Offer', readonly=True),
+ 'computed_course_id': fields.many2one('training.course', 'Course', readonly=True),
+ 'computed_analytic_id': fields.many2one('account.analytic.account', 'Analytic Account', readonly=True),
+ 'product_line_id': fields.many2one('training.course_category', 'Product Line', readonly=True),
}
def init(self, cr):
@@ -577,20 +574,19 @@
for sess_stats in cr.dictfetchall():
sess_stats['duration'] = sess_stats['seances_duration']
cache_session[sess_stats['session_id']] = sess_stats
+ return True
def docache_seance_populate(self, cr, uid, cache_seance, seance_ids):
if not seance_ids:
return
-
query_seance_ids = ','.join(map(str, seance_ids))
-
# pre-compute procurement price
seance_procs_cache = {}
for seance_id in seance_ids:
seance_procs_cache[seance_id] = {
- 'proc_fix': 0.0,
- 'proc_sub': 0.0,
- }
+ 'proc_fix': 0.0,
+ 'proc_sub': 0.0,
+ }
cr.execute("SELECT * FROM training_report_seance_purchase_stats_view trspsv WHERE seance_id IN (%s)" % (query_seance_ids))
for purch_stat in cr.dictfetchall():
price = purch_stat['price']
@@ -610,6 +606,7 @@
seance_stats['sessions_ratio'] = {}
cache_seance[seance_stats['seance_id']] = seance_stats
+ return True
def docache_session(self, cache_session, session):
if session.id not in cache_session:
@@ -618,6 +615,7 @@
'subscription_count': session.confirmed_subscriptions,
'duration': (sum([ seance.duration for seance in session.seance_ids]) or 1.0) / (float(len(session.group_ids)) or 1.0)
}
+ return True
def docache_seance(self, cr, uid, cache_seance, seance, context=None):
if seance.id not in cache_seance:
@@ -662,6 +660,7 @@
'group': seance.group_id.name,
'sessions_ratio': {},
}
+ return True
# print(" group class : %s" % (cache_seance[seance.id]['group']))
# print(" trainer cost : %s" % (cache_seance[seance.id]['trainer_cost']))
@@ -669,16 +668,18 @@
# print(" participant cnt : %s" % (cache_seance[seance.id]['participants']))
def get_sale_price(self, cr, uid, theor_cost, context=None):
+ if context is None:
+ context = {}
offer_pool = self.pool.get('training.offer')
subl_pool = self.pool.get('training.subscription.line')
price = 0.0
- if theor_cost['offer_kind'] == 'intra':
- o = offer_pool.browse(cr, uid, theor_cost['offer_id'])
- pcount = o.number_of_participants or 12
- price = (o.sale_order_id and o.sale_order_id.amount_untaxed or 0.0) / pcount
+ if theor_cost.get('offer_kind',False) == 'intra':
+ offer_data = offer_pool.browse(cr, uid, theor_cost['offer_id'])
+ participant_count = offer_data.number_of_participants or 12
+ price = (offer_data.sale_order_id and offer_data.sale_order_id.amount_untaxed or 0.0) / participant_count
else:
#price = subl_pool.read(cr, uid, theor_cost['id'], ['price'])['price']
- price = theor_cost['subl_price']
+ price = theor_cost.get('subl_price')
return price
training_report_costs_view()
@@ -716,7 +717,7 @@
}
def search(self, cr, uid, args, offset=0, limit=None, order=None, context=None, count=False):
- if not context:
+ if context is None:
context = {}
if context.get('date_filter', '') == 'current_year':
args.extend([('date','>=',time.strftime('%Y-01-01')),('date','<=',time.strftime('%Y-12-31'))])
@@ -725,10 +726,8 @@
# month_start_dt = datetime.datetime(map(int, month_start.split('-')))
# month_end = get_last_day(month_start_dt, d_month=1).strftime('%Y-%m-%d')
# args.extend
- r = super(training_report_confirmed_subscription_count, self).search(cr, uid, args, offset=offset, limit=limit, order=order, context=context, count=count)
- return r
+ return super(training_report_confirmed_subscription_count, self).search(cr, uid, args, offset=offset, limit=limit, order=order, context=context, count=count)
training_report_confirmed_subscription_count()
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
-
=== modified file 'training_report/training_report.xml'
--- training_report/training_report.xml 2009-11-25 16:36:08 +0000
+++ training_report/training_report.xml 2011-03-17 10:37:29 +0000
@@ -1,6 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<openerp>
<data>
+
<report auto="False"
id="account_analytic_account_balance"
menu="False"
@@ -9,12 +10,6 @@
rml="/training_report/report/analytic_balance_year.rml"
string="Analytic Balance Year"/>
- <wizard id="account_analytic_account_balance_report_year"
- keyword="client_print_multi"
- model="account.analytic.account"
- name="account.analytic.account.balance.year.report"
- string="Analytic Balance Year"/>
-
<report auto="False"
id="course_profitability"
menu="False"
@@ -24,13 +19,5 @@
rml="training_report/report/course_profitability.rml"
/>
- <wizard id="course_profitability_report"
- keyword="client_print_multi"
- model="training.course"
- name="training.course.profitability.report"
- string="Course Profitablility"/>
-
-
-
</data>
</openerp>
=== modified file 'training_report/wizard/__init__.py'
--- training_report/wizard/__init__.py 2010-03-10 20:55:08 +0000
+++ training_report/wizard/__init__.py 2011-03-17 10:37:29 +0000
@@ -21,9 +21,9 @@
##############################################################################
-import wizard_account_analytic_balance_report_year_to_date
-import wizard_course_profitability
-import wizard_session_volume
+import training_report_account_analytic_balance_year
+import training_report_course_profitability
+import training_report_session_volume
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
=== renamed file 'training_report/wizard/wizard_account_analytic_balance_report_year_to_date.py' => 'training_report/wizard/training_report_account_analytic_balance_year.py'
--- training_report/wizard/wizard_account_analytic_balance_report_year_to_date.py 2009-11-25 16:36:08 +0000
+++ training_report/wizard/training_report_account_analytic_balance_year.py 2011-03-17 10:37:29 +0000
@@ -20,38 +20,36 @@
#
##############################################################################
+
+from osv import osv
+from osv import fields
import time
-import wizard
-import datetime
-
-dates_form = '''<?xml version="1.0"?>
-<form string="Select period">
- <field name="date1"/>
- <field name="date2"/>
-</form>'''
-
-dates_fields = {
- 'date1': {'string':'Start of period', 'type':'date', 'required':True, 'default': lambda *a: time.strftime('%Y-01-01')},
- 'date2': {'string':'End of period', 'type':'date', 'required':True, 'default': lambda *a: time.strftime('%Y-%m-%d')},
-}
-
-
-class wizard_report(wizard.interface):
-
-
- states = {
- 'init': {
- 'actions': [],
- 'result': {'type':'form', 'arch':dates_form, 'fields':dates_fields, 'state':[('end','Cancel'), ('report','Print')]}
- },
- 'report': {
- 'actions': [],
- 'result': {'type':'print', 'report':'account.analytic.account.balance.year', 'state':'end'}
+
+class training_report_account_analytic_balance_year(osv.osv_memory):
+ _name = 'training.report.account.analytic.balance.year'
+ _columns = {
+ 'date1' : fields.date('Start of period', required=True),
+ 'date2' : fields.date('End of period', required=True),
+ }
+
+ _defaults = {
+ 'date1': lambda *a: time.strftime('%Y-01-01'),
+ 'date2': lambda *a: time.strftime('%Y-%m-%d'),
+ }
+
+ def action_report(self, cr, uid, ids, context=None):
+ if context is None:
+ context = {}
+ datas = {'form':{}, 'ids': context.get('active_ids', [])}
+ res = self.read(cr, uid, ids, ['date1', 'date2'], context)
+ res = res and res[0] or {}
+ datas['form'].update(res)
+ return {
+ 'type': 'ir.actions.report.xml',
+ 'report_name': 'account.analytic.account.balance.year',
+ 'datas': datas,
}
- }
-wizard_report('account.analytic.account.balance.year.report')
-
-
+
+training_report_account_analytic_balance_year()
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
-
=== added file 'training_report/wizard/training_report_account_analytic_balance_year_view.xml'
--- training_report/wizard/training_report_account_analytic_balance_year_view.xml 1970-01-01 00:00:00 +0000
+++ training_report/wizard/training_report_account_analytic_balance_year_view.xml 2011-03-17 10:37:29 +0000
@@ -0,0 +1,35 @@
+<openerp>
+ <data>
+
+ <record model="ir.ui.view" id="training_report_account_analytic_balance_year_form">
+ <field name="name">training.report.account.analytic.balance.year.form</field>
+ <field name="model">training.report.account.analytic.balance.year</field>
+ <field name="type">form</field>
+ <field name="arch" type="xml">
+ <form string="Analytic Balance Year">
+ <field name="date1"/>
+ <field name="date2"/>
+ <separator colspan="4" />
+ <group colspan="4" col="2">
+ <button string="Cancel" special="cancel" type="object" icon="gtk-cancel"/>
+ <button name="action_report" string="Print" type="object" icon="gtk-print"/>
+ </group>
+ </form>
+ </field>
+ </record>
+
+ <record model="ir.actions.act_window" id="training_report_account_analytic_balance_year_form_act">
+ <field name="name">Analytic Balance Year</field>
+ <field name="res_model">training.report.account.analytic.balance.year</field>
+ <field name="view_type">form</field>
+ <field name="view_mode">form</field>
+ <field name="target">new</field>
+ </record>
+
+ <act_window id="action_act_training_report_account_analytic_balance_year"
+ key2="client_action_multi" name="Analytic Balance Year"
+ res_model="training.report.account.analytic.balance.year" src_model="account.analytic.account"
+ view_mode="form" target="new" view_type="form"/>
+
+ </data>
+</openerp>
=== renamed file 'training_report/wizard/wizard_course_profitability.py' => 'training_report/wizard/training_report_course_profitability.py'
--- training_report/wizard/wizard_course_profitability.py 2009-11-25 16:36:08 +0000
+++ training_report/wizard/training_report_course_profitability.py 2011-03-17 10:37:29 +0000
@@ -20,42 +20,39 @@
#
##############################################################################
+
+from osv import osv
+from osv import fields
import time
-import wizard
-import datetime
-
-dates_form = '''<?xml version="1.0"?>
-<form string="Select period">
- <field name="date1"/>
- <field name="date2"/>
- <field name="analytic_account"/>
- <field name="analytic_fix_cost"/>
-</form>'''
-
-dates_fields = {
- 'date1': {'string':'Start of period', 'type':'date', 'required':True, 'default': lambda *a: time.strftime('%Y-01-01')},
- 'date2': {'string':'End of period', 'type':'date', 'required':True, 'default': lambda *a: time.strftime('%Y-%m-%d')},
- 'analytic_account':{'string':'Analytic Account', 'type':'many2one','relation': 'account.analytic.account', 'required':True},
- 'analytic_fix_cost':{'string':'Analytic Fix Cost', 'type':'float'},
-}
-
-
-class wizard_report(wizard.interface):
-
-
- states = {
- 'init': {
- 'actions': [],
- 'result': {'type':'form', 'arch':dates_form, 'fields':dates_fields, 'state':[('end','Cancel'), ('report','Print')]}
- },
- 'report': {
- 'actions': [],
- 'result': {'type':'print', 'report':'training.course.profitability', 'state':'end'}
+
+class training_report_course_profitability(osv.osv_memory):
+ _name = 'training.report.course.profitability'
+ _columns = {
+ 'date1' : fields.date('Start of period', required=True),
+ 'date2' : fields.date('End of period', required=True),
+ 'analytic_account' : fields.many2one('account.analytic.account', 'Analytic Account', required=True),
+ 'analytic_fix_cost' : fields.float('Analytic Fix Cost'),
+ }
+
+
+ _defaults = {
+ 'date1': lambda *a: time.strftime('%Y-01-01'),
+ 'date2': lambda *a: time.strftime('%Y-%m-%d'),
+ }
+
+ def action_report(self, cr, uid, ids, context=None):
+ if context is None:
+ context = {}
+ datas = {'form':{}, 'ids': context.get('active_ids', [])}
+ res = self.read(cr, uid, ids, ['date1', 'date2', 'analytic_account', 'analytic_fix_cost'], context)
+ res = res and res[0] or {}
+ datas['form'].update(res)
+ return {
+ 'type': 'ir.actions.report.xml',
+ 'report_name': 'training.course.profitability',
+ 'datas': datas,
}
- }
-wizard_report('training.course.profitability.report')
-
-
+
+training_report_course_profitability()
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
-
=== added file 'training_report/wizard/training_report_course_profitability_view.xml'
--- training_report/wizard/training_report_course_profitability_view.xml 1970-01-01 00:00:00 +0000
+++ training_report/wizard/training_report_course_profitability_view.xml 2011-03-17 10:37:29 +0000
@@ -0,0 +1,37 @@
+<openerp>
+ <data>
+
+ <record model="ir.ui.view" id="view_training_report_course_profitability_form">
+ <field name="name">training.report.course.profitability.form</field>
+ <field name="model">training.report.course.profitability</field>
+ <field name="type">form</field>
+ <field name="arch" type="xml">
+ <form string="Course Profitablility">
+ <field name="date1"/>
+ <field name="date2"/>
+ <field name="analytic_account"/>
+ <field name="analytic_fix_cost"/>
+ <separator colspan="4" />
+ <group colspan="4" col="2">
+ <button string="Cancel" special="cancel" type="object" icon="gtk-cancel"/>
+ <button name="action_report" string="Print" type="object" icon="gtk-print"/>
+ </group>
+ </form>
+ </field>
+ </record>
+
+ <record model="ir.actions.act_window" id="training_report_course_profitability_form_act">
+ <field name="name">Course Profitablility</field>
+ <field name="res_model">training.report.course.profitability</field>
+ <field name="view_type">form</field>
+ <field name="view_mode">form</field>
+ <field name="target">new</field>
+ </record>
+
+ <act_window id="action_act_training_report_course_profitability"
+ key2="client_action_multi" name="Course Profitablility"
+ res_model="training.report.course.profitability" src_model="training.course"
+ view_mode="form" target="new" view_type="form"/>
+
+ </data>
+</openerp>
=== renamed file 'training_report/wizard/wizard_session_volume.py' => 'training_report/wizard/training_report_session_volume.py'
--- training_report/wizard/wizard_session_volume.py 2010-09-22 10:00:18 +0000
+++ training_report/wizard/training_report_session_volume.py 2011-03-17 10:37:29 +0000
@@ -20,433 +20,383 @@
#
##############################################################################
-import wizard
+from osv import osv
+from osv import fields
import time
-import datetime
-import pooler
import tools
from tools.translate import _
import mx.DateTime as dt
-_aged_trial_form = """<?xml version="1.0"?>
-<form string="Session Volume Report">
- <separator string="Period" colspan="4" />
- <field name="date_start"/>
- <field name="date_stop"/>
- <separator string="Year" colspan="4" />
- <field name="year" />
- <separator string="Report" colspan="4" />
- <field name="kind" />
-</form>"""
-
-def first_day_of_previous_month():
- return dt.strptime((dt.today() - dt.RelativeDate(months=1)).strftime('%Y-%m-01'), '%Y-%m-%d')
-
-def last_day_of_previous_month():
- return first_day_of_previous_month() + dt.RelativeDate(months=1, seconds=-1)
-
-_aged_trial_fields = {
- 'date_start': {'string':'Start of period', 'type':'date', 'required':True, 'default': lambda *a: first_day_of_previous_month().strftime('%Y-%m-%d')},
- 'date_stop': {'string':'Stop of period', 'type':'date', 'required':True, 'default': lambda *a: last_day_of_previous_month().strftime('%Y-%m-%d')},
- 'year': {'string':'Year', 'type':'integer', 'required':True, 'default': lambda *a: -1},
- 'kind' : {'string' : 'Kind',
- 'type' : 'selection',
- 'selection' : [
+class training_report_session_volume(osv.osv_memory):
+ _name = 'training.report.session.volume'
+ _columns = {
+ 'date_start' : fields.date('Start of period', required=True),
+ 'date_stop' : fields.date('End of period', required=True),
+ 'year' : fields.integer('Year', required=True),
+ 'kind' : fields.selection([
('product_lines', 'Statistics by Product Lines'),
('theoretical_product_lines', 'Theoretical Statistics by Product Lines'),
('sessions', 'Sessions volume by State'),
('count_subscriptions_offer', 'Subscription Volume by State'),
#('subscriptions_partner', 'Partner Amount of Subscriptions'),
- ],
- 'default' : lambda *a: 'product_lines'}
-}
-
-def previous_date(date, year):
- return dt.strptime(date, '%Y-%m-%d') + dt.RelativeDate(years=year)
-
-def previous_period(date_start, date_stop, year):
- return (previous_date(date_start, year), previous_date(date_stop, year))
-
-def compute_theoretical_product_lines(cr, uid, ids, context, date_start, date_stop, kind):
-# print(">>> --== Compute Theoretical Product Lines ==--")
- pool = pooler.get_pool(cr.dbname)
- session_pool = pool.get('training.session')
- subl_pool = pool.get('training.subscription.line')
- prodline_pool = pool.get('training.course_category')
- offer_pool = pool.get('training.offer')
- trcv_pool = pool.get('training.report.costs.view')
-
- cache_seance = {}
- cache_session = {}
- product_line = {} # dict containing cost + revenue per product lines
-
- query_base = "SELECT * FROM training_report_costs_view "
- query = "WHERE seance_date BETWEEN %s AND %s AND offer_kind = %s"
- query_args = (date_start, date_stop, kind)
-
- if kind == 'intra':
- cr.execute("SELECT DISTINCT(session_id) FROM training_report_intra_session_seance_view " + query, query_args)
- else:
- cr.execute("SELECT DISTINCT(session_id) FROM training_report_costs_view " + query, query_args)
- session_ids = [ x[0] for x in cr.fetchall() ]
- trcv_pool.docache_session_populate(cr, uid, cache_session, session_ids)
-
- if kind == 'intra':
- cr.execute("SELECT DISTINCT(seance_id) FROM training_report_intra_session_seance_view " + query, query_args)
- else:
- cr.execute("SELECT DISTINCT(seance_id) FROM training_report_costs_view " + query, query_args)
- seance_ids = [ x[0] for x in cr.fetchall() ]
- trcv_pool.docache_seance_populate(cr, uid, cache_seance, seance_ids)
-
- if kind != 'intra':
- cr.execute(query_base + query, query_args)
- for theor_cost in cr.dictfetchall():
- c_session_id = theor_cost['session_id']
- c_seance_id = theor_cost['seance_id']
-
- if c_session_id not in cache_seance[c_seance_id]['sessions_ratio']:
- # seance already cached, but we still need to update the session ratio
- session_total_duration = cache_session[theor_cost['session_id']]['duration']
- cache_seance[c_seance_id]['sessions_ratio'][c_session_id] = cache_seance[c_seance_id]['duration'] / session_total_duration
-
- # all things are cached now
- c_seance = cache_seance[theor_cost['seance_id']]
- c_prodline_id = theor_cost['product_line_id']
- if c_prodline_id not in product_line:
- plo = prodline_pool.browse(cr, uid, c_prodline_id)
- product_line[c_prodline_id] = {
- 'id': c_prodline_id,
- 'name': plo.name,
- 'costs': 0.0,
- 'revenues': 0.0,
- 'subscriptions': set(),
- }
- pl = product_line[c_prodline_id]
- pl['costs'] += c_seance['trainer_cost'] + c_seance['proc_cost']
- pl['revenues'] += c_seance['sessions_ratio'][theor_cost['session_id']] * trcv_pool.get_sale_price(cr, uid, theor_cost, context=context)
- pl['subscriptions'].add(theor_cost['id'])
- else: # kind == 'intra'
- cr.execute("SELECT * FROM training_report_intra_session_seance_view " + query, query_args)
- for theor_intra in cr.dictfetchall():
- c_session_id = theor_intra['session_id']
- c_seance_id = theor_intra['seance_id']
-
- if c_session_id not in cache_seance[c_seance_id]['sessions_ratio']:
- # seance already cached, but we still need to update the session ratio
- session_total_duration = cache_session[theor_intra['session_id']]['duration']
- cache_seance[c_seance_id]['sessions_ratio'][c_session_id] = cache_seance[c_seance_id]['duration'] / session_total_duration
-
- c_seance = cache_seance[theor_intra['seance_id']]
- c_session = cache_session[theor_intra['session_id']]
-
- c_session_ratio = cache_seance[c_seance_id]['sessions_ratio'][c_session_id]
-
- c_prodline_id = theor_intra['product_line_id']
- if c_prodline_id not in product_line:
- plo = prodline_pool.browse(cr, uid, c_prodline_id)
- product_line[c_prodline_id] = {
- 'id': c_prodline_id,
- 'name': plo.name,
- 'costs': 0.0,
- 'revenues': 0.0,
- 'subscriptions': set(),
- }
- pl = product_line[c_prodline_id]
- pl['costs'] += c_session_ratio * theor_intra['session_cost']
- pl['revenues'] += c_session_ratio * theor_intra['session_revenue']
- for x in xrange(1, theor_intra['number_of_participants'] + 1):
- pl['subscriptions'].add(x)
-
- res = []
- total = { 'revenues': 0.0, 'costs': 0.0 }
- for p, v in product_line.iteritems():
- res.append(v)
- v['subscriptions'] = len(v['subscriptions'])
- v['margin'] = (v['revenues'] / (v['costs'] or 1.0)) * 100
- v['balance'] = (v['revenues'] - v['costs'])
- total['revenues'] += v['revenues']
- total['costs'] += v['costs']
-
- total['balance'] = total['revenues'] - total['costs']
- total['margin'] = (total['revenues'] / (total['costs'] or 1.0)) * 100
-
- return {
- 'product_lines': res,
- 'total': total,
- 'date_start': date_start,
- 'date_stop': date_stop,
- 'kind': kind,
- }
-
-def compute_product_lines_exam(cr, uid, ids, context, date_start, date_stop):
- res = []
-
-
- pool = pooler.get_pool(cr.dbname)
-
- tsl_proxy = pool.get('training.subscription.line')
-
- tsl_ids = tsl_proxy.search(cr, uid,
- [
- ('state', 'not in', ('draft', 'cancelled')),
- ('date', '>=', "%s 00:00:00" % (date_start)),
- ('date', '<=', "%s 23:59:59" % (date_stop)),
- ('kind', '=', 'exam'),
- ],
- context=context)
-
- product_lines = {}
-
- for sl in tsl_proxy.browse(cr, uid, tsl_ids, context=context):
-
- if not (sl.course_id and sl.course_id.category_id):
- continue
-
- product_line_id = sl.course_id.category_id
-
- product_lines.setdefaults(product_line_id, [])
-
- if sl.invoice_line_id and sl.invoice_id:
- product_lines[product_line_id].append(sl)
-
-
-def compute_product_lines(cr, uid, ids, context, date_start, date_stop, kind):
- res = []
-
- pool = pooler.get_pool(cr.dbname)
- tsl_proxy = pool.get('training.subscription.line')
-
- tsl_ids = tsl_proxy.search(cr, uid,
- [
- ('state', 'not in', ('draft', 'cancelled')),
- ('date', '>=', "%s 00:00:00" % (date_start)),
- ('date', '<=', "%s 23:59:59" % (date_stop)),
- ('kind', '=', kind),
- ],
- context=context)
-
- product_lines = {}
-
- for sl in tsl_proxy.browse(cr, uid, tsl_ids, context=context):
-
- session_id = sl.session_id
- invoice_id = sl.invoice_id
-
- product_line_id = sl.session_id.offer_id.product_line_id
-
- product_lines.setdefault(product_line_id,
- {
- 'invoices' : set(),
- 'sessions' : {},
- 'subscription_count' : 0,
- 'exams' : {},
- }
- )
-
- product_lines[product_line_id]['subscription_count'] += 1
-
- if invoice_id and sl.invoice_line_id:
- product_lines[product_line_id]['invoices'].add(invoice_id)
-
- if sl.session_id not in product_lines[product_line_id]['sessions']:
-
- po_pool = pool.get('purchase.order')
- sl_sess_seance_ids = [ seance.id for seance in session_id.seance_ids ]
- sl_sess_po = po_pool.search(cr, uid, [('seance_id','in',sl_sess_seance_ids)], context=context)
- value = sum(po.invoice_id and po.invoice_id.amount_untaxed or po.amount_untaxed
- for po in po_pool.browse(cr, uid, sl_sess_po, context=context))
- #value = sum(po.procurement_id.purchase_id.amount_total
- # for seance in session_id.seance_ids
- # for po in seance.purchase_line_ids
- # if po.procurement_id and po.procurement_id.purchase_id)
-
- value += sum(request.purchase_order_id.amount_untaxed
- for request in session_id.request_ids
- if request.purchase_order_id and request.state in ('accepted', 'done'))
-
- product_lines[product_line_id]['sessions'][sl.session_id] = value
-
- if sl.kind == 'exam' and sl.course_id and sl.course_id.category_id:
- product_lines[product_line_id]['exams'].setdefault(sl.course_id.category_id, {'subscription_count' : 0,
- 'price' : 0.0,
- }
- )
- product_line = product_lines[product_line_id]['exams'][sl.course_id.category_id]
- product_line['subscription_count'] += 1
- product_line['price'] += sl.price
-
- for pl, data in product_lines.iteritems():
- subscription_count = data['subscription_count']
-
- pl_input = sum(invoice_id.amount_untaxed for invoice_id in data['invoices'])
- pl_output = sum( data['sessions'].values() or [0.0])
-
- pl_balance = pl_input - pl_output
-
- pl_margin = (pl_input / (pl_output or 1.0)) * 100
-
- pl_average_price = subscription_count > 0 and (pl_input / subscription_count) or 0
- pl_yield = subscription_count > 0 and (pl_balance / subscription_count) or 0
-
- if ((-0.00001 < pl_input < 0.00001) or (-0.00001 < pl_output < 0.00001)):
- pl_margin = _('N/A')
+ ], 'Kind', required=True)
+ }
+
+ _defaults = {
+ 'date_start': lambda self, cr, uid, context: self.first_day_of_previous_month(cr, uid, context).strftime('%Y-%m-%d'),
+ 'date_stop': lambda self, cr, uid, context: self.last_day_of_previous_month(cr, uid, context).strftime('%Y-%m-%d'),
+ 'year': lambda *a: -1,
+ 'kind': lambda *a: 'product_lines',
+ }
+
+
+ def first_day_of_previous_month(self, cr, uid, context=None):
+ return dt.strptime((dt.today() - dt.RelativeDate(months=1)).strftime('%Y-%m-01'), '%Y-%m-%d')
+
+ def last_day_of_previous_month(self, cr, uid, context=None):
+ return self.first_day_of_previous_month(cr, uid, context) + dt.RelativeDate(months=1, seconds=-1)
+
+ def previous_date(self, cr, uid, date, year, context=None):
+ return dt.strptime(date, '%Y-%m-%d') + dt.RelativeDate(years=year)
+
+ def previous_period(self, cr, uid, date_start, date_stop, year, context=None):
+ return (self.previous_date(cr, uid, date_start, year,context), self.previous_date(cr, uid, date_stop, year, context))
+
+ def compute_theoretical_product_lines(self, cr, uid, ids, date_start, date_stop, kind, context=None):
+ if context is None:
+ context = {}
+ session_pool = self.pool.get('training.session')
+ subl_pool = self.pool.get('training.subscription.line')
+ prodline_pool = self.pool.get('training.course_category')
+ offer_pool = self.pool.get('training.offer')
+ trcv_pool = self.pool.get('training.report.costs.view')
+
+ cache_seance = {}
+ cache_session = {}
+ product_line = {} # dict containing cost + revenue per product lines
+
+ query_base = "SELECT * FROM training_report_costs_view "
+ query = "WHERE seance_date BETWEEN %s AND %s AND offer_kind = %s"
+ query_args = (date_start, date_stop, kind)
+
+ if kind == 'intra':
+ cr.execute("SELECT DISTINCT(session_id) FROM training_report_intra_session_seance_view " + query, query_args)
+ else:
+ cr.execute("SELECT DISTINCT(session_id) FROM training_report_costs_view " + query, query_args)
+ session_ids = [ x[0] for x in cr.fetchall() ]
+ trcv_pool.docache_session_populate(cr, uid, cache_session, session_ids)
+
+ if kind == 'intra':
+ cr.execute("SELECT DISTINCT(seance_id) FROM training_report_intra_session_seance_view " + query, query_args)
+ else:
+ cr.execute("SELECT DISTINCT(seance_id) FROM training_report_costs_view " + query, query_args)
+ seance_ids = [ x[0] for x in cr.fetchall() ]
+ trcv_pool.docache_seance_populate(cr, uid, cache_seance, seance_ids)
+
+ if kind != 'intra':
+ cr.execute(query_base + query, query_args)
+ for theor_cost in cr.dictfetchall():
+ c_session_id = theor_cost['session_id']
+ c_seance_id = theor_cost['seance_id']
+
+ if c_session_id not in cache_seance[c_seance_id]['sessions_ratio']:
+ # seance already cached, but we still need to update the session ratio
+ session_total_duration = cache_session[theor_cost['session_id']]['duration']
+ cache_seance[c_seance_id]['sessions_ratio'][c_session_id] = cache_seance[c_seance_id]['duration'] / session_total_duration
+
+ # all things are cached now
+ c_seance = cache_seance[theor_cost['seance_id']]
+ c_prodline_id = theor_cost['product_line_id']
+ if c_prodline_id not in product_line:
+ plo = prodline_pool.browse(cr, uid, c_prodline_id)
+ product_line[c_prodline_id] = {
+ 'id': c_prodline_id,
+ 'name': plo.name,
+ 'costs': 0.0,
+ 'revenues': 0.0,
+ 'subscriptions': set(),
+ }
+ pl = product_line[c_prodline_id]
+ pl['costs'] += c_seance['trainer_cost'] + c_seance['proc_cost']
+ pl['revenues'] += c_seance['sessions_ratio'][theor_cost['session_id']] * trcv_pool.get_sale_price(cr, uid, theor_cost, context=context)
+ pl['subscriptions'].add(theor_cost['id'])
+ else: # kind == 'intra'
+ cr.execute("SELECT * FROM training_report_intra_session_seance_view " + query, query_args)
+ for theor_intra in cr.dictfetchall():
+ c_session_id = theor_intra['session_id']
+ c_seance_id = theor_intra['seance_id']
+
+ if c_session_id not in cache_seance[c_seance_id]['sessions_ratio']:
+ # seance already cached, but we still need to update the session ratio
+ session_total_duration = cache_session[theor_intra['session_id']]['duration']
+ cache_seance[c_seance_id]['sessions_ratio'][c_session_id] = cache_seance[c_seance_id]['duration'] / session_total_duration
+
+ c_seance = cache_seance[theor_intra['seance_id']]
+ c_session = cache_session[theor_intra['session_id']]
+
+ c_session_ratio = cache_seance[c_seance_id]['sessions_ratio'][c_session_id]
+
+ c_prodline_id = theor_intra['product_line_id']
+ if c_prodline_id not in product_line:
+ plo = prodline_pool.browse(cr, uid, c_prodline_id)
+ product_line[c_prodline_id] = {
+ 'id': c_prodline_id,
+ 'name': plo.name,
+ 'costs': 0.0,
+ 'revenues': 0.0,
+ 'subscriptions': set(),
+ }
+ pl = product_line[c_prodline_id]
+ pl['costs'] += c_session_ratio * theor_intra['session_cost']
+ pl['revenues'] += c_session_ratio * theor_intra['session_revenue']
+ for x in xrange(1, theor_intra['number_of_participants'] + 1):
+ pl['subscriptions'].add(x)
+
+ res = []
+ total = { 'revenues': 0.0, 'costs': 0.0 }
+ for p, v in product_line.iteritems():
+ res.append(v)
+ v['subscriptions'] = len(v['subscriptions'])
+ v['margin'] = (v['revenues'] / (v['costs'] or 1.0)) * 100
+ v['balance'] = (v['revenues'] - v['costs'])
+ total['revenues'] += v['revenues']
+ total['costs'] += v['costs']
+
+ total['balance'] = total['revenues'] - total['costs']
+ total['margin'] = (total['revenues'] / (total['costs'] or 1.0)) * 100
+
+ return {
+ 'product_lines': res,
+ 'total': total,
+ 'date_start': date_start,
+ 'date_stop': date_stop,
+ 'kind': kind,
+ }
+
+# def compute_product_lines_exam(self, cr, uid, ids, date_start, date_stop, context=None):
+# if context is None:
+# context = {}
+# tsl_proxy = self.pool.get('training.subscription.line')
+# tsl_ids = tsl_proxy.search(cr, uid,
+# [
+# ('state', 'not in', ('draft', 'cancelled')),
+# ('date', '>=', "%s 00:00:00" % (date_start)),
+# ('date', '<=', "%s 23:59:59" % (date_stop)),
+# ('kind', '=', 'exam'),
+# ],
+# context=context)
+#
+# product_lines = {}
+# for sl in tsl_proxy.browse(cr, uid, tsl_ids, context=context):
+# if not (sl.course_id and sl.course_id.category_id):
+# continue
+# product_line_id = sl.course_id.category_id
+# product_lines.setdefaults(product_line_id, [])
+# if sl.invoice_line_id and sl.invoice_id:
+# product_lines[product_line_id].append(sl)
+# return True
+
+ def compute_product_lines(self, cr, uid, ids, date_start, date_stop, kind, context=None):
+ if context is None:
+ context = {}
+ res = []
+ tsl_proxy = self.pool.get('training.subscription.line')
+ tsl_ids = tsl_proxy.search(cr, uid,
+ [
+ ('state', 'not in', ('draft', 'cancelled')),
+ ('date', '>=', "%s 00:00:00" % (date_start)),
+ ('date', '<=', "%s 23:59:59" % (date_stop)),
+ ('kind', '=', kind),
+ ],
+ context=context)
+ product_lines = {}
+ for sl in tsl_proxy.browse(cr, uid, tsl_ids, context=context):
+ session_id = sl.session_id
+ invoice_id = sl.invoice_id
+ product_line_id = sl.session_id.offer_id.product_line_id
+ product_lines.setdefault(product_line_id,
+ {
+ 'invoices' : set(),
+ 'sessions' : {},
+ 'subscription_count' : 0,
+ 'exams' : {},
+ })
+ product_lines[product_line_id]['subscription_count'] += 1
+
+ if invoice_id and sl.invoice_line_id:
+ product_lines[product_line_id]['invoices'].add(invoice_id)
+
+ if sl.session_id not in product_lines[product_line_id]['sessions']:
+
+ po_pool = self.pool.get('purchase.order')
+ sl_sess_seance_ids = [ seance.id for seance in session_id.seance_ids ]
+ sl_sess_po = po_pool.search(cr, uid, [('seance_id','in',sl_sess_seance_ids)], context=context)
+ value = sum(po.invoice_id and po.invoice_id.amount_untaxed or po.amount_untaxed
+ for po in po_pool.browse(cr, uid, sl_sess_po, context=context))
+ #value = sum(po.procurement_id.purchase_id.amount_total
+ # for seance in session_id.seance_ids
+ # for po in seance.purchase_line_ids
+ # if po.procurement_id and po.procurement_id.purchase_id)
+
+ value += sum(request.purchase_order_id.amount_untaxed
+ for request in session_id.request_ids
+ if request.purchase_order_id and request.state in ('accepted', 'done'))
+
+ product_lines[product_line_id]['sessions'][sl.session_id] = value
+
+ if sl.kind == 'exam' and sl.course_id and sl.course_id.category_id:
+ product_lines[product_line_id]['exams'].setdefault(sl.course_id.category_id, {'subscription_count' : 0,
+ 'price' : 0.0,
+ })
+ product_line = product_lines[product_line_id]['exams'][sl.course_id.category_id]
+ product_line['subscription_count'] += 1
+ product_line['price'] += sl.price
+
+ for pl, data in product_lines.iteritems():
+ subscription_count = data['subscription_count']
+ pl_input = sum(invoice_id.amount_untaxed for invoice_id in data['invoices'])
+ pl_output = sum( data['sessions'].values() or [0.0])
+ pl_balance = pl_input - pl_output
+ pl_margin = (pl_input / (pl_output or 1.0)) * 100
+ pl_average_price = subscription_count > 0 and (pl_input / subscription_count) or 0
+ pl_yield = subscription_count > 0 and (pl_balance / subscription_count) or 0
+
+ if ((-0.00001 < pl_input < 0.00001) or (-0.00001 < pl_output < 0.00001)):
+ pl_margin = _('N/A')
+
+ values = {
+ 'id' : pl.id,
+ 'name' : pl.name,
+ 'input' : pl_input,
+ 'output' : pl_output,
+ 'balance' : pl_balance,
+ 'subscription_count' : subscription_count,
+ 'margin' : pl_margin,
+ 'average_price' : pl_average_price,
+ 'yield' : pl_yield,
+ 'exams' : [(category.name, vals['subscription_count'], vals['price']) for category, vals in data['exams'].iteritems()]
+ }
+
+ res.append(values)
values = {
- 'id' : pl.id,
- 'name' : pl.name,
- 'input' : pl_input,
- 'output' : pl_output,
- 'balance' : pl_balance,
- 'subscription_count' : subscription_count,
- 'margin' : pl_margin,
- 'average_price' : pl_average_price,
- 'yield' : pl_yield,
- 'exams' : [(category.name, vals['subscription_count'], vals['price']) for category, vals in data['exams'].iteritems()]
- }
-
- res.append(values)
-
- values = {
- 'subscription' : sum(line['subscription_count'] for line in res),
- 'input' : sum(line['input'] for line in res),
- 'output' : sum(line['output'] for line in res),
- }
-
- values['balance'] = values['input'] - values['output']
- if (-0.00001 < values['input'] < 0.00001) or (-0.00001 < values['output'] < 0.00001):
- values['margin'] = _('N/A')
- else:
- values['margin'] = (values['input'] / (values['output'] or 1.0)) * 100.0
- values['average_price'] = values['subscription'] > 0 and (values['input'] / values['subscription']) or 0
- values['yield'] = values['subscription'] > 0 and (values['balance'] / values['subscription']) or 0
-
- return {
- 'product_lines' : res,
- 'total' : values,
- 'date_start' : date_start,
- 'date_stop' : date_stop,
- 'kind' : kind,
- }
-
-def compute_sessions(cr, uid, ids, context, date_start, date_stop):
- return {
- 'lines' : [],
- 'date_start' : date_start,
- 'date_stop' : date_stop,
- }
-
-def compute_subscrtiption_partner(cr, uid, ids, context, date_start, date_stop):
- cr.execute("""
- SELECT res.name, coalesce(sum(tsl.price), 0.0) as total_price
- FROM training_subscription_line tsl,
- res_partner res,
- training_session s
- WHERE res.id = tsl.partner_id
- AND tsl.session_id = s.id
- AND tsl.state IN ('confirmed', 'done')
- AND s.date BETWEEN %s AND %s
- GROUP BY tsl.partner_id,res.name
- ORDER BY total_price DESC
- """, (date_start, date_stop))
-
- return {
- 'lines' : [{'name' : name, 'price' : price} for name, price in cr.fetchall()],
- 'date_start' : date_start,
- 'date_stop' : date_stop,
- }
-
-def compute_count_subscriptions_offer(cr, uid, ids, context, date_start, date_stop):
- return {
- 'lines' : [],
- 'date_start' : date_start,
- 'date_stop' : date_stop,
- }
-
-def _select(self, cr, uid, data, context=None):
- functions = {
- 'sessions' : compute_sessions,
- 'count_subscriptions_offer' : compute_count_subscriptions_offer,
- 'subscriptions_partner' : compute_subscrtiption_partner,
- }
-
- date_start = data['form']['date_start']
- date_stop = data['form']['date_stop']
-
- old_date_start, old_date_stop = previous_period(date_start, date_stop, data['form']['year'])
-
- old_date_start = old_date_start.strftime('%Y-%m-%d')
- old_date_stop = old_date_stop.strftime('%Y-%m-%d')
-
- if data['form']['kind'] == 'product_lines':
- for kind in ('standard', 'exam', 'intra'):
- data['form']['selected_period_%s' % kind] = compute_product_lines(cr, uid, data, context, date_start, date_stop, kind)
- data['form']['old_period_%s' % kind] = compute_product_lines(cr, uid, data, context, old_date_start, old_date_stop, kind)
- elif data['form']['kind'] == 'theoretical_product_lines':
- for kind in ('standard', 'exam', 'intra'):
- data['form']['selected_period_%s' % kind] = compute_theoretical_product_lines(cr, uid, data, context, date_start, date_stop, kind)
- else:
- function = functions[data['form']['kind']]
- data['form']['selected_period'] = function(cr, uid, data, context, date_start, date_stop)
- data['form']['old_period'] = function(cr, uid, data, context, old_date_start, old_date_stop)
-
- print(">>> _select :: got dataz" % (data))
- return data['form']
-
-class wizard_report(wizard.interface):
- def _select_report(self, cr, uid, data, context=None):
- return "report_%s" % (data['form']['kind'],)
-
- states = {
- 'init': {
- 'result': {'type':'form',
- 'arch':_aged_trial_form,
- 'fields':_aged_trial_fields,
- 'state':[('end','Cancel'),('choice','Print')]},
- },
- 'choice' : {
- 'actions' : [],
- 'result' : { 'type' : 'choice', 'next_state' : _select_report },
- },
- 'report_product_lines': {
- 'actions': [_select],
- 'result': {'type' : 'print',
- 'report' : 'training.session.volume',
- 'state' : 'end'},
- },
- 'report_theoretical_product_lines': {
- 'actions': [_select],
- 'result': {
- 'type': 'print',
- 'report': 'training.session.volume.theoretical',
- 'state': 'end',
- },
- },
- 'report_sessions' : {
- 'actions' : [_select],
- 'result' : {
- 'type' : 'print',
- 'report' : 'training.session.report',
- 'state' : 'end',
- },
- },
- 'report_count_subscriptions_offer' : {
- 'actions' : [_select],
- 'result' : {
- 'type' : 'print',
- 'report' : 'training.count.subscriptions.offer',
- 'state' : 'end',
- },
- },
- 'report_subscriptions_partner' : {
- 'actions' : [_select],
- 'result' : {
- 'type' : 'print',
- 'report' : 'training.subscriptions.partner',
- 'state' : 'end',
- }}
- }
-
-wizard_report('training.session.volume.report')
+ 'subscription' : sum(line['subscription_count'] for line in res),
+ 'input' : sum(line['input'] for line in res),
+ 'output' : sum(line['output'] for line in res),
+ }
+
+ values['balance'] = values['input'] - values['output']
+ if (-0.00001 < values['input'] < 0.00001) or (-0.00001 < values['output'] < 0.00001):
+ values['margin'] = _('N/A')
+ else:
+ values['margin'] = (values['input'] / (values['output'] or 1.0)) * 100.0
+ values['average_price'] = values['subscription'] > 0 and (values['input'] / values['subscription']) or 0
+ values['yield'] = values['subscription'] > 0 and (values['balance'] / values['subscription']) or 0
+
+ return {
+ 'product_lines' : res,
+ 'total' : values,
+ 'date_start' : date_start,
+ 'date_stop' : date_stop,
+ 'kind' : kind,
+ }
+
+ def compute_sessions(self, cr, uid, ids, date_start, date_stop, context):
+ return {
+ 'lines' : [],
+ 'date_start' : date_start,
+ 'date_stop' : date_stop,
+ }
+
+ def compute_subscrtiption_partner(self, cr, uid, ids, date_start, date_stop, context):
+ cr.execute("""
+ SELECT res.name, coalesce(sum(tsl.price), 0.0) as total_price
+ FROM training_subscription_line tsl,
+ res_partner res,
+ training_session s
+ WHERE res.id = tsl.partner_id
+ AND tsl.session_id = s.id
+ AND tsl.state IN ('confirmed', 'done')
+ AND s.date BETWEEN %s AND %s
+ GROUP BY tsl.partner_id,res.name
+ ORDER BY total_price DESC
+ """, (date_start, date_stop))
+
+ return {
+ 'lines' : [{'name' : name, 'price' : price} for name, price in cr.fetchall()],
+ 'date_start' : date_start,
+ 'date_stop' : date_stop,
+ }
+
+ def compute_count_subscriptions_offer(self, cr, uid, ids, date_start, date_stop, context):
+ return {
+ 'lines' : [],
+ 'date_start' : date_start,
+ 'date_stop' : date_stop,
+ }
+
+ def _select(self, cr, uid, data, context=None):
+ if context is None:
+ context = {}
+ functions = {
+ 'sessions' : self.compute_sessions,
+ 'count_subscriptions_offer' : self.compute_count_subscriptions_offer,
+ 'subscriptions_partner' : self.compute_subscrtiption_partner,
+ }
+
+ date_start = data['form']['date_start']
+ date_stop = data['form']['date_stop']
+
+ old_date_start, old_date_stop = self.previous_period(cr, uid, date_start, date_stop, data['form']['year'], context)
+
+ old_date_start = old_date_start.strftime('%Y-%m-%d')
+ old_date_stop = old_date_stop.strftime('%Y-%m-%d')
+
+ if data['form']['kind'] == 'product_lines':
+ for kind in ('standard', 'exam', 'intra'):
+ data['form']['selected_period_%s' % kind] = self.compute_product_lines(cr, uid, data, date_start, date_stop, kind, context)
+ data['form']['old_period_%s' % kind] = self.compute_product_lines(cr, uid, data, old_date_start, old_date_stop, kind, context)
+ elif data['form']['kind'] == 'theoretical_product_lines':
+ for kind in ('standard', 'exam', 'intra'):
+ data['form']['selected_period_%s' % kind] = self.compute_theoretical_product_lines(cr, uid, data, date_start, date_stop, kind, context)
+ else:
+ function = functions[data['form']['kind']]
+ data['form']['selected_period'] = function(cr, uid, data, date_start, date_stop, context)
+ data['form']['old_period'] = function(cr, uid, data, old_date_start, old_date_stop, context)
+
+ return data['form']
+
+ def action_print(self, cr, uid, ids, context=None):
+ if context is None:
+ context = {}
+ datas = {'form':{}, 'ids': context.get('active_ids', [])}
+ res = self.read(cr, uid, ids, ['date_start', 'date_stop', 'year', 'kind'], context)
+ res = res and res[0] or {}
+ datas['form'].update(res)
+
+ report_name = False
+ if res.get('kind',False) == 'product_lines':
+ report_name = 'training.session.volume'
+ elif res.get('kind',False) == 'theoretical_product_lines':
+ report_name = 'training.session.volume.theoretical'
+ elif res.get('kind',False) == 'sessions':
+ report_name = 'training.session.report'
+ elif res.get('kind',False) == 'count_subscriptions_offer':
+ report_name = 'training.count.subscriptions.offer'
+ elif res.get('kind',False) == 'subscriptions_partner':
+ report_name = 'training.subscriptions.partner'
+ if not report_name:
+ return {}
+
+ new_datas = self._select(cr, uid, datas, context)
+ datas['form'].update(new_datas)
+ return {
+ 'type': 'ir.actions.report.xml',
+ 'report_name': report_name,
+ 'datas': datas,
+ }
+
+training_report_session_volume()
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
=== added file 'training_report/wizard/training_report_session_volume_view.xml'
--- training_report/wizard/training_report_session_volume_view.xml 1970-01-01 00:00:00 +0000
+++ training_report/wizard/training_report_session_volume_view.xml 2011-03-17 10:37:29 +0000
@@ -0,0 +1,37 @@
+<openerp>
+ <data>
+
+ <record model="ir.ui.view" id="view_training_report_session_volume_form">
+ <field name="name">training.report.session.volume.form</field>
+ <field name="model">training.report.session.volume</field>
+ <field name="type">form</field>
+ <field name="arch" type="xml">
+ <form string="Session Volume Report">
+ <separator string="Period" colspan="4" />
+ <field name="date_start"/>
+ <field name="date_stop"/>
+ <separator string="Year" colspan="4" />
+ <field name="year" />
+ <separator string="Report" colspan="4" />
+ <field name="kind" />
+ <separator colspan="4" />
+ <group colspan="4" col="2">
+ <button string="Cancel" special="cancel" type="object" icon="gtk-cancel"/>
+ <button name="action_print" string="Print" type="object" icon="gtk-print"/>
+ </group>
+ </form>
+ </field>
+ </record>
+
+ <record model="ir.actions.act_window" id="action_training_report_session_volume_form_act">
+ <field name="name">Report Volume</field>
+ <field name="res_model">training.report.session.volume</field>
+ <field name="view_type">form</field>
+ <field name="view_mode">form</field>
+ <field name="target">new</field>
+ </record>
+
+ <menuitem id="training_report_volume_mi" parent="menu_training_report" action="action_training_report_session_volume_form_act"/>
+
+ </data>
+</openerp>
Follow ups