[IMP] better badge views and checks
bzr revid: mat@openerp.com-20130412085452-mnecqo80cgmo2ecs
This commit is contained in:
parent
28761467fc
commit
252365095a
|
@ -26,6 +26,9 @@ from openerp.tools.safe_eval import safe_eval
|
||||||
|
|
||||||
from templates import TemplateHelper
|
from templates import TemplateHelper
|
||||||
from datetime import date
|
from datetime import date
|
||||||
|
import logging
|
||||||
|
|
||||||
|
_logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class gamification_badge_user(osv.Model):
|
class gamification_badge_user(osv.Model):
|
||||||
|
@ -130,6 +133,24 @@ class gamification_badge(osv.Model):
|
||||||
('create_date', '>=', first_month_day)], context=context))
|
('create_date', '>=', first_month_day)], context=context))
|
||||||
return result
|
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 = {
|
_columns = {
|
||||||
'name': fields.char('Badge', required=True, translate=True),
|
'name': fields.char('Badge', required=True, translate=True),
|
||||||
'description': fields.text('Description'),
|
'description': fields.text('Description'),
|
||||||
|
@ -161,6 +182,8 @@ class gamification_badge(osv.Model):
|
||||||
type="integer",
|
type="integer",
|
||||||
string='My Monthly Sending Total',
|
string='My Monthly Sending Total',
|
||||||
help="The number of time the current user has sent this badge this month."),
|
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([
|
'rule_automatic': fields.selection([
|
||||||
('goals', 'List of goals to reach'),
|
('goals', 'List of goals to reach'),
|
||||||
|
@ -338,22 +361,46 @@ class gamification_badge(osv.Model):
|
||||||
|
|
||||||
return True
|
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):
|
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
|
"""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 user_from_id: the id of the res.users trying to send the badge
|
||||||
:param badge_id: the granted badge id
|
: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 {}
|
context = context or {}
|
||||||
badge = self.browse(cr, uid, badge_id, context=context)
|
badge = self.browse(cr, uid, badge_id, context=context)
|
||||||
|
|
||||||
if badge.rule_auth == 'nobody':
|
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]:
|
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':
|
elif badge.rule_auth == 'having':
|
||||||
badge_users = self.pool.get('gamification.badge.user').search(
|
badge_users = self.pool.get('gamification.badge.user').search(
|
||||||
|
@ -361,23 +408,24 @@ class gamification_badge(osv.Model):
|
||||||
|
|
||||||
if len(badge_users) == 0:
|
if len(badge_users) == 0:
|
||||||
# the user_from has no badges
|
# 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]
|
owners = [owner.id for owner in badge.owner_ids]
|
||||||
granted = False
|
granted = False
|
||||||
for badge_user in badge_users:
|
for badge_user in badge_users:
|
||||||
if badge_user.id in owners:
|
if badge_user in owners:
|
||||||
granted = True
|
granted = True
|
||||||
|
break
|
||||||
if not granted:
|
if not granted:
|
||||||
raise osv.except_osv(_('Warning!'), _('You do not have the required badges.'))
|
return 4
|
||||||
|
|
||||||
# else badge.rule_auth == 'everyone' -> no check
|
# else badge.rule_auth == 'everyone' -> no check
|
||||||
|
|
||||||
if badge.rule_max and badge.stat_my_monthly_sending >= badge.rule_max_number:
|
if badge.rule_max and badge.stat_my_monthly_sending >= badge.rule_max_number:
|
||||||
# sent the maximum number of time this month
|
# 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):
|
class grant_badge_wizard(osv.TransientModel):
|
||||||
|
@ -400,7 +448,7 @@ class grant_badge_wizard(osv.TransientModel):
|
||||||
if uid == wiz.user_id.id:
|
if uid == wiz.user_id.id:
|
||||||
raise osv.except_osv(_('Warning!'), _('You can not send a badge to yourself'))
|
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,
|
user_from_id=uid,
|
||||||
badge_id=wiz.badge_id.id,
|
badge_id=wiz.badge_id.id,
|
||||||
context=context):
|
context=context):
|
||||||
|
|
|
@ -93,8 +93,16 @@
|
||||||
<field name="rule_auth_badge_ids" attrs="{'invisible': [('rule_auth','!=','having')]}" widget="many2many_tags" />
|
<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" attrs="{'invisible': [('rule_auth','=','nobody')]}" />
|
||||||
<field name="rule_max_number" attrs="{'invisible': ['|',('rule_max','=',False),('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>
|
||||||
<group string="Automatic Rules">
|
<group string="Automatic Rules">
|
||||||
<field name="rule_automatic" widget="radio"/>
|
<field name="rule_automatic" widget="radio"/>
|
||||||
|
@ -110,7 +118,6 @@
|
||||||
<group>
|
<group>
|
||||||
<field name="stat_my"/>
|
<field name="stat_my"/>
|
||||||
<field name="stat_my_this_month"/>
|
<field name="stat_my_this_month"/>
|
||||||
|
|
||||||
</group>
|
</group>
|
||||||
</group>
|
</group>
|
||||||
</sheet>
|
</sheet>
|
||||||
|
@ -129,25 +136,45 @@
|
||||||
<field name="image"/>
|
<field name="image"/>
|
||||||
<field name="stat_my"/>
|
<field name="stat_my"/>
|
||||||
<field name="stat_count"/>
|
<field name="stat_count"/>
|
||||||
<field name="stat_count_distinct"/>
|
<field name="stat_this_month"/>
|
||||||
<field name="unique_owner_ids"/>
|
<field name="unique_owner_ids"/>
|
||||||
|
<field name="remaining_sending" />
|
||||||
|
<field name="rule_max_number" />
|
||||||
<templates>
|
<templates>
|
||||||
<t t-name="kanban-box">
|
<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 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_content">
|
||||||
<div class="oe_kanban_left">
|
<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>
|
</div>
|
||||||
<h4><a type="open"><field name="name"/></a></h4>
|
<div>
|
||||||
<t t-if="record.description.value">
|
<h4><a type="open"><field name="name"/></a></h4>
|
||||||
<em><field name="description"/></em>
|
<t t-if="record.description.value">
|
||||||
</t>
|
<em><field name="description"/></em>
|
||||||
<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"/>
|
|
||||||
</t>
|
</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>
|
||||||
</div>
|
</div>
|
||||||
</t>
|
</t>
|
||||||
|
@ -171,7 +198,7 @@
|
||||||
<field name="create_date"/>
|
<field name="create_date"/>
|
||||||
<templates>
|
<templates>
|
||||||
<t t-name="kanban-box">
|
<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_content">
|
||||||
<div class="oe_kanban_left">
|
<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>
|
<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>
|
||||||
|
|
|
@ -25,9 +25,6 @@ from openerp.tools.safe_eval import safe_eval
|
||||||
from templates import TemplateHelper
|
from templates import TemplateHelper
|
||||||
|
|
||||||
from datetime import date, datetime, timedelta
|
from datetime import date, datetime, timedelta
|
||||||
import logging
|
|
||||||
|
|
||||||
_logger = logging.getLogger(__name__)
|
|
||||||
|
|
||||||
|
|
||||||
class gamification_goal_type(osv.Model):
|
class gamification_goal_type(osv.Model):
|
||||||
|
|
|
@ -1,9 +1,12 @@
|
||||||
/* Kanban views */
|
/* Kanban views */
|
||||||
.openerp .oe_kanban_view .oe_kanban_card.oe_kanban_goal,
|
.openerp .oe_kanban_view .oe_kanban_card.oe_kanban_goal {
|
||||||
.openerp .oe_kanban_view .oe_kanban_card.oe_kanban_badge {
|
|
||||||
width: 220px;
|
width: 220px;
|
||||||
min-height: 200px;
|
min-height: 200px;
|
||||||
}
|
}
|
||||||
|
.openerp .oe_kanban_view .oe_kanban_card.oe_kanban_badge {
|
||||||
|
width: 250px;
|
||||||
|
min-height: 150px;
|
||||||
|
}
|
||||||
.oe_kanban_badge_avatars {
|
.oe_kanban_badge_avatars {
|
||||||
margin-top: 8px;
|
margin-top: 8px;
|
||||||
}
|
}
|
||||||
|
@ -21,7 +24,8 @@
|
||||||
margin: auto;
|
margin: auto;
|
||||||
margin-bottom: -20px;
|
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;
|
text-align: center;
|
||||||
}
|
}
|
||||||
.oe_kanban_goal .oe_goal_state_block .oe_goal_state {
|
.oe_kanban_goal .oe_goal_state_block .oe_goal_state {
|
||||||
|
|
|
@ -125,7 +125,7 @@ openerp.gamification = function(instance) {
|
||||||
self.$el.find('.oe_goal_gauge').attr('id', unique_id);
|
self.$el.find('.oe_goal_gauge').attr('id', unique_id);
|
||||||
var g = new JustGage({
|
var g = new JustGage({
|
||||||
id: unique_id,
|
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,
|
value: self.record.current.raw_value,
|
||||||
min: 0,
|
min: 0,
|
||||||
max: self.record.target_goal.raw_value,
|
max: self.record.target_goal.raw_value,
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
|
|
||||||
from openerp.osv import fields, osv
|
from openerp.osv import fields, osv
|
||||||
from openerp.tools.translate import _
|
from openerp.tools.translate import _
|
||||||
|
from openerp import SUPERUSER_ID
|
||||||
|
|
||||||
|
|
||||||
class hr_gamification_badge_user(osv.Model):
|
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 = self.browse(cr, uid, context['badge_id'], context=context)
|
||||||
badge_user = context['badge_user']
|
badge_user = context['badge_user']
|
||||||
if badge_user.employee_id:
|
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)
|
badge_user.employee_id.id, context=context, **kwargs)
|
||||||
return super(gamification_badge, self).message_post(cr, uid, thread_id, context=context, **kwargs)
|
return super(gamification_badge, self).message_post(cr, uid, thread_id, context=context, **kwargs)
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue