summaryrefslogtreecommitdiff
path: root/addons/gamification
diff options
context:
space:
mode:
authorMartin Trigaux <mat@openerp.com>2013-04-12 10:54:52 +0200
committerMartin Trigaux <mat@openerp.com>2013-04-12 10:54:52 +0200
commit252365095a18b71ac0912ca2bc3f5262ffdd87b8 (patch)
treee7068f83d354327844d2c2ea0007bb8bc9603998 /addons/gamification
parent28761467fc3c13f45f655b39b58cb233a7a1c1ea (diff)
[IMP] better badge views and checks
bzr revid: mat@openerp.com-20130412085452-mnecqo80cgmo2ecs
Diffstat (limited to 'addons/gamification')
-rw-r--r--addons/gamification/badge.py68
-rw-r--r--addons/gamification/badge_view.xml57
-rw-r--r--addons/gamification/goal.py3
-rw-r--r--addons/gamification/static/src/css/goal.css10
-rw-r--r--addons/gamification/static/src/js/gamification.js2
5 files changed, 108 insertions, 32 deletions
diff --git a/addons/gamification/badge.py b/addons/gamification/badge.py
index a681caa6ecf..3872c4362a2 100644
--- a/addons/gamification/badge.py
+++ b/addons/gamification/badge.py
@@ -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):
diff --git a/addons/gamification/badge_view.xml b/addons/gamification/badge_view.xml
index a590308cc5f..84fbbd14c68 100644
--- a/addons/gamification/badge_view.xml
+++ b/addons/gamification/badge_view.xml
@@ -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>
diff --git a/addons/gamification/goal.py b/addons/gamification/goal.py
index 9acc4b9cb95..b3ebced9ed1 100644
--- a/addons/gamification/goal.py
+++ b/addons/gamification/goal.py
@@ -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):
diff --git a/addons/gamification/static/src/css/goal.css b/addons/gamification/static/src/css/goal.css
index 82a0d60b903..cb8054f33b4 100644
--- a/addons/gamification/static/src/css/goal.css
+++ b/addons/gamification/static/src/css/goal.css
@@ -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 {
diff --git a/addons/gamification/static/src/js/gamification.js b/addons/gamification/static/src/js/gamification.js
index 44af26550a0..a856d057172 100644
--- a/addons/gamification/static/src/js/gamification.js
+++ b/addons/gamification/static/src/js/gamification.js
@@ -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,