[REF] gamification: code review (WIP)

bzr revid: qdp-launchpad@openerp.com-20130603203053-dy7ia09rl0i1sxmd
This commit is contained in:
Quentin (OpenERP)
2013-06-03 22:30:53 +02:00
parent a8eb9301e4
commit 3887f78cef
7 changed files with 39 additions and 65 deletions
+2 -2
View File
@@ -33,7 +33,7 @@ Fields
- ``last_update`` : the date of the last modification of this goal
- ``computation_mode`` : related field from the linked goal type
- ``type_description`` : related field from the linked goal type
- ``type_unit`` : related field from the linked goal type
- ``type_suffix`` : related field from the linked goal type
- ``type_condition`` : related field from the linked goal type
@@ -43,4 +43,4 @@ Methods
- ``update`` :
Compute the current value of goal and change states accordingly and send reminder if needed.
- ``get_action`` :
Returns the action description specified for the goal modification. If an action XML ID is specified in the goal type definition it will be used. If a goal is manual, the action is a simple wizard to input a new value.
Returns the action description specified for the goal modification. If an action XML ID is specified in the goal type definition it will be used. If a goal is manual, the action is a simple wizard to input a new value.
+28 -52
View File
@@ -41,17 +41,18 @@ class gamification_goal_type(osv.Model):
"""
_name = 'gamification.goal.type'
_description = 'Gamification goal type'
_order = 'sequence'
def _get_suffix(self, cr, uid, ids, field_name, arg, context=None):
res = dict.fromkeys(ids, 0)
for goal in self.browse(cr, uid, ids, context):
if goal.unit and not goal.monetary:
res[goal.id] = goal.unit
res = dict.fromkeys(ids, '')
for goal in self.browse(cr, uid, ids, context=context):
if goal.suffix and not goal.monetary:
res[goal.id] = goal.suffix
elif goal.monetary:
# use the current user's company currency
user = self.pool.get('res.users').browse(cr, uid, uid, context)
if goal.unit:
res[goal.id] = "%s %s" % (user.company_id.currency_id.symbol, goal.unit)
if goal.suffix:
res[goal.id] = "%s %s" % (user.company_id.currency_id.symbol, goal.suffix)
else:
res[goal.id] = user.company_id.currency_id.symbol
else:
@@ -61,13 +62,9 @@ class gamification_goal_type(osv.Model):
_columns = {
'name': fields.char('Goal Type', required=True, translate=True),
'description': fields.text('Goal Description'),
'monetary': fields.boolean('Monetary Value', help="The target and current value are defined in the company currency."),
'unit': fields.char('Suffix',
help="The unit of the target and current values", translate=True),
'full_suffix': fields.function(_get_suffix, type="char",
string="Full Suffix", help="The currency and suffix field"),
'suffix': fields.char('Suffix', help="The unit of the target and current values", translate=True),
'full_suffix': fields.function(_get_suffix, type="char", string="Full Suffix", help="The currency and suffix field"),
'computation_mode': fields.selection([
('manually', 'Recorded manually'),
('count', 'Automatic: number of records'),
@@ -75,13 +72,12 @@ class gamification_goal_type(osv.Model):
('python', 'Automatic: execute a specific Python code'),
],
string="Computation Mode",
required=True),
required=True), #TODO: add help tooltip
'display_mode': fields.selection([
('progress', 'Progressive (using numerical values)'),
('checkbox', 'Checkbox (done or not-done)'),
],
string="Displayed as", required=True),
'model_id': fields.many2one('ir.model',
string='Model',
help='The model object for the field to evaluate'),
@@ -96,7 +92,6 @@ class gamification_goal_type(osv.Model):
required=True),
'compute_code': fields.char('Compute Code',
help="The name of the python method that will be executed to compute the current value. See the file gamification/goal_type_data.py for examples."),
'condition': fields.selection([
('higher', 'The higher the better'),
('lower', 'The lower the better')
@@ -104,18 +99,13 @@ class gamification_goal_type(osv.Model):
string='Goal Performance',
help='A goal is considered as completed when the current value is compared to the value to reach',
required=True),
'sequence': fields.integer('Sequence',
help='Sequence number for ordering',
required=True),
'action_id': fields.many2one('ir.actions.act_window',
string="Action",
'sequence': fields.integer('Sequence', help='Sequence number for ordering', required=True),
'action_id': fields.many2one('ir.actions.act_window', string="Action",
help="The action that will be called to update the goal value."),
'res_id_field': fields.char("ID Field of user",
help="The field name on the user profile (res.users) containing the value for res_id for action.")
}
_order = 'sequence'
_defaults = {
'sequence': 1,
'condition': 'higher',
@@ -137,19 +127,13 @@ class gamification_goal(osv.Model):
def _get_completeness(self, cr, uid, ids, field_name, arg, context=None):
"""Return the percentage of completeness of the goal, between 0 and 100"""
res = {}
for goal in self.browse(cr, uid, ids, context):
if goal.type_condition == 'higher':
if goal.current > 0:
res[goal.id] = min(100, round(100.0 * goal.current / goal.target_goal, 2))
else:
res[goal.id] = 0.0
else:
res = dict.fromkeys(ids, 0.0)
for goal in self.browse(cr, uid, ids, context=context):
if goal.type_condition == 'higher' and goal.current > 0:
res[goal.id] = min(100, round(100.0 * goal.current / goal.target_goal, 2))
elif goal.current < goal.target_goal:
# a goal 'lower than' has only two values possible: 0 or 100%
if goal.current < goal.target_goal:
res[goal.id] = 100.0
else:
res[goal.id] = 0.0
res[goal.id] = 100.0
return res
def on_change_type_id(self, cr, uid, ids, type_id=False, context=None):
@@ -157,8 +141,7 @@ class gamification_goal(osv.Model):
if not type_id:
return {'value': {'type_id': False}}
goal_type = goal_type.browse(cr, uid, type_id, context=context)
ret = {'value': {'computation_mode': goal_type.computation_mode, 'type_condition': goal_type.condition}}
return ret
return {'value': {'computation_mode': goal_type.computation_mode, 'type_condition': goal_type.condition}}
_columns = {
'type_id': fields.many2one('gamification.goal.type',
@@ -166,7 +149,7 @@ class gamification_goal(osv.Model):
required=True,
ondelete="cascade"),
'user_id': fields.many2one('res.users', string='User', required=True),
'planline_id' : fields.many2one('gamification.goal.planline',
'planline_id': fields.many2one('gamification.goal.planline',
string='Goal Planline',
ondelete="cascade"),
'plan_id': fields.related('planline_id', 'plan_id',
@@ -207,7 +190,7 @@ class gamification_goal(osv.Model):
'type_description': fields.related('type_id', 'description',
type='char', string='Type Description', readonly=True),
'type_unit': fields.related('type_id', 'unit',
'type_suffix': fields.related('type_id', 'suffix',
type='char', string='Type Description', readonly=True),
'type_condition': fields.related('type_id', 'condition',
type='char', string='Type Condition', readonly=True),
@@ -224,6 +207,7 @@ class gamification_goal(osv.Model):
}
_order = 'create_date desc, end_date desc, type_id, id'
#TODO code review of this method
def update(self, cr, uid, ids, context=None):
"""Update the goals to recomputes values and change of states
@@ -232,7 +216,6 @@ class gamification_goal(osv.Model):
If a goal reaches the target value, the status is set to reached
If the end date is passed (at least +1 day, time not considered) without
the target value being reached, the goal is set as failed."""
if context is None: context = {}
for goal in self.browse(cr, uid, ids, context=context):
if goal.state in ('draft', 'canceled'):
@@ -250,12 +233,8 @@ class gamification_goal(osv.Model):
# generate a remind report
template_env = TemplateHelper()
body_html = template_env.get_template('reminder.mako').render({'object':goal})
self.message_post(cr, uid, goal.id,
body=body_html,
partner_ids=[goal.user_id.partner_id.id],
context=context,
subtype='mail.mt_comment')
body_html = template_env.get_template('reminder.mako').render({'object': goal})
self.message_post(cr, uid, goal.id, body=body_html, partner_ids=[goal.user_id.partner_id.id], context=context, subtype='mail.mt_comment')
elif goal.type_id.computation_mode == 'python':
values = {'cr': cr, 'uid': goal.user_id.id, 'context': context, 'self': self.pool.get('gamification.goal.type')}
@@ -294,10 +273,7 @@ class gamification_goal(osv.Model):
towrite = {'current': len(res)}
# check goal target reached
if (goal.type_id.condition == 'higher' \
and towrite['current'] >= goal.target_goal) \
or (goal.type_id.condition == 'lower' \
and towrite['current'] <= goal.target_goal):
if (goal.type_id.condition == 'higher' and towrite['current'] >= goal.target_goal) or (goal.type_id.condition == 'lower' and towrite['current'] <= goal.target_goal):
towrite['state'] = 'reached'
# check goal failure
@@ -418,19 +394,18 @@ class gamification_goal(osv.Model):
values = {'state': 'reached', 'current': 1}
self.write(cr, uid, goal_ids, values, context=context)
#TOCHECK: it's totally unclear for me what the 'current' and the update method...
class goal_manual_wizard(osv.TransientModel):
"""Wizard type to update a manual goal"""
_name = 'gamification.goal.wizard'
_columns = {
'goal_id': fields.many2one("gamification.goal", string='Goal'),
'goal_id': fields.many2one("gamification.goal", string='Goal', required=True),
'current': fields.float('Current'),
}
def action_update_current(self, cr, uid, ids, context=None):
"""Wizard action for updating the current value"""
if context is None:
context = {}
goal_obj = self.pool.get('gamification.goal')
@@ -442,3 +417,4 @@ class goal_manual_wizard(osv.TransientModel):
goal_obj.write(cr, uid, [wiz.goal_id.id], towrite, context=context)
goal_obj.update(cr, uid, [wiz.goal_id.id], context=context)
return {}
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
+1 -3
View File
@@ -35,8 +35,6 @@ class gamification_goal_type_data(osv.Model):
The model specified in 'xml_id' must inherit from mail.thread
"""
if context is None: context = {}
ref_obj = self.pool.get(xml_id)
user = self.pool.get('res.users').browse(cr, uid, uid, context=context)
count = ref_obj.search(cr, uid, [('message_follower_ids', '=', user.partner_id.id)], count=True, context=context)
return count
return ref_obj.search(cr, uid, [('message_follower_ids', '=', user.partner_id.id)], count=True, context=context)
+1 -1
View File
@@ -250,7 +250,7 @@
</group>
<group string="Formating Options">
<field name="display_mode" widget="radio" />
<field name="unit" placeholder="e.g. days"/>
<field name="suffix" placeholder="e.g. days"/>
<field name="monetary"/>
</group>
<group string="Clickable Goals">
+1 -1
View File
@@ -791,7 +791,7 @@ class gamification_goal_planline(osv.Model):
}),
'type_condition': fields.related('type_id', 'condition', type="selection",
readonly=True, string="Condition", selection=[('lower', '<='), ('higher', '>=')]),
'type_unit': fields.related('type_id', 'unit', type="char", readonly=True, string="Unit"),
'type_suffix': fields.related('type_id', 'suffix', type="char", readonly=True, string="Unit"),
'type_monetary': fields.related('type_id', 'monetary', type="boolean", readonly=True, string="Monetary"),
'type_full_suffix': fields.related('type_id', 'full_suffix', type="char", readonly=True, string="Suffix"),
}
+2 -2
View File
@@ -56,7 +56,7 @@ class res_users_gamification_group(osv.Model):
'type_condition': planline_board['goal_type'].condition,
'type_computation_mode': planline_board['goal_type'].computation_mode,
'type_monetary': planline_board['goal_type'].monetary,
'type_unit': planline_board['goal_type'].unit,
'type_suffix': planline_board['goal_type'].suffix,
'type_action': True if planline_board['goal_type'].action_id else False,
'type_display': planline_board['goal_type'].display_mode,
'target_goal': planline_board['target_goal'],
@@ -95,7 +95,7 @@ class res_users_gamification_group(osv.Model):
'type_description': goal.type_description,
'type_condition': goal.type_id.condition,
'type_monetary': goal.type_id.monetary,
'type_unit': goal.type_id.unit,
'type_suffix': goal.type_id.suffix,
'type_action': True if goal.type_id.action_id else False,
'type_display': goal.type_id.display_mode,
'state': goal.state,
@@ -34,7 +34,7 @@
Target: &lt;=
</t>
<span t-attf-class="#{goal.type_monetary ? 'oe_goal_field_monetary' : ''}"><t t-esc="goal.target_goal"/></span>
<t t-if="goal.type_unit"><t t-esc="goal.type_unit"/></t>
<t t-if="goal.type_suffix"><t t-esc="goal.type_suffix"/></t>
</div>
</t>
</div>
@@ -55,7 +55,7 @@
<t t-if="planline.type_condition == 'lower'">
Target: &lt;=
</t>
<span t-attf-class="#{planline.type_monetary ? 'oe_goal_field_monetary' : ''}"><t t-esc="planline.target_goal" /></span><t t-if="planline.type_unit"> <t t-esc="planline.type_unit"/></t>
<span t-attf-class="#{planline.type_monetary ? 'oe_goal_field_monetary' : ''}"><t t-esc="planline.target_goal" /></span><t t-if="planline.type_suffix"> <t t-esc="planline.type_suffix"/></t>
</div>
</div>
</div>
@@ -73,11 +73,11 @@
<!-- progress, action on current value -->
<t t-esc="goal.user_name"/><br/>
<t t-if="goal.id != planline.own_goal_id or (planline.computation_mode != 'manually' and !planline.type_action)">
<span t-attf-class="#{planline.type_monetary ? 'oe_goal_field_monetary' : ''}"><t t-esc="goal.current" /></span><t t-if="planline.type_unit"> <t t-esc="planline.type_unit"/></t>
<span t-attf-class="#{planline.type_monetary ? 'oe_goal_field_monetary' : ''}"><t t-esc="goal.current" /></span><t t-if="planline.type_suffix"> <t t-esc="planline.type_suffix"/></t>
</t>
<t t-if="goal.id == planline.own_goal_id and (planline.type_action or planline.computation_mode == 'manually')">
<a class="oe_goal_action" t-att-id="planline.own_goal_id">
<span t-attf-class="#{planline.type_monetary ? 'oe_goal_field_monetary' : ''}"><t t-esc="goal.current" /></span><t t-if="planline.type_unit"> <t t-esc="planline.type_unit"/></t>
<span t-attf-class="#{planline.type_monetary ? 'oe_goal_field_monetary' : ''}"><t t-esc="goal.current" /></span><t t-if="planline.type_suffix"> <t t-esc="planline.type_suffix"/></t>
</a>
</t>
</t>