mirror of
https://github.com/bringout/oca-ocb-vertical-industry.git
synced 2026-04-21 10:52:08 +02:00
19.0 vanilla
This commit is contained in:
parent
4607ccbd2e
commit
825ff6514e
487 changed files with 184979 additions and 195262 deletions
|
|
@ -6,9 +6,10 @@ import logging
|
|||
from datetime import date, timedelta
|
||||
|
||||
from dateutil.relativedelta import relativedelta, MO
|
||||
from markupsafe import Markup
|
||||
|
||||
from odoo import api, models, fields, _, exceptions
|
||||
from odoo.tools import ustr
|
||||
from odoo import _, api, exceptions, fields, models
|
||||
from odoo.http import SESSION_LIFETIME
|
||||
|
||||
_logger = logging.getLogger(__name__)
|
||||
|
||||
|
|
@ -44,7 +45,8 @@ def start_end_date_for_period(period, default_start_date=False, default_end_date
|
|||
|
||||
return fields.Datetime.to_string(start_date), fields.Datetime.to_string(end_date)
|
||||
|
||||
class Challenge(models.Model):
|
||||
|
||||
class GamificationChallenge(models.Model):
|
||||
"""Gamification challenge
|
||||
|
||||
Set of predifined objectives assigned to people with rules for recurrence and
|
||||
|
|
@ -57,15 +59,15 @@ class Challenge(models.Model):
|
|||
|
||||
_name = 'gamification.challenge'
|
||||
_description = 'Gamification Challenge'
|
||||
_inherit = 'mail.thread'
|
||||
_inherit = ['mail.thread']
|
||||
_order = 'end_date, start_date, name, id'
|
||||
|
||||
@api.model
|
||||
def default_get(self, fields_list):
|
||||
res = super().default_get(fields_list)
|
||||
if 'user_domain' in fields_list and 'user_domain' not in res:
|
||||
def default_get(self, fields):
|
||||
res = super().default_get(fields)
|
||||
if 'user_domain' in fields and 'user_domain' not in res:
|
||||
user_group_id = self.env.ref('base.group_user')
|
||||
res['user_domain'] = f'["&", ("groups_id", "=", "{user_group_id.name}"), ("active", "=", True)]'
|
||||
res['user_domain'] = f'["&", ("all_group_ids", "in", [{user_group_id.id}]), ("active", "=", True)]'
|
||||
return res
|
||||
|
||||
# description
|
||||
|
|
@ -105,7 +107,7 @@ class Challenge(models.Model):
|
|||
help="List of goals that will be set",
|
||||
required=True, copy=True)
|
||||
|
||||
reward_id = fields.Many2one('gamification.badge', string="For Every Succeeding User")
|
||||
reward_id = fields.Many2one('gamification.badge', string="For Every Succeeding User", index='btree_not_null')
|
||||
reward_first_id = fields.Many2one('gamification.badge', string="For 1st user")
|
||||
reward_second_id = fields.Many2one('gamification.badge', string="For 2nd user")
|
||||
reward_third_id = fields.Many2one('gamification.badge', string="For 3rd user")
|
||||
|
|
@ -127,7 +129,7 @@ class Challenge(models.Model):
|
|||
('yearly', "Yearly")
|
||||
], default='never',
|
||||
string="Report Frequency", required=True)
|
||||
report_message_group_id = fields.Many2one('mail.channel', string="Send a copy to", help="Group that will receive a copy of the report in addition to the user")
|
||||
report_message_group_id = fields.Many2one('discuss.channel', string="Send a copy to", help="Group that will receive a copy of the report in addition to the user")
|
||||
report_template_id = fields.Many2one('mail.template', default=lambda self: self._get_report_template(), string="Report Template", required=True)
|
||||
remind_update_delay = fields.Integer("Non-updated manual goals will be reminded after", help="Never reminded if no value or zero is specified.")
|
||||
last_report_date = fields.Date("Last Report Date", default=fields.Date.today)
|
||||
|
|
@ -188,8 +190,8 @@ class Challenge(models.Model):
|
|||
def create(self, vals_list):
|
||||
"""Overwrite the create method to add the user of groups"""
|
||||
for vals in vals_list:
|
||||
if vals.get('user_domain'):
|
||||
users = self._get_challenger_users(ustr(vals.get('user_domain')))
|
||||
if user_domain := vals.get('user_domain'):
|
||||
users = self._get_challenger_users(str(user_domain))
|
||||
|
||||
if not vals.get('user_ids'):
|
||||
vals['user_ids'] = []
|
||||
|
|
@ -198,19 +200,14 @@ class Challenge(models.Model):
|
|||
return super().create(vals_list)
|
||||
|
||||
def write(self, vals):
|
||||
if vals.get('user_domain'):
|
||||
users = self._get_challenger_users(ustr(vals.get('user_domain')))
|
||||
if user_domain := vals.get('user_domain'):
|
||||
users = self._get_challenger_users(str(user_domain))
|
||||
|
||||
if not vals.get('user_ids'):
|
||||
vals['user_ids'] = []
|
||||
vals['user_ids'].extend((4, user.id) for user in users)
|
||||
|
||||
write_res = super(Challenge, self).write(vals)
|
||||
|
||||
if vals.get('report_message_frequency', 'never') != 'never':
|
||||
# _recompute_challenge_users do not set users for challenges with no reports, subscribing them now
|
||||
for challenge in self:
|
||||
challenge.message_subscribe([user.partner_id.id for user in challenge.user_ids])
|
||||
write_res = super().write(vals)
|
||||
|
||||
if vals.get('state') == 'inprogress':
|
||||
self._recompute_challenge_users()
|
||||
|
|
@ -221,7 +218,7 @@ class Challenge(models.Model):
|
|||
|
||||
elif vals.get('state') == 'draft':
|
||||
# resetting progress
|
||||
if self.env['gamification.goal'].search([('challenge_id', 'in', self.ids), ('state', '=', 'inprogress')], limit=1):
|
||||
if self.env['gamification.goal'].search_count([('challenge_id', 'in', self.ids), ('state', '=', 'inprogress')], limit=1):
|
||||
raise exceptions.UserError(_("You can not reset a challenge with unfinished goals."))
|
||||
|
||||
return write_res
|
||||
|
|
@ -267,22 +264,28 @@ class Challenge(models.Model):
|
|||
return True
|
||||
|
||||
Goals = self.env['gamification.goal']
|
||||
|
||||
self.flush_recordset()
|
||||
self.user_ids.presence_ids.flush_recordset()
|
||||
# include yesterday goals to update the goals that just ended
|
||||
# exclude goals for portal users that did not connect since the last update
|
||||
# exclude goals for users that have not interacted with the
|
||||
# webclient since the last update or whose session is no longer
|
||||
# valid.
|
||||
yesterday = fields.Date.to_string(date.today() - timedelta(days=1))
|
||||
self.env.cr.execute("""SELECT gg.id
|
||||
FROM gamification_goal as gg
|
||||
JOIN res_users_log as log ON gg.user_id = log.create_uid
|
||||
JOIN res_users ru on log.create_uid = ru.id
|
||||
WHERE (gg.write_date < log.create_date OR ru.share IS NOT TRUE)
|
||||
AND ru.active IS TRUE
|
||||
JOIN mail_presence as mp ON mp.user_id = gg.user_id
|
||||
WHERE gg.write_date <= mp.last_presence
|
||||
AND mp.last_presence >= now() AT TIME ZONE 'UTC' - interval '%(session_lifetime)s seconds'
|
||||
AND gg.closed IS NOT TRUE
|
||||
AND gg.challenge_id IN %s
|
||||
AND gg.challenge_id IN %(challenge_ids)s
|
||||
AND (gg.state = 'inprogress'
|
||||
OR (gg.state = 'reached' AND gg.end_date >= %s))
|
||||
OR (gg.state = 'reached' AND gg.end_date >= %(yesterday)s))
|
||||
GROUP BY gg.id
|
||||
""", [tuple(self.ids), yesterday])
|
||||
""", {
|
||||
'session_lifetime': SESSION_LIFETIME,
|
||||
'challenge_ids': tuple(self.ids),
|
||||
'yesterday': yesterday
|
||||
})
|
||||
|
||||
Goals.browse(goal_id for [goal_id] in self.env.cr.fetchall()).update_goal()
|
||||
|
||||
|
|
@ -520,24 +523,27 @@ class Challenge(models.Model):
|
|||
|
||||
domain.append(('user_id', '=', user.id))
|
||||
|
||||
goal = Goals.search(domain, limit=1)
|
||||
goal = Goals.search_fetch(domain, ['current', 'completeness', 'state'], limit=1)
|
||||
if not goal:
|
||||
continue
|
||||
|
||||
if goal.state != 'reached':
|
||||
return []
|
||||
line_data.update(goal.read(['id', 'current', 'completeness', 'state'])[0])
|
||||
line_data.update({
|
||||
fname: goal[fname]
|
||||
for fname in ['id', 'current', 'completeness', 'state']
|
||||
})
|
||||
res_lines.append(line_data)
|
||||
continue
|
||||
|
||||
line_data['own_goal_id'] = False,
|
||||
line_data['goals'] = []
|
||||
if line.condition=='higher':
|
||||
goals = Goals.search(domain, order="completeness desc, current desc")
|
||||
else:
|
||||
goals = Goals.search(domain, order="completeness desc, current asc")
|
||||
goals = Goals.search(domain, order='id')
|
||||
if not goals:
|
||||
continue
|
||||
goals = goals.sorted(key=lambda goal: (
|
||||
-goal.completeness, -goal.current if line.condition == 'higher' else goal.current
|
||||
))
|
||||
|
||||
for ranking, goal in enumerate(goals):
|
||||
if user and goal.user_id == user:
|
||||
|
|
@ -608,7 +614,9 @@ class Challenge(models.Model):
|
|||
lines = challenge._get_serialized_challenge_lines(user, restrict_goals=subset_goals)
|
||||
if not lines:
|
||||
continue
|
||||
|
||||
# Avoid error if 'full_suffix' is missing in the line
|
||||
for line in lines:
|
||||
line.setdefault('full_suffix', '')
|
||||
body_html = challenge.report_template_id.with_user(user).with_context(challenge_lines=lines)._render_field('body_html', challenge.ids)[challenge.id]
|
||||
|
||||
# notify message only to users, do not post on the challenge
|
||||
|
|
@ -661,15 +669,14 @@ class Challenge(models.Model):
|
|||
challenge_ended = force or end_date == fields.Date.to_string(yesterday)
|
||||
if challenge.reward_id and (challenge_ended or challenge.reward_realtime):
|
||||
# not using start_date as intemportal goals have a start date but no end_date
|
||||
reached_goals = self.env['gamification.goal'].read_group([
|
||||
reached_goals = self.env['gamification.goal']._read_group([
|
||||
('challenge_id', '=', challenge.id),
|
||||
('end_date', '=', end_date),
|
||||
('state', '=', 'reached')
|
||||
], fields=['user_id'], groupby=['user_id'])
|
||||
for reach_goals_user in reached_goals:
|
||||
if reach_goals_user['user_id_count'] == len(challenge.line_ids):
|
||||
], groupby=['user_id'], aggregates=['__count'])
|
||||
for user, count in reached_goals:
|
||||
if count == len(challenge.line_ids):
|
||||
# the user has succeeded every assigned goal
|
||||
user = self.env['res.users'].browse(reach_goals_user['user_id'][0])
|
||||
if challenge.reward_realtime:
|
||||
badges = self.env['gamification.badge.user'].search_count([
|
||||
('challenge_id', '=', challenge.id),
|
||||
|
|
@ -689,22 +696,21 @@ class Challenge(models.Model):
|
|||
message_body = _("The challenge %s is finished.", challenge.name)
|
||||
|
||||
if rewarded_users:
|
||||
user_names = rewarded_users.name_get()
|
||||
message_body += _(
|
||||
"<br/>Reward (badge %(badge_name)s) for every succeeding user was sent to %(users)s.",
|
||||
message_body += Markup("<br/>") + _(
|
||||
"Reward (badge %(badge_name)s) for every succeeding user was sent to %(users)s.",
|
||||
badge_name=challenge.reward_id.name,
|
||||
users=", ".join(name for (user_id, name) in user_names)
|
||||
users=", ".join(rewarded_users.mapped('display_name'))
|
||||
)
|
||||
else:
|
||||
message_body += _("<br/>Nobody has succeeded to reach every goal, no badge is rewarded for this challenge.")
|
||||
message_body += Markup("<br/>") + _("Nobody has succeeded to reach every goal, no badge is rewarded for this challenge.")
|
||||
|
||||
# reward bests
|
||||
reward_message = _("<br/> %(rank)d. %(user_name)s - %(reward_name)s")
|
||||
reward_message = Markup("<br/> %(rank)d. %(user_name)s - %(reward_name)s")
|
||||
if challenge.reward_first_id:
|
||||
(first_user, second_user, third_user) = challenge._get_topN_users(MAX_VISIBILITY_RANKING)
|
||||
if first_user:
|
||||
challenge._reward_user(first_user, challenge.reward_first_id)
|
||||
message_body += _("<br/>Special rewards were sent to the top competing users. The ranking for this challenge is :")
|
||||
message_body += Markup("<br/>") + _("Special rewards were sent to the top competing users. The ranking for this challenge is:")
|
||||
message_body += reward_message % {
|
||||
'rank': 1,
|
||||
'user_name': first_user.name,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue