[IMP] better badge views and checks

bzr revid: mat@openerp.com-20130412085452-mnecqo80cgmo2ecs
This commit is contained in:
Martin Trigaux 2013-04-12 10:54:52 +02:00
parent 28761467fc
commit 252365095a
6 changed files with 110 additions and 33 deletions

View File

@ -26,6 +26,9 @@ from openerp.tools.safe_eval import safe_eval
from templates import TemplateHelper
from datetime import date
import logging
_logger = logging.getLogger(__name__)
class gamification_badge_user(osv.Model):
@ -130,6 +133,24 @@ class gamification_badge(osv.Model):
('create_date', '>=', first_month_day)], context=context))
return result
def _remaining_sending_calc(self, cr, uid, ids, name, args, context=None):
"""Computes the number of badges remaining the user can send
0 if not allowed or no remaining
integer if limited sending
-1 if infinite (should not be displayed)
"""
result = dict.fromkeys(ids, False)
for badge in self.browse(cr, uid, ids, context=context):
if self.can_grant_badge(cr, uid, uid, badge.id, context) != 1:
result[badge.id] = 0
elif not badge.rule_max:
result[badge.id] = -1
else:
result[badge.id] = badge.rule_max_number - badge.stat_my_monthly_sending
return result
_columns = {
'name': fields.char('Badge', required=True, translate=True),
'description': fields.text('Description'),
@ -161,6 +182,8 @@ class gamification_badge(osv.Model):
type="integer",
string='My Monthly Sending Total',
help="The number of time the current user has sent this badge this month."),
'remaining_sending': fields.function(_remaining_sending_calc, type='integer',
string='Remaining Sending Allowed', help="If a maxium is set"),
'rule_automatic': fields.selection([
('goals', 'List of goals to reach'),
@ -338,22 +361,46 @@ class gamification_badge(osv.Model):
return True
def check_granting(self, cr, uid, user_from_id, badge_id, context=None):
"""Check the user can grant a badge and raise the appropriate exception
if not"""
context = context or {}
status_code = self.can_grant_badge(cr, uid, user_from_id, badge_id, context)
if status_code == 1:
return True
elif status_code == 2:
raise osv.except_osv(_('Warning!'), _('This badge can not be sent by users.'))
elif status_code == 3:
raise osv.except_osv(_('Warning!'), _('You are not in the user allowed list.'))
elif status_code == 4:
raise osv.except_osv(_('Warning!'), _('You do not have the required badges.'))
elif status_code == 5:
raise osv.except_osv(_('Warning!'), _('You have already sent this badge too many time this month.'))
else:
_logger.exception("Unknown badge status code: %d" % int(status_code))
return False
def can_grant_badge(self, cr, uid, user_from_id, badge_id, context=None):
"""Check if a user can grant a badge to another user
:param user_from_id: the id of the res.users trying to send the badge
:param badge_id: the granted badge id
:return: boolean, True if succeeded to send, False otherwise
:return: integer representing the permission.
1: can grant
2: nobody can send
3: user not in the allowed list
4: don't have the required badges
5: user's monthly limit reached
"""
context = context or {}
badge = self.browse(cr, uid, badge_id, context=context)
if badge.rule_auth == 'nobody':
raise osv.except_osv(_('Warning!'), _('This badge can not be sent by users.'))
return 2
elif badge.rule_auth == 'list':
elif badge.rule_auth == 'users':
if user_from_id not in [user.id for user in badge.rule_auth_user_ids]:
raise osv.except_osv(_('Warning!'), _('You are not in the user allowed list.'))
return 3
elif badge.rule_auth == 'having':
badge_users = self.pool.get('gamification.badge.user').search(
@ -361,23 +408,24 @@ class gamification_badge(osv.Model):
if len(badge_users) == 0:
# the user_from has no badges
raise osv.except_osv(_('Warning!'), _('You do not have the required badges.'))
return 4
owners = [owner.id for owner in badge.owner_ids]
granted = False
for badge_user in badge_users:
if badge_user.id in owners:
if badge_user in owners:
granted = True
break
if not granted:
raise osv.except_osv(_('Warning!'), _('You do not have the required badges.'))
return 4
# else badge.rule_auth == 'everyone' -> no check
if badge.rule_max and badge.stat_my_monthly_sending >= badge.rule_max_number:
# sent the maximum number of time this month
raise osv.except_osv(_('Warning!'), _('You have already sent this badge too many time this month.'))
return 5
return True
return 1
class grant_badge_wizard(osv.TransientModel):
@ -400,7 +448,7 @@ class grant_badge_wizard(osv.TransientModel):
if uid == wiz.user_id.id:
raise osv.except_osv(_('Warning!'), _('You can not send a badge to yourself'))
if badge_obj.can_grant_badge(cr, uid,
if badge_obj.check_granting(cr, uid,
user_from_id=uid,
badge_id=wiz.badge_id.id,
context=context):

View File

@ -93,8 +93,16 @@
<field name="rule_auth_badge_ids" attrs="{'invisible': [('rule_auth','!=','having')]}" widget="many2many_tags" />
<field name="rule_max" attrs="{'invisible': [('rule_auth','=','nobody')]}" />
<field name="rule_max_number" attrs="{'invisible': ['|',('rule_max','=',False),('rule_auth','=','nobody')]}"/>
<field name="stat_my_monthly_sending" attrs="{'invisible': [('rule_auth','=','nobody')]}"/>
<label for="stat_my_monthly_sending"/>
<div>
<field name="stat_my_monthly_sending" attrs="{'invisible': [('rule_auth','=','nobody')]}" />
<div attrs="{'invisible': [('remaining_sending','=',-1)]}" class="oe_grey">
You can still send <field name="remaining_sending" class="oe_inline"/> badges this month
</div>
<div attrs="{'invisible': [('remaining_sending','!=',-1)]}" class="oe_grey">
No monthly sending limit
</div>
</div>
</group>
<group string="Automatic Rules">
<field name="rule_automatic" widget="radio"/>
@ -110,7 +118,6 @@
<group>
<field name="stat_my"/>
<field name="stat_my_this_month"/>
</group>
</group>
</sheet>
@ -129,25 +136,45 @@
<field name="image"/>
<field name="stat_my"/>
<field name="stat_count"/>
<field name="stat_count_distinct"/>
<field name="stat_this_month"/>
<field name="unique_owner_ids"/>
<field name="remaining_sending" />
<field name="rule_max_number" />
<templates>
<t t-name="kanban-box">
<div t-attf-class="#{record.stat_my.raw_value ? 'oe_kanban_color_5' : 'oe_kanban_color_white'} oe_kanban_card oe_kanban_global_click oe_kanban_badge">
<div class="oe_kanban_content">
<div class="oe_kanban_left">
<a type="open"><img t-att-src="kanban_image('gamification.badge', 'image', record.image.raw_value)" t-att-title="record.name.value" width="24" height="24" /></a>
<a type="open"><img t-att-src="kanban_image('gamification.badge', 'image', record.image.raw_value)" t-att-title="record.name.value" width="100" height="100" /></a>
<div class="oe_kanban_badge_avatars">
<t t-foreach="record.unique_owner_ids.raw_value.slice(0,11)" t-as="owner">
<img t-att-src="kanban_image('res.users', 'image_small', owner)" t-att-data-member_id="owner"/>
</t>
</div>
</div>
<h4><a type="open"><field name="name"/></a></h4>
<t t-if="record.description.value">
<em><field name="description"/></em>
</t>
<p>Granted <t t-esc="record.stat_count.raw_value" />x (<t t-esc="record.stat_count_distinct.raw_value"/> pers.)</p>
<div class="oe_kanban_badge_avatars">
<t t-foreach="record.unique_owner_ids.raw_value.slice(0,11)" t-as="owner">
<img t-att-src="kanban_image('res.users', 'image_small', owner)" t-att-data-member_id="owner"/>
<div>
<h4><a type="open"><field name="name"/></a></h4>
<t t-if="record.description.value">
<em><field name="description"/></em>
</t>
</div>
<p>
Total: <t t-esc="record.stat_count.raw_value"/> (<t t-esc="record.stat_this_month.raw_value"/> this month)
</p>
<t t-if="record.remaining_sending.value != 0">
<button type="action" name="%(action_grant_wizard)d" class="oe_highlight">Grant</button>
<p class="oe_grey">
<t t-if="record.remaining_sending.value != -1">
<t t-esc="record.remaining_sending.value"/>/<t t-esc="record.rule_max_number.value"/> remaining
</t>
<t t-if="record.remaining_sending.value == -1">
</t>
</p>
</t>
<t t-if="record.remaining_sending.value == 0">
<div class="oe_grey">You can not send this badge</div>
</t>
</div>
</div>
</div>
</t>
@ -171,7 +198,7 @@
<field name="create_date"/>
<templates>
<t t-name="kanban-box">
<div class="oe_kanban_card oe_kanban_global_click oe_kanban_goal oe_kanban_color_white">
<div class="oe_kanban_card oe_kanban_global_click oe_kanban_badge oe_kanban_color_white">
<div class="oe_kanban_content">
<div class="oe_kanban_left">
<a type="open"><img t-att-src="kanban_image('gamification.badge', 'image', record.badge_id.raw_value)" t-att-title="record.badge_name.value" width="24" height="24" /></a>

View File

@ -25,9 +25,6 @@ from openerp.tools.safe_eval import safe_eval
from templates import TemplateHelper
from datetime import date, datetime, timedelta
import logging
_logger = logging.getLogger(__name__)
class gamification_goal_type(osv.Model):

View File

@ -1,9 +1,12 @@
/* Kanban views */
.openerp .oe_kanban_view .oe_kanban_card.oe_kanban_goal,
.openerp .oe_kanban_view .oe_kanban_card.oe_kanban_badge {
.openerp .oe_kanban_view .oe_kanban_card.oe_kanban_goal {
width: 220px;
min-height: 200px;
}
.openerp .oe_kanban_view .oe_kanban_card.oe_kanban_badge {
width: 250px;
min-height: 150px;
}
.oe_kanban_badge_avatars {
margin-top: 8px;
}
@ -21,7 +24,8 @@
margin: auto;
margin-bottom: -20px;
}
.oe_kanban_goal .oe_goal_state_block,p {
.oe_kanban_goal .oe_goal_state_block,
.oe_kanban_goal p {
text-align: center;
}
.oe_kanban_goal .oe_goal_state_block .oe_goal_state {

View File

@ -125,7 +125,7 @@ openerp.gamification = function(instance) {
self.$el.find('.oe_goal_gauge').attr('id', unique_id);
var g = new JustGage({
id: unique_id,
node: self.$el.find('.oe_goal_gauge').empty().get(0),
node: self.$('.oe_goal_gauge').empty().get(0),
value: self.record.current.raw_value,
min: 0,
max: self.record.target_goal.raw_value,

View File

@ -21,6 +21,7 @@
from openerp.osv import fields, osv
from openerp.tools.translate import _
from openerp import SUPERUSER_ID
class hr_gamification_badge_user(osv.Model):
@ -56,7 +57,7 @@ class gamification_badge(osv.Model):
badge = self.browse(cr, uid, context['badge_id'], context=context)
badge_user = context['badge_user']
if badge_user.employee_id:
return self.pool.get('hr.employee').message_post(cr, uid,
return self.pool.get('hr.employee').message_post(cr, SUPERUSER_ID,
badge_user.employee_id.id, context=context, **kwargs)
return super(gamification_badge, self).message_post(cr, uid, thread_id, context=context, **kwargs)