diff --git a/addons/survey/controllers/main.py b/addons/survey/controllers/main.py index 83e957d8b1e088343b9b4c87adc20f374f3beaf7..a7f7325a86f340d67c233820c7be4351a1daebe6 100644 --- a/addons/survey/controllers/main.py +++ b/addons/survey/controllers/main.py @@ -435,6 +435,16 @@ class Survey(http.Controller): # filter_finish: boolean => only finished surveys or not # + @http.route(['/survey/<model("survey.survey"):survey>/get_certification_preview'], type="http", auth="user", methods=['GET'], website=True) + def survey_get_certification_preview(self, survey, **kwargs): + if not request.env.user.has_group('survey.group_survey_user'): + raise werkzeug.exceptions.Forbidden() + + fake_user_input = survey._create_answer(user=request.env.user, test_entry=True) + response = self._generate_report(fake_user_input, download=False) + fake_user_input.sudo().unlink() + return response + @http.route(['/survey/<int:survey_id>/get_certification'], type='http', auth='user', methods=['GET'], website=True) def survey_get_certification(self, survey_id, **kwargs): """ The certification document can be downloaded as long as the user has succeeded the certification """ @@ -456,21 +466,13 @@ class Survey(http.Controller): if not succeeded_attempt: raise UserError(_("The user has not succeeded the certification")) - report_sudo = request.env.ref('survey.certification_report').sudo() - - report = report_sudo.render_qweb_pdf([succeeded_attempt.id], data={'report_type': 'pdf'})[0] - reporthttpheaders = [ - ('Content-Type', 'application/pdf'), - ('Content-Length', len(report)), - ] - reporthttpheaders.append(('Content-Disposition', content_disposition('Certification.pdf'))) - return request.make_response(report, headers=reporthttpheaders) + return self._generate_report(succeeded_attempt, download=True) def _prepare_result_dict(self, survey, current_filters=None): """Returns dictionary having values for rendering template""" current_filters = current_filters if current_filters else [] result = {'page_ids': []} - + # First append questions without page questions_without_page = [self._prepare_question_values(question,current_filters) for question in survey.question_ids if not question.page_id] if questions_without_page: @@ -621,3 +623,18 @@ class Survey(http.Controller): if len(answers_no_comment) == 1: answers_no_comment = answers_no_comment[0] return answers_no_comment, comment + + def _generate_report(self, user_input, download=True): + report = request.env.ref('survey.certification_report').sudo().render_qweb_pdf([user_input.id], data={'report_type': 'pdf'})[0] + + report_content_disposition = content_disposition('Certification.pdf') + if not download: + content_split = report_content_disposition.split(';') + content_split[0] = 'inline' + report_content_disposition = ';'.join(content_split) + + return request.make_response(report, headers=[ + ('Content-Type', 'application/pdf'), + ('Content-Length', len(report)), + ('Content-Disposition', report_content_disposition), + ]) diff --git a/addons/survey/models/survey_survey.py b/addons/survey/models/survey_survey.py index a63f12451e9c4abf306867cdd859e4d79bcf1aa0..135aa653acf147932900a2366b7d1571499ae9cc 100644 --- a/addons/survey/models/survey_survey.py +++ b/addons/survey/models/survey_survey.py @@ -88,6 +88,14 @@ class Survey(models.Model): 'mail.template', 'Email Template', domain="[('model', '=', 'survey.user_input')]", help="Automated email sent to the user when he succeeds the certification, containing his certification document.") + certification_report_layout = fields.Selection([ + ('modern_purple', 'Modern Purple'), + ('modern_blue', 'Modern Blue'), + ('modern_gold', 'Modern Gold'), + ('classic_purple', 'Classic Purple'), + ('classic_blue', 'Classic Blue'), + ('classic_gold', 'Classic Gold')], + string='Certification template', default='modern_purple') # Certification badge # certification_badge_id_dummy is used to have two different behaviours in the form view : # - If the certification badge is not set, show certification_badge_id and only display create option in the m2o @@ -539,6 +547,14 @@ class Survey(models.Model): action['context'] = ctx return action + def action_survey_preview_certification_template(self): + self.ensure_one() + return { + 'type': 'ir.actions.act_url', + 'target': '_blank', + 'url': '/survey/%s/get_certification_preview' % (self.id) + } + # ------------------------------------------------------------ # GRAPH / RESULTS # ------------------------------------------------------------ diff --git a/addons/survey/static/src/fonts/ETHOS-REGULAR.OTF b/addons/survey/static/src/fonts/ETHOS-REGULAR.OTF new file mode 100755 index 0000000000000000000000000000000000000000..7069cc84eedcd2a400ff2aeef0c496901256efa8 Binary files /dev/null and b/addons/survey/static/src/fonts/ETHOS-REGULAR.OTF differ diff --git a/addons/survey/static/src/fonts/Oswald-Light.ttf b/addons/survey/static/src/fonts/Oswald-Light.ttf new file mode 100755 index 0000000000000000000000000000000000000000..b210bd7f90664a29e4cb86a89e096b7d9d8f3e63 Binary files /dev/null and b/addons/survey/static/src/fonts/Oswald-Light.ttf differ diff --git a/addons/survey/static/src/fonts/TheSecret-Regular.ttf b/addons/survey/static/src/fonts/TheSecret-Regular.ttf new file mode 100644 index 0000000000000000000000000000000000000000..3c8f60b91018a98decc679601432b9309ed3c834 Binary files /dev/null and b/addons/survey/static/src/fonts/TheSecret-Regular.ttf differ diff --git a/addons/survey/static/src/img/certification_background.png b/addons/survey/static/src/img/certification_background.png deleted file mode 100644 index 966d05cf9033472a1881aeb7b1507f5b6d42d4f4..0000000000000000000000000000000000000000 Binary files a/addons/survey/static/src/img/certification_background.png and /dev/null differ diff --git a/addons/survey/static/src/img/certification_bg_classic_blue.jpg b/addons/survey/static/src/img/certification_bg_classic_blue.jpg new file mode 100644 index 0000000000000000000000000000000000000000..4145476d85dc0553235f69ab78be143c0d7f6462 Binary files /dev/null and b/addons/survey/static/src/img/certification_bg_classic_blue.jpg differ diff --git a/addons/survey/static/src/img/certification_bg_classic_default.jpg b/addons/survey/static/src/img/certification_bg_classic_default.jpg new file mode 100644 index 0000000000000000000000000000000000000000..b638bad1ea57d76791f8949528b7a442db1a237b Binary files /dev/null and b/addons/survey/static/src/img/certification_bg_classic_default.jpg differ diff --git a/addons/survey/static/src/img/certification_bg_classic_gold.jpg b/addons/survey/static/src/img/certification_bg_classic_gold.jpg new file mode 100644 index 0000000000000000000000000000000000000000..6e2fdba092150875721fadce4bf90020dbd87784 Binary files /dev/null and b/addons/survey/static/src/img/certification_bg_classic_gold.jpg differ diff --git a/addons/survey/static/src/img/certification_bg_modern.png b/addons/survey/static/src/img/certification_bg_modern.png new file mode 100644 index 0000000000000000000000000000000000000000..c0046186d4a885672d51fe53ad6fa2712f6ccb3e Binary files /dev/null and b/addons/survey/static/src/img/certification_bg_modern.png differ diff --git a/addons/survey/static/src/img/certification_seal.svg b/addons/survey/static/src/img/certification_seal.svg new file mode 100644 index 0000000000000000000000000000000000000000..2b0b580323c1474fa5240667ad217e58926ec558 --- /dev/null +++ b/addons/survey/static/src/img/certification_seal.svg @@ -0,0 +1 @@ +<svg width="106" height="106" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><defs><linearGradient x1="50%" y1="0%" x2="50%" y2="100%" id="a"><stop stop-color="#C80000" offset="0%"/><stop stop-color="#8F0000" offset="100%"/></linearGradient><path d="M51.41 101.824l-1.112 1.459a2 2 0 0 1-3.368-.295l-.842-1.63a2 2 0 0 0-3.133-.552l-1.348 1.243a2 2 0 0 1-3.265-.875l-.546-1.75a2 2 0 0 0-2.99-1.089l-1.543.99a2 2 0 0 1-3.064-1.428l-.233-1.819a2 2 0 0 0-2.756-1.59l-1.692.707a2 2 0 0 1-2.769-1.94l.086-1.831a2 2 0 0 0-2.437-2.045l-1.79.403a2 2 0 0 1-2.39-2.39l.403-1.79a2 2 0 0 0-2.045-2.437l-1.832.086a2 2 0 0 1-1.939-2.77l.708-1.691a2 2 0 0 0-1.591-2.756l-1.82-.233a2 2 0 0 1-1.428-3.064l.99-1.543a2 2 0 0 0-1.087-2.99l-1.751-.546a2 2 0 0 1-.875-3.265l1.243-1.348a2 2 0 0 0-.552-3.133l-1.63-.842a2 2 0 0 1-.295-3.368l1.46-1.111a2 2 0 0 0 0-3.182l-1.46-1.111a2 2 0 0 1 .295-3.368l1.63-.842a2 2 0 0 0 .552-3.133l-1.243-1.348a2 2 0 0 1 .875-3.265l1.75-.546a2 2 0 0 0 1.089-2.99l-.99-1.543a2 2 0 0 1 1.428-3.064l1.819-.233a2 2 0 0 0 1.59-2.756l-.707-1.692a2 2 0 0 1 1.94-2.769l1.831.086a2 2 0 0 0 2.045-2.437l-.403-1.79a2 2 0 0 1 2.39-2.39l1.79.403a2 2 0 0 0 2.437-2.045l-.086-1.832a2 2 0 0 1 2.77-1.939l1.691.708a2 2 0 0 0 2.756-1.591l.233-1.82a2 2 0 0 1 3.064-1.428l1.543.99a2 2 0 0 0 2.99-1.087l.546-1.751a2 2 0 0 1 3.265-.875l1.348 1.243a2 2 0 0 0 3.133-.552l.842-1.63a2 2 0 0 1 3.368-.295l1.111 1.46a2 2 0 0 0 3.182 0l1.111-1.46a2 2 0 0 1 3.368.295l.842 1.63a2 2 0 0 0 3.133.552l1.348-1.243a2 2 0 0 1 3.265.875l.546 1.75a2 2 0 0 0 2.99 1.089l1.543-.99a2 2 0 0 1 3.064 1.428l.233 1.819a2 2 0 0 0 2.756 1.59l1.692-.707a2 2 0 0 1 2.769 1.94l-.086 1.831a2 2 0 0 0 2.437 2.045l1.79-.403a2 2 0 0 1 2.39 2.39l-.403 1.79a2 2 0 0 0 2.045 2.437l1.832-.086a2 2 0 0 1 1.939 2.77l-.708 1.691a2 2 0 0 0 1.591 2.756l1.82.233a2 2 0 0 1 1.428 3.064l-.99 1.543a2 2 0 0 0 1.087 2.99l1.751.546a2 2 0 0 1 .875 3.265l-1.243 1.348a2 2 0 0 0 .552 3.133l1.63.842a2 2 0 0 1 .295 3.368l-1.46 1.111a2 2 0 0 0 0 3.182l1.46 1.111a2 2 0 0 1-.295 3.368l-1.63.842a2 2 0 0 0-.552 3.133l1.243 1.348a2 2 0 0 1-.875 3.265l-1.75.546a2 2 0 0 0-1.089 2.99l.99 1.543a2 2 0 0 1-1.428 3.064l-1.819.233a2 2 0 0 0-1.59 2.756l.707 1.692a2 2 0 0 1-1.94 2.769l-1.831-.086a2 2 0 0 0-2.045 2.437l.403 1.79a2 2 0 0 1-2.39 2.39l-1.79-.403a2 2 0 0 0-2.437 2.045l.086 1.832a2 2 0 0 1-2.77 1.939l-1.691-.708a2 2 0 0 0-2.756 1.591l-.233 1.82a2 2 0 0 1-3.064 1.428l-1.543-.99a2 2 0 0 0-2.99 1.087l-.546 1.751a2 2 0 0 1-3.265.875l-1.348-1.243a2 2 0 0 0-3.133.552l-.842 1.63a2 2 0 0 1-3.368.295l-1.111-1.46a2 2 0 0 0-3.182 0z" id="b"/><filter x=".9%" y=".9%" width="98.2%" height="98.2%" filterUnits="objectBoundingBox" id="c"><feGaussianBlur stdDeviation=".5" in="SourceAlpha" result="shadowBlurInner1"/><feOffset dy="1" in="shadowBlurInner1" result="shadowOffsetInner1"/><feComposite in="shadowOffsetInner1" in2="SourceAlpha" operator="arithmetic" k2="-1" k3="1" result="shadowInnerInner1"/><feColorMatrix values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0.785265516 0" in="shadowInnerInner1" result="shadowMatrixInner1"/><feOffset dy="-1" in="SourceAlpha" result="shadowOffsetInner2"/><feComposite in="shadowOffsetInner2" in2="SourceAlpha" operator="arithmetic" k2="-1" k3="1" result="shadowInnerInner2"/><feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.291220498 0" in="shadowInnerInner2" result="shadowMatrixInner2"/><feMerge><feMergeNode in="shadowMatrixInner1"/><feMergeNode in="shadowMatrixInner2"/></feMerge></filter><radialGradient fx="50%" fy="50%" id="d"><stop stop-color="#C40505" offset="0%"/><stop stop-color="#8D0101" offset="100%"/></radialGradient></defs><g fill="none" fill-rule="evenodd"><use fill="url(#a)" xlink:href="#b"/><use fill="#000" filter="url(#c)" xlink:href="#b"/><circle fill="url(#d)" cx="53" cy="53" r="42"/></g></svg> \ No newline at end of file diff --git a/addons/survey/static/src/scss/survey_reports.scss b/addons/survey/static/src/scss/survey_reports.scss index 94e00e729af48b4f6215271fb080d7aeb9af31ab..0710fefffbcbd398eff2d8f7ec9c3fc75b257714 100644 --- a/addons/survey/static/src/scss/survey_reports.scss +++ b/addons/survey/static/src/scss/survey_reports.scss @@ -1,20 +1,37 @@ -.certification-wrapper { - background: url(/survey/static/src/img/certification_background.png) no-repeat; +@font-face { + font-family: certification-cursive; + src: url(/survey/static/src/fonts/TheSecret-Regular.ttf); +} +@font-face { + font-family: certification-serif; + src: url(/survey/static/src/fonts/ETHOS-REGULAR.OTF); +} +@font-face { + font-family: certification-modern; + src: url(/survey/static/src/fonts/Oswald-Light.ttf); +} + +#o_survey_certification.certification-wrapper { + width: 250mm; + height: 280mm; + display: flex; background-size: 100% 100%; - height: 610px; - width: 860px; + background-color: #875A7B; - .certification { - margin-left: 350px; - padding-top: 140px; - width: 510px; - text-align: center; + &.blue { + background-color: #4761e2; + } - h2 { - color: #876B81; - } + &.gold { + background-color: #af881a; + } - &.test-entry::after { + .certification { + position: relative; + width: 100%; + height: 100%; + + .test-entry { top: 0px; left: 0px; position: absolute; @@ -23,6 +40,158 @@ width: 860px; background: url(/survey/static/src/img/watermark.png) no-repeat; background-size: 100% 100%; + background-position: center; + } + } + + &.classic { + padding: 5mm; + background-image: url(/survey/static/src/img/certification_bg_classic_default.jpg); + color: #3e2e3a; + + &.blue { + background-image: url(/survey/static/src/img/certification_bg_classic_blue.jpg); + color: #272d4f; + } + + &.gold { + background-image: url(/survey/static/src/img/certification_bg_classic_gold.jpg); + color: #5A4721; + } + + .certification { + padding: 20mm; + font-family: certification-serif, serif; + font-family: Times; + text-align: center; + color: inherit; + + .certification-name-label { + padding: 5mm 0 8mm; + } + + .certification-name { + font-size: 45pt; + line-height: 0.9; + text-transform: uppercase; + letter-spacing: 0.2mm; + } + + .user-name { + padding-bottom: 6mm; + padding-top: 3mm; + font-family: certification-cursive, cursive; + letter-spacing: -0.2mm; + word-spacing: 0.2mm; + font-size: 60pt; + } + + hr { + border-color: inherit; + margin: 15mm auto; + opacity: 0.6; + width: 50mm; + + &.small { + margin: 2mm auto; + } + } + + .certification-description, .certification-date { + padding: 5mm 40mm 10mm; + } + + .certificate-signature { + position: absolute; + bottom: 10mm; + right: 10mm; + left: 10mm; + font-size: 14pt; + + img { + max-width: 40mm; + max-height: 40mm; + } + } + } + } + + &.modern { + background-image: url(/survey/static/src/img/certification_bg_modern.png); + + .certification { + padding-left: 40mm; + padding-right: 40mm; + font-family: certification-modern, sans-serif; + color: #223541; + + .certification-bg-dark { + display: inline-block; + background-color: #223541; + color: white; + } + + .certification-top { + .certification-bg-dark { + margin-bottom: 10mm; + padding: 20mm 6mm 5mm; + text-align: center; + width: 56mm; + } + + .certification-company-wrapper { + background-color: rgba(white, 0.9); + padding: 1mm 2mm; + + img { + max-width: 40mm; + max-height: 30mm; + } + } + + .certification-name { + text-transform: uppercase; + font-size: 40pt; + line-height: 0.9; + } + } + + .certification-bottom { + padding: 60mm 0 10mm; + font-size: 16pt; + + .user-name { + margin-bottom: 20mm; + font-family: certification-cursive, cursive; + font-size: 50pt; + } + + .certification-bottom-group { + position: absolute; + bottom: 0; + right: 40mm; + left: 40mm; + top: 220mm; + + > div { + display: inline-block; + height: 100%; + float: left; + bottom: 0; + top: 0; + } + + .certification-bg-dark { + width: 56mm; + max-height: 100%; + } + + .certification-date { + padding-right: 30mm; + padding-left: 15mm; + } + } + } } } } diff --git a/addons/survey/views/survey_report_templates.xml b/addons/survey/views/survey_report_templates.xml index 9d9190b547a339b7d021ebf436c3ad0afc75a415..85d8e933006a1cc4af31e7dd0f98e27b4af7176c 100644 --- a/addons/survey/views/survey_report_templates.xml +++ b/addons/survey/views/survey_report_templates.xml @@ -1,35 +1,79 @@ <?xml version="1.0" encoding="utf-8"?> <odoo> -<data> - <template id="certification_report_view"> - <t t-set="data_report_landscape" t-value="True"/> - <t t-set="full_width" t-value="True"/> - <t t-call="web.html_container"> - <t t-foreach="docs" t-as="user_input"> - <div t-att-data-oe-model="user_input._name" t-att-data-oe-id="user_input.id" class="article certification-wrapper"> - <div t-attf-class="certification #{'test-entry' if user_input.test_entry else ''}"> - <h2> - <span t-field="user_input.survey_id.create_uid.company_id.display_name"/> - </h2> - <p>Certifies that</p> - <h2> - <span t-esc="user_input.partner_id.name or user_input.email"/> - </h2> - <!-- You should not print a certificate if failed :) --> - <p t-if="user_input.quizz_passed">Successfully achieved</p> - <p t-if="not user_input.quizz_passed">Successfully failed</p> - <h3> - <span t-field="user_input.survey_id.display_name"/> - </h3> - <p> - <strong t-if="user_input.quizz_passed">Date of Certification:</strong> - <strong t-if="not user_input.quizz_passed">Date of Failure:</strong> - <span t-field="user_input.create_date"/> - </p> + <data> + <template id="certification_report_view_modern"> + <!-- Style classes to be applyed to '#o_survey_certification': [no class](purple), gold, blue --> + <div id="o_survey_certification" t-att-data-oe-model="user_input._name" t-att-data-oe-id="user_input.id" t-att-class="'article certification-wrapper modern %s' % layout_color"> + <div class="certification"> + <div t-if="user_input.test_entry" class="test-entry"/> + <div class="certification-top"> + <div class="certification-bg-dark"> + <div class="certification-company-wrapper" t-field="user_input.survey_id.create_uid.company_id.logo" t-options="{'widget': 'image'}" role="img"/> + </div> + <div class="certification-name" t-field="user_input.survey_id.display_name"/> + </div> + + <div class="certification-bottom"> + <h5 class="user-name-label">This Certificate is Presented to</h5> + <div class="user-name" t-esc="user_input.partner_id.name or user_input.email"/> + + <div class="certification-description"> + <span t-field="user_input.survey_id.create_uid.company_id.display_name"/> is proud to award this certificate to + <span t-esc="user_input.partner_id.name or user_input.email"/> for gratuating from <span t-field="user_input.survey_id.display_name"/>. + </div> + + <div class="certification-bottom-group"> + <div class="certification-bg-dark"/> + <div class="certification-date"> + <h5>Date</h5> + <h5 t-field="user_input.create_date" t-options='{"widget": "date"}'/> + </div> + <div class="certification-seal"> + <img src="/survey/static/src/img/certification_seal.svg" alt="Certification Seal" role="image"/> + </div> + </div> + </div> + </div> + </div> + </template> + + <template id="certification_report_view_classic"> + <!-- Style classes to be applyed to '#o_survey_certification': [no class](purple), gold, blue --> + <div id="o_survey_certification" t-att-data-oe-model="user_input._name" t-att-data-oe-id="user_input.id" t-att-class="'article certification-wrapper classic %s' % layout_color"> + <div class="certification"> + <div t-if="user_input.test_entry" class="test-entry"/> + <h5 class="certification-name-label">CERTIFICATE</h5> + <div class="certification-name" t-field="user_input.survey_id.display_name"/> + <hr/> + + <h5>This Certificate is Presented to</h5> + <div class="user-name" t-esc="user_input.partner_id.name or user_input.email"/> + <hr class="small"/> + + <div class="certification-description"> + <span t-field="user_input.survey_id.create_uid.company_id.display_name"/> is proud to award this certificate to + <span t-esc="user_input.partner_id.name or user_input.email"/> for graduating from <span t-field="user_input.survey_id.display_name"/>. + </div> + + <div class="certification-date" t-field="user_input.create_date" t-options='{"widget": "date"}'/> + <img src="/survey/static/src/img/certification_seal.svg" alt="Certification Seal" role="img"/> + + <div class="certificate-signature"> + <span t-field="user_input.survey_id.create_uid.company_id.logo" t-options="{'widget': 'image'}" role="img"/> </div> </div> + </div> + </template> + + <template id="certification_report_view"> + <t t-call="web.html_container"> + <t t-foreach="docs" t-as="user_input"> + <t t-set="layout_values" t-value="user_input.survey_id.certification_report_layout.split('_') if user_input.survey_id.certification_report_layout else ['modern', 'purple']"/> + <t t-set="layout_template" t-value="'survey.certification_report_view_%s' % (layout_values[0])"/> + <t t-set="layout_color" t-value="layout_values[1]"/> + <t t-call="{{layout_template}}"/> + </t> </t> - </t> - </template> -</data> + </template> + </data> </odoo> diff --git a/addons/survey/views/survey_survey_views.xml b/addons/survey/views/survey_survey_views.xml index ac63a3af39a9c72fdf0eff6041a5fa7f6b6f892a..e728e29a84ff12f1d70cbd4add8090142c1965a7 100644 --- a/addons/survey/views/survey_survey_views.xml +++ b/addons/survey/views/survey_survey_views.xml @@ -98,6 +98,13 @@ <field name="passing_score" attrs="{'invisible': [('scoring_type', '=', 'no_scoring')]}" /> <field name="certificate" attrs="{'invisible': [('scoring_type', '=', 'no_scoring')]}" /> <field name="certification_mail_template_id" attrs="{'invisible': [('certificate', '=', False)]}" /> + <label for="certification_report_layout" string="Certification Template" attrs="{'invisible': [('certificate', '=', False)]}"/> + <div attrs="{'invisible': [('certificate', '=', False)]}" class="d-flex"> + <field name="certification_report_layout" class="oe_inline"/> + <button name="action_survey_preview_certification_template" + string="Preview" type="object" + icon="fa-external-link" target="_blank" class="btn-link pt-0"/> + </div> <field name="certification_give_badge" attrs="{'invisible': ['|', ('certificate', '=', False), ('users_login_required', '=', False)]}" /> <field name="certification_badge_id" attrs="{'invisible': ['|', ('certification_give_badge', '=', False), ('certification_badge_id', '!=', False)]}" domain="[('survey_id', '=', active_id), ('survey_id', '!=', False)]"