Browse Source

add company_id in period. in queries add the usable field name. add tooltip on the result (to display val_c). add from to. right align for column header and values. update preview form to have better display. define security

pull/90/head
laetitia.gangloff@acsone.eu 11 years ago
committed by Stéphane Bidoul
parent
commit
ab5e88a402
  1. 1
      mis_builder/__openerp__.py
  2. 98
      mis_builder/models/mis_builder.py
  3. 10
      mis_builder/security/ir.model.access.csv
  4. 3
      mis_builder/static/src/css/custom.css
  5. 9
      mis_builder/static/src/xml/mis_widget.xml
  6. 1
      mis_builder/tests/mis.report.csv
  7. 5
      mis_builder/tests/mis.report.instance.csv
  8. 13
      mis_builder/tests/mis.report.instance.period.csv
  9. 1
      mis_builder/tests/mis.report.kpi.csv
  10. 1
      mis_builder/tests/mis.report.query.csv
  11. 11
      mis_builder/tests/mis_builder_test.py
  12. 23
      mis_builder/views/mis_builder.xml

1
mis_builder/__openerp__.py

@ -33,6 +33,7 @@
'data': [
'wizard/mis_builder_dashboard.xml',
'views/mis_builder.xml',
'security/ir.model.access.csv',
],
'test': [
],

98
mis_builder/models/mis_builder.py

@ -48,7 +48,7 @@ def _get_selection_label(selection, value):
return ''
def utc_midnight(d, add_day=0):
def _utc_midnight(d, add_day=0):
d = datetime.strptime(d, tools.DEFAULT_SERVER_DATE_FORMAT)
if add_day:
d = d + timedelta(days=add_day)
@ -57,6 +57,10 @@ def utc_midnight(d, add_day=0):
return datetime.strftime(d_utc_midnight, tools.DEFAULT_SERVER_DATETIME_FORMAT)
def _clean(varStr):
return re.sub('\W|^(?=\d)', '_', varStr)
class mis_report_kpi(orm.Model):
""" A KPI is an element of a MIS report.
@ -106,6 +110,7 @@ class mis_report_kpi(orm.Model):
'divider': '1',
'dp': 0,
'compare_method': 'pct',
'sequence': 1,
}
_order = 'sequence'
@ -127,12 +132,11 @@ class mis_report_kpi(orm.Model):
res['warning'] = {'title': 'Invalid name', 'message': 'The name must be a valid python identifier'}
return res
def onchange_description(self, cr, uid, ids, description, context=None):
def onchange_description(self, cr, uid, ids, description, name, context=None):
# construct name from description
clean = lambda varStr: re.sub('\W|^(?=\d)', '_', varStr)
res = {}
if description:
res = {'value': {'name': clean(description)}}
if description and not name:
res = {'value': {'name': _clean(description)}}
return res
def onchange_type(self, cr, uid, ids, kpi_type, context=None):
@ -152,7 +156,7 @@ class mis_report_kpi(orm.Model):
kpi.divider, kpi.dp, kpi.suffix)
elif kpi.type == 'pct':
return self._render_num(value,
100, kpi.dp, '%')
0.01, kpi.dp, '%')
else:
return unicode(value)
@ -170,7 +174,7 @@ class mis_report_kpi(orm.Model):
kpi.divider, kpi.dp, kpi.suffix,
sign='+')
elif kpi.compare_method == 'pct' and base_value != 0:
return self._render_num(value / base_value - base_value,
return self._render_num(value / base_value - 1,
0.01, kpi.dp, '%',
sign='+')
return ''
@ -192,6 +196,15 @@ class mis_report_query(orm.Model):
_name = 'mis.report.query'
def _get_field_names(self, cr, uid, ids, name, args, context=None):
res = {}
for query in self.browse(cr, uid, ids, context=context):
field_name = []
for field in query.field_ids:
field_name.append(field.name)
res[query.id] = ', '.join(field_name)
return res
_columns = {
'name': fields.char(size=32, required=True,
string='Name'),
@ -199,6 +212,9 @@ class mis_report_query(orm.Model):
string='Model'),
'field_ids': fields.many2many('ir.model.fields', required=True,
string='Fields to fetch'),
'field_name': fields.function(_get_field_names, type='char', string='Fetched fields name',
store={'mis.report.query':
(lambda self, cr, uid, ids, c={}: ids, ['field_ids'], 20), }),
'date_field': fields.many2one('ir.model.fields', required=True,
string='Date field',
domain=[('ttype', 'in', ('date', 'datetime'))]),
@ -259,11 +275,6 @@ class mis_report_instance_period(orm.Model):
if isinstance(ids, (int, long)):
ids = [ids]
res = {}
company_id = context.get('force_company')
if not company_id:
user = self.pool.get('res.users').read(cr, uid, uid, ['company_id'], context=context)
if user['company_id']:
company_id = user['company_id'][0]
for c in self.browse(cr, uid, ids, context=context):
d = parser.parse(c.report_instance_id.pivot_date)
if c.type == 'd':
@ -280,17 +291,16 @@ class mis_report_instance_period(orm.Model):
date_to = date_to.strftime(tools.DEFAULT_SERVER_DATE_FORMAT)
period_ids = None
elif c.type == 'fp':
# TODO: date!
period_obj = self.pool['account.period']
all_period_ids = period_obj.search(cr, uid,
[('special', '=', False), ('company_id', '=', company_id)],
[('special', '=', False), ('company_id', '=', c.company_id.id)],
order='date_start',
context=context)
current_period_ids = period_obj.search(cr, uid,
[('special', '=', False),
('date_start', '<=', d),
('date_stop', '>=', d),
('company_id', '=', company_id)],
('company_id', '=', c.company_id.id)],
context=context)
if not current_period_ids:
raise orm.except_orm(_("Error!"),
@ -350,12 +360,18 @@ class mis_report_instance_period(orm.Model):
'sequence': fields.integer(string='Sequence'),
'report_instance_id': fields.many2one('mis.report.instance',
string='Report Instance'),
'comparison_column_ids': fields.many2many('mis.report.instance.period', 'mis_report_instance_period_rel', 'period_id', 'compare_period_id', string='Compare with'),
'comparison_column_ids': fields.many2many('mis.report.instance.period', 'mis_report_instance_period_rel',
'period_id', 'compare_period_id', string='Compare with'),
'company_id': fields.many2one('res.company', 'Company', required=True)
}
_defaults = {
'offset': -1,
'duration': 1,
'sequence': 1,
'company_id': lambda s, cr, uid, c: s.pool.get('res.company')._company_default_get(cr, uid,
'mis.report.instance.period',
context=c)
}
_order = 'sequence'
@ -383,18 +399,11 @@ class mis_report_instance_period(orm.Model):
'date_to': c.date_to})
# TODO: initial balance?
company_id = context.get('force_company')
if not company_id:
user = self.pool.get('res.users').read(cr, uid, uid, ['company_id'], context=context)
if user['company_id']:
company_id = user['company_id'][0]
account_ids = account_obj.search(cr, uid, [('company_id', '=', company_id)], context=context)
account_ids = account_obj.search(cr, uid, [('company_id', '=', c.company_id.id)], context=context)
account_datas = account_obj.read(cr, uid, account_ids, ['code', 'balance'], context=search_ctx)
balances = {}
clean = lambda varStr: re.sub('\W|^(?=\d)', '_', varStr)
for account_data in account_datas:
# TODO: company_id in key
key = 'bal' + clean(account_data['code'])
key = 'bal' + _clean(account_data['code'])
assert key not in balances
balances[key] = account_data['balance']
@ -404,11 +413,6 @@ class mis_report_instance_period(orm.Model):
res = {}
report = c.report_instance_id.report_id
company_id = context.get('force_company')
if not company_id:
user = self.pool.get('res.users').read(cr, uid, uid, ['company_id'], context=context)
if user['company_id']:
company_id = user['company_id'][0]
for query in report.query_ids:
obj = self.pool[query.model_id.model]
domain = query.domain and safe_eval(query.domain) or []
@ -416,11 +420,12 @@ class mis_report_instance_period(orm.Model):
domain.extend([(query.date_field.name, '>=', c.date_from),
(query.date_field.name, '<=', c.date_to)])
else:
datetime_from = utc_midnight(c.date_from)
datetime_to = utc_midnight(c.date_to, add_day=1)
datetime_from = _utc_midnight(c.date_from)
datetime_to = _utc_midnight(c.date_to, add_day=1)
domain.extend([(query.date_field.name, '>=', datetime_from),
(query.date_field.name, '<', datetime_to)])
domain.extend([('company_id', '=', company_id)])
if obj._columns.get('company_id', False):
domain.extend([('company_id', '=', c.company_id.id)])
field_names = [field.name for field in query.field_ids]
obj_ids = obj.search(cr, uid, domain, context=context)
obj_datas = obj.read(cr, uid, obj_ids, field_names, context=context)
@ -516,8 +521,17 @@ class mis_report_instance(orm.Model):
'target_move': 'posted',
}
def _format_date(self, cr, uid, date, context=None):
# format date following user language
lang = self.pool['res.users'].read(cr, uid, uid, ['lang'], context=context)['lang']
language_id = self.pool['res.lang'].search(cr, uid, [('code', '=', lang)], context=context)[0]
tformat = self.pool['res.lang'].read(cr, uid, language_id, ['date_format'])['date_format']
return datetime.strftime(datetime.strptime(date, tools.DEFAULT_SERVER_DATE_FORMAT), tformat)
def compute(self, cr, uid, _ids, context=None):
assert isinstance(_ids, (int, long))
if context is None:
context = {}
r = self.browse(cr, uid, _ids, context=context)
context['state'] = r.target_move
@ -533,8 +547,16 @@ class mis_report_instance(orm.Model):
report_instance_period_obj = self.pool.get('mis.report.instance.period')
kpi_obj = self.pool.get('mis.report.kpi')
for period in r.period_ids:
current_col = dict(name=period.name, values=report_instance_period_obj._compute(cr, uid, period, context=context))
current_col = dict(name=period.name,
values=report_instance_period_obj._compute(cr, uid, period, context=context),
date=period.duration > 1 and
_('from %s to %s' % (period.period_from and period.period_from.name
or self._format_date(cr, uid, period.date_from, context=context),
period.period_to and period.period_to.name
or self._format_date(cr, uid, period.date_to, context=context)))
or period.period_from and period.period_from.name or period.date_from)
cols.append(current_col)
# add comparison column
for compare_col in period.comparison_column_ids:
column1 = current_col
for col in cols:
@ -543,8 +565,12 @@ class mis_report_instance(orm.Model):
continue
compare_values = {}
for kpi in r.report_id.kpi_ids:
compare_values[kpi.name] = {'val_r': kpi_obj._render_comparison(kpi, column1['values'][kpi.name]['val'], column2['values'][kpi.name]['val'])}
cols.append(dict(name='%s - %s' % (period.name, compare_col.name), values=compare_values))
compare_values[kpi.name] = {'val_r': kpi_obj._render_comparison(kpi,
column1['values'][kpi.name]['val'],
column2['values'][kpi.name]['val'])}
cols.append(dict(name='%s - %s' % (period.name, compare_col.name),
values=compare_values,
date=''))
res['cols'] = cols
return res

10
mis_builder/security/ir.model.access.csv

@ -1 +1,11 @@
"id","name","model_id:id","group_id:id","perm_read","perm_write","perm_create","perm_unlink"
manage_mis_report_kpi,manage_mis_report_kpi,model_mis_report_kpi,account.group_account_manager,1,1,1,1
access_mis_report_kpi,access_mis_report_kpi,model_mis_report_kpi,account.group_account_invoice,1,0,0,0
manage_mis_report_query,manage_mis_report_query,model_mis_report_query,account.group_account_manager,1,1,1,1
access_mis_report_query,access_mis_report_query,model_mis_report_query,account.group_account_invoice,1,0,0,0
manage_mis_report,manage_mis_report,model_mis_report,account.group_account_manager,1,1,1,1
access_mis_report,access_mis_report,model_mis_report,account.group_account_invoice,1,0,0,0
manage_mis_report_instance_period,manage_mis_report_instance_period,model_mis_report_instance_period,account.group_account_manager,1,1,1,1
access_mis_report_instance_period,access_mis_report_instance_period,model_mis_report_instance_period,account.group_account_invoice,1,0,0,0
manage_mis_report_instance,manage_mis_report_instance,model_mis_report_instance,account.group_account_manager,1,1,1,1
access_mis_report_instance,access_mis_report_instance,model_mis_report_instance,account.group_account_invoice,1,0,0,0

3
mis_builder/static/src/css/custom.css

@ -0,0 +1,3 @@
.openerp .rallign {
text-align: right;
}

9
mis_builder/static/src/xml/mis_widget.xml

@ -5,10 +5,13 @@
<thead>
<tr class="oe_list_header_columns">
<th class="oe_list_header_char"></th>
<th t-foreach="widget.mis_report_data.cols" t-as="col" class="oe_list_header_char">
<th t-foreach="widget.mis_report_data.cols" t-as="col" class="oe_list_header_char rallign">
<div>
<t t-esc="col.name"/>
</div>
<div>
<t t-esc="col.date"/>
</div>
</th>
</tr>
</thead>
@ -19,10 +22,12 @@
<t t-esc="row.description"/>
</div>
</th>
<td t-foreach="widget.mis_report_data.cols" t-as="col">
<td t-foreach="widget.mis_report_data.cols" t-as="col" class="rallign">
<t t-foreach="col.values" t-as="value">
<t t-if="value == row.name">
<label t-att="{'title': value_value.val_c}" class=" oe_form_label_help oe_align_right">
<t t-esc="value_value.val_r"/>
</label>
</t>
</t>
</td>

1
mis_builder/tests/mis.report.csv

@ -1,2 +1,3 @@
"id","description","kpi_ids/id","name","query_ids/id"
"mis_report","","mis_report_kpi_1,mis_report_kpi_2,mis_report_kpi_3,mis_report_kpi_4,mis_report_kpi_5,mis_report_kpi_6","Test","mis_report_query"
"mis_report_test","","mis_report_kpi_test","Test report","mis_report_query_test"

5
mis_builder/tests/mis.report.instance.csv

@ -1,2 +1,3 @@
"id","date","description","name","period_ids/id","report_id/id"
"mis_report_instance","2014-07-18","","Test-report-instance","mis_report_instance_period_1,mis_report_instance_period_2,mis_report_instance_period_3,mis_report_instance_period_4,mis_report_instance_period_5","mis_report"
"id","description","name","period_ids/id","report_id/id"
"mis_report_instance","","Test-report-instance","mis_report_instance_period_1,mis_report_instance_period_2,mis_report_instance_period_3,mis_report_instance_period_4,mis_report_instance_period_5","mis_report"
"mis_report_instance_test","","Test-report-instance without company","mis_report_instance_period_test","mis_report_test"

13
mis_builder/tests/mis.report.instance.period.csv

@ -1,6 +1,7 @@
"id","duration","name","offset","type","sequence"
"mis_report_instance_period_1","1","today","","Day",""
"mis_report_instance_period_2","1","yesterday","-1","Day",""
"mis_report_instance_period_3","1","last week","-1","Week","2"
"mis_report_instance_period_4","2","last 2 period","-2","Fiscal Period","3"
"mis_report_instance_period_5","2","last 2 week","-2","Week","4"
"id","duration","name","offset","type","sequence","company_id/id"
"mis_report_instance_period_1","1","today","","Day","","base.main_company"
"mis_report_instance_period_2","1","yesterday","-1","Day","","base.main_company"
"mis_report_instance_period_3","1","last week","-1","Week","2","base.main_company"
"mis_report_instance_period_4","2","last 2 period","-2","Fiscal Period","3","base.main_company"
"mis_report_instance_period_5","2","last 2 week","-2","Week","4","base.main_company"
"mis_report_instance_period_test","1","today","","Day","","base.main_company"

1
mis_builder/tests/mis.report.kpi.csv

@ -5,3 +5,4 @@
"mis_report_kpi_4","Difference","margin","profit/ca","","margin","","4","Percentage","%"
"mis_report_kpi_5","None","couleur","'vert' if profit > 0 else 'rouge'","","couleur","","5","String",""
"mis_report_kpi_6","Percentage","total invoice","len(inv)","","total_invoice","","6","Numeric","€"
"mis_report_kpi_test","Percentage","total test","len(test)","","total_test","","1","Numeric",""

1
mis_builder/tests/mis.report.query.csv

@ -1,2 +1,3 @@
"id","date_field/id","domain","field_ids/id","model_id/id","name"
"mis_report_query","account.field_account_invoice_date_invoice","","account.field_account_invoice_amount_untaxed","account.model_account_invoice","inv"
"mis_report_query_test","account.field_account_analytic_balance_date1","","account.field_account_analytic_balance_empty_acc","account.model_account_analytic_balance","test"

11
mis_builder/tests/mis_builder_test.py

@ -36,9 +36,16 @@ class mis_builder_test(common.TransactionCase):
def test_datetime_conversion(self):
date_to_convert = '2014-07-05'
date_time_convert = models.mis_builder.utc_midnight(date_to_convert)
date_time_convert = models.mis_builder._utc_midnight(date_to_convert)
self.assertEqual(date_time_convert, '2014-07-05 00:00:00', 'The converted date time convert must contains hour')
date_time_convert = models.mis_builder.utc_midnight(date_to_convert, add_day=1)
date_time_convert = models.mis_builder._utc_midnight(date_to_convert, add_day=1)
self.assertEqual(date_time_convert, '2014-07-06 00:00:00', 'The converted date time convert must contains hour')
def test_fetch_query(self):
# create a report on a model without company_id field : account.analytic.balance
data = self.registry('mis.report.instance').compute(self.cr, self.uid, self.ref('mis_builder.mis_report_instance_test'))
self.assertDictContainsSubset({'rows': [{'description': u'total test', 'name': u'total_test'}],
'cols': [{'values': {u'total_test': {'val_c': None, 'val': 0, 'val_r': '0'}},
'name': u'today'}]}, data)
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

23
mis_builder/views/mis_builder.xml

@ -27,6 +27,7 @@
<field name="name"/>
<field name="model_id"/>
<field name="field_ids" domain="[('model_id', '=', model_id)]" widget="many2many_tags"/>
<field name="field_name"/>
<field name="date_field" domain="[('model_id', '=', model_id), ('ttype', 'in', ('date', 'datetime'))]"/>
<field name="domain"/>
</tree>
@ -34,7 +35,7 @@
<field name="kpi_ids">
<tree string="KPI's" editable="bottom">
<field name="sequence" widget="handle"/>
<field name="description" on_change="onchange_description(description, context)"/>
<field name="description" on_change="onchange_description(description, name, context)"/>
<field name="name" on_change="onchange_name(name, context)"/>
<field name="expression"/>
<field name="type" on_change="onchange_type(type, context)"/>
@ -51,7 +52,7 @@
</record>
<record model="ir.actions.act_window" id="mis_report_view_action">
<field name="name">mis.report.view.action</field>
<field name="name">Mis report</field>
<field name="view_id" ref="mis_report_view_tree"/>
<field name="res_model">mis.report</field>
<field name="view_type">form</field>
@ -66,24 +67,13 @@
<field name="priority" eval="17"/>
<field name="arch" type="xml">
<form string="MIS Report Result" version="7.0">
<sheet>
<div class="oe_title">
<h1>
<field name="name" placeholder="Name"/>
</h1>
</div>
<group>
<field name="description"/>
<field name="pivot_date"/>
</group>
<widget type="mis_report"></widget>
</sheet>
<widget type="mis_report"></widget>
</form>
</field>
</record>
<record model="ir.actions.act_window" id="mis_report_instance_result_action">
<field name="name">mis.report.instance.result.view.action</field>
<field name="name">Preview</field>
<field name="view_id" ref="mis_report_instance_result_view_form"/>
<field name="res_model">mis.report.instance</field>
<field name="view_type">form</field>
@ -142,6 +132,7 @@
<field name="report_instance_id" invisible="1"/>
<field name="id" invisible="1"/>
<field name="comparison_column_ids" domain="[('report_instance_id', '=', report_instance_id), ('id', '!=', id)]" widget="many2many_tags"/>
<field name="company_id" groups="base.group_multi_company"/>
</tree>
</field>
</group>
@ -151,7 +142,7 @@
</record>
<record model="ir.actions.act_window" id="mis_report_instance_view_action">
<field name="name">mis.report.instance.view.action</field>
<field name="name">Mis report instance</field>
<field name="view_id" ref="mis_report_instance_view_tree"/>
<field name="res_model">mis.report.instance</field>
<field name="view_type">form</field>

Loading…
Cancel
Save