Files
odoo_source/addons/website_slides_survey/controllers/slides.py
T
Adrien Schoffeniels 2e0490beb5 [IMP] website_slides: improve website_slides_survey integration
SPECS

1. Change the default content of the modal opened after the installation
of a module

When the installation of a suggested module from the upload dialog is
completed, the page is reloaded and the upload dialog is opened on load.
Since the user installed the module to add content of the category related to
this module, it is more convenient to open the modal directly on this category.

2. Replace the notification displayed when the user creates a new
certification by a permanent button allowing to add questions

When a user creates a certification, he must then add questions to this
certification. Instead of showing a notification after the creation
proposing to add questions that was shown only once, a permanent button
has been added to the view of the certification so that anyone with the
sufficient access rights can add questions, at any time, from the certification
view.

Task-2727654

closes odoo/odoo#86721

Signed-off-by: Thibault Delavallee (tde) <tde@openerp.com>
2022-06-01 16:26:02 +02:00

166 lines
7.6 KiB
Python

# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
import werkzeug
import werkzeug.utils
import werkzeug.exceptions
from odoo import _
from odoo import http
from odoo.addons.http_routing.models.ir_http import slug
from odoo.exceptions import AccessError
from odoo.http import request
from odoo.osv import expression
from odoo.addons.website_slides.controllers.main import WebsiteSlides
class WebsiteSlidesSurvey(WebsiteSlides):
@http.route(['/slides_survey/slide/get_certification_url'], type='http', auth='user', website=True)
def slide_get_certification_url(self, slide_id, **kw):
fetch_res = self._fetch_slide(slide_id)
if fetch_res.get('error'):
raise werkzeug.exceptions.NotFound()
slide = fetch_res['slide']
if slide.channel_id.is_member:
slide.action_set_viewed()
certification_url = slide._generate_certification_url().get(slide.id)
if not certification_url:
raise werkzeug.exceptions.NotFound()
return request.redirect(certification_url)
@http.route(['/slides_survey/certification/search_read'], type='json', auth='user', methods=['POST'], website=True)
def slides_certification_search_read(self, fields):
can_create = request.env['survey.survey'].check_access_rights('create', raise_exception=False)
return {
'read_results': request.env['survey.survey'].search_read([('certification', '=', True)], fields),
'can_create': can_create,
}
# ------------------------------------------------------------
# Overrides
# ------------------------------------------------------------
@http.route(['/slides/add_slide'], type='json', auth='user', methods=['POST'], website=True)
def create_slide(self, *args, **post):
create_new_survey = post['slide_category'] == "certification" and post.get('survey') and not post['survey']['id']
linked_survey_id = int(post.get('survey', {}).get('id') or 0)
if create_new_survey:
# If user cannot create a new survey, no need to create the slide either.
if not request.env['survey.survey'].check_access_rights('create', raise_exception=False):
return {'error': _('You are not allowed to create a survey.')}
# Create survey first as certification slide needs a survey_id (constraint)
post['survey_id'] = request.env['survey.survey'].create({
'title': post['survey']['title'],
'questions_layout': 'page_per_question',
'is_attempts_limited': True,
'attempts_limit': 1,
'is_time_limited': False,
'scoring_type': 'scoring_without_answers',
'certification': True,
'scoring_success_min': 70.0,
'certification_mail_template_id': request.env.ref('survey.mail_template_certification').id,
}).id
elif linked_survey_id:
try:
request.env['survey.survey'].browse([linked_survey_id]).read(['title'])
except AccessError:
return {'error': _('You are not allowed to link a certification.')}
post['survey_id'] = post['survey']['id']
# Then create the slide
result = super(WebsiteSlidesSurvey, self).create_slide(*args, **post)
if post['slide_category'] == "certification":
# Set the url to redirect the user to the survey
result['url'] = '/slides/slide/%s?fullscreen=1' % (slug(request.env['slide.slide'].browse(result['slide_id']))),
return result
# Utils
# ---------------------------------------------------
def _slide_mark_completed(self, slide):
if slide.slide_category == 'certification':
raise werkzeug.exceptions.Forbidden(_("Certification slides are completed when the survey is succeeded."))
return super(WebsiteSlidesSurvey, self)._slide_mark_completed(slide)
def _get_valid_slide_post_values(self):
result = super(WebsiteSlidesSurvey, self)._get_valid_slide_post_values()
result.append('survey_id')
return result
# Profile
# ---------------------------------------------------
def _prepare_user_slides_profile(self, user):
values = super(WebsiteSlidesSurvey, self)._prepare_user_slides_profile(user)
values.update({
'certificates': self._get_users_certificates(user)[user.id]
})
return values
# All Users Page
# ---------------------------------------------------
def _prepare_all_users_values(self, users):
result = super(WebsiteSlidesSurvey, self)._prepare_all_users_values(users)
certificates_per_user = self._get_users_certificates(users)
for index, user in enumerate(users):
result[index].update({
'certification_count': len(certificates_per_user.get(user.id, []))
})
return result
def _get_users_certificates(self, users):
partner_ids = [user.partner_id.id for user in users]
domain = [
('slide_partner_id.partner_id', 'in', partner_ids),
('scoring_success', '=', True),
('slide_partner_id.survey_scoring_success', '=', True)
]
certificates = request.env['survey.user_input'].sudo().search(domain)
users_certificates = {
user.id: [
certificate for certificate in certificates if certificate.partner_id == user.partner_id
] for user in users
}
return users_certificates
# Badges & Ranks Page
# ---------------------------------------------------
def _prepare_ranks_badges_values(self, **kwargs):
""" Extract certification badges, to render them in ranks/badges page in another section.
Order them by number of granted users desc and show only badges linked to opened certifications."""
values = super(WebsiteSlidesSurvey, self)._prepare_ranks_badges_values(**kwargs)
# 1. Getting all certification badges, sorted by granted user desc
domain = expression.AND([[('survey_id', '!=', False)], self._prepare_badges_domain(**kwargs)])
certification_badges = request.env['gamification.badge'].sudo().search(domain)
# keep only the badge with challenge category = slides (the rest will be displayed under 'normal badges' section
certification_badges = certification_badges.filtered(
lambda b: 'slides' in b.challenge_ids.mapped('challenge_category'))
if not certification_badges:
return values
# 2. sort by granted users (done here, and not in search directly, because non stored field)
certification_badges = certification_badges.sorted("granted_users_count", reverse=True)
# 3. Remove certification badge from badges and keep only certification badge linked to opened survey
badges = values['badges'] - certification_badges
certification_badges = certification_badges.filtered(lambda b: b.survey_id.state == 'open')
# 4. Getting all course url for each badge
certification_slides = request.env['slide.slide'].sudo().search([('survey_id', 'in', certification_badges.mapped('survey_id').ids)])
certification_badge_urls = {slide.survey_id.certification_badge_id.id: slide.channel_id.website_url for slide in certification_slides}
# 5. Applying changes
values.update({
'badges': badges,
'certification_badges': certification_badges,
'certification_badge_urls': certification_badge_urls
})
return values