| @ -0,0 +1,47 @@ | |||||
|  | .. image:: https://img.shields.io/badge/licence-OPL--1-red.svg | ||||
|  |     :target: https://www.odoo.com/documentation/16.0/legal/licenses.html#odoo-apps | ||||
|  |     :alt: License: OPL-1 | ||||
|  | 
 | ||||
|  | Enhanced Survey Management | ||||
|  | ========================== | ||||
|  | * Enhance your survey management with this module. | ||||
|  | 
 | ||||
|  | Installation | ||||
|  | ============ | ||||
|  |     - www.odoo.com/documentation/16.0/setup/install.html | ||||
|  |     - Install our custom addon | ||||
|  | 
 | ||||
|  | License | ||||
|  | ------- | ||||
|  | Odoo Proprietary License v1.0 (OPL-1) | ||||
|  | (https://www.odoo.com/documentation/16.0/legal/licenses.html#odoo-apps) | ||||
|  | 
 | ||||
|  | Company | ||||
|  | ------- | ||||
|  | * `Cybrosys Techno Solutions <https://cybrosys.com/>`__ | ||||
|  | 
 | ||||
|  | Credits | ||||
|  | ------- | ||||
|  | * Developers: (V16) Mohammed Savad, Ahammed Harshad, Gee Paul Joby, Nihala Jebin, | ||||
|  | Contact: odoo@cybrosys.com | ||||
|  | 
 | ||||
|  | Contacts | ||||
|  | -------- | ||||
|  | * Mail Contact : odoo@cybrosys.com | ||||
|  | * Website : https://cybrosys.com | ||||
|  | 
 | ||||
|  | Bug Tracker | ||||
|  | ----------- | ||||
|  | Bugs are tracked on GitHub Issues. In case of trouble, please check there if your issue has already been reported. | ||||
|  | 
 | ||||
|  | Maintainer | ||||
|  | ========== | ||||
|  | .. image:: https://cybrosys.com/images/logo.png | ||||
|  |    :target: https://cybrosys.com | ||||
|  | This module is maintained by Cybrosys Technologies. | ||||
|  | 
 | ||||
|  | For support and more information, please visit https://www.cybrosys.com | ||||
|  | 
 | ||||
|  | Further information | ||||
|  | =================== | ||||
|  | HTML Description: `<static/description/index.html>`__ | ||||
| @ -0,0 +1,23 @@ | |||||
|  | # -*- coding: utf-8 -*- | ||||
|  | ############################################################################### | ||||
|  | # | ||||
|  | #    Cybrosys Technologies Pvt. Ltd. | ||||
|  | # | ||||
|  | #    Copyright (C) 2023-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) | ||||
|  | #    Author: Mohammed Savad, Ahammed Harshad  (odoo@cybrosys.com) | ||||
|  | # | ||||
|  | #    This program is under the terms of the Odoo Proprietary License v1.0(OPL-1) | ||||
|  | #    It is forbidden to publish, distribute, sublicense, or sell copies of the | ||||
|  | #    Software or modified copies of the Software. | ||||
|  | # | ||||
|  | #    THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
|  | #    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
|  | #    FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL | ||||
|  | #    THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,DAMAGES OR OTHER | ||||
|  | #    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,ARISING | ||||
|  | #    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | ||||
|  | #    DEALINGS IN THE SOFTWARE. | ||||
|  | # | ||||
|  | ############################################################################### | ||||
|  | from . import controllers | ||||
|  | from . import models | ||||
| @ -0,0 +1,69 @@ | |||||
|  | # -*- coding: utf-8 -*- | ||||
|  | ############################################################################### | ||||
|  | # | ||||
|  | #    Cybrosys Technologies Pvt. Ltd. | ||||
|  | # | ||||
|  | #    Copyright (C) 2023-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) | ||||
|  | #    Author: Mohammed Savad, Ahammed Harshad  (odoo@cybrosys.com) | ||||
|  | # | ||||
|  | #    This program is under the terms of the Odoo Proprietary License v1.0 OPL-1) | ||||
|  | #    It is forbidden to publish, distribute, sublicense, or sell copies of the | ||||
|  | #    Software or modified copies of the Software. | ||||
|  | # | ||||
|  | #    THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
|  | #    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
|  | #    FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL | ||||
|  | #    THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,DAMAGES OR OTHER | ||||
|  | #    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,ARISING | ||||
|  | #    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | ||||
|  | #    DEALINGS IN THE SOFTWARE. | ||||
|  | # | ||||
|  | ############################################################################### | ||||
|  | { | ||||
|  |     'name': 'Enhanced Survey Management', | ||||
|  |     'version': '16.0.1.0.0', | ||||
|  |     'category': 'Extra Tools', | ||||
|  |     'summary': 'Enhance your survey management with new question kinds and more', | ||||
|  |     'description': 'Upgrade your survey management capabilities with the ' | ||||
|  |                    'addition of versatile question types. ' | ||||
|  |                    'Capture specific timeframes by incorporating questions ' | ||||
|  |                    'about the month, week, or range, ' | ||||
|  |                    'enabling finer data analysis. ' | ||||
|  |                    'Furthermore, enhance data collection by allowing ' | ||||
|  |                    'respondents to upload files, ' | ||||
|  |                    'fostering a more comprehensive understanding of their ' | ||||
|  |                    'experiences.' | ||||
|  |                    'Explore these new question types and optimize your survey ' | ||||
|  |                    'strategy for enhanced insights.', | ||||
|  |     'author': 'Cybrosys Techno Solutions', | ||||
|  |     'company': 'Cybrosys Techno Solutions', | ||||
|  |     'maintainer': 'Cybrosys Techno Solutions', | ||||
|  |     'website': 'https://www.cybrosys.com', | ||||
|  |     'images': [ | ||||
|  |         'static/description/banner.png', | ||||
|  |         'static/description/icon.png', | ||||
|  |     ], | ||||
|  |     'depends': ['base', 'survey', 'website'], | ||||
|  |     'data': [ | ||||
|  |         'data/enhanced_survey_management_data.xml', | ||||
|  |         'security/ir.model.access.csv', | ||||
|  |         'views/survey_templates.xml', | ||||
|  |         'views/survey_question_views.xml', | ||||
|  |         'views/survey_input_print_templates.xml', | ||||
|  |         'views/survey_portal_templates.xml', | ||||
|  |         'views/survey_user_views.xml', | ||||
|  |         'views/survey_survey_views.xml' | ||||
|  |     ], | ||||
|  |     'assets': { | ||||
|  |         'web.assets_frontend': [ | ||||
|  |             'https://cdn.jsdelivr.net/npm/flatpickr/dist/flatpickr.min.css', | ||||
|  |             'https://cdn.jsdelivr.net/npm/flatpickr@4.6.3/dist/flatpickr.min.js', | ||||
|  |             'enhanced_survey_management/static/src/js/survey_form.js', | ||||
|  |             'enhanced_survey_management/static/src/js/survey_submit.js', | ||||
|  |         ] | ||||
|  |     }, | ||||
|  |     'license': 'OPL-1', | ||||
|  |     'installable': True, | ||||
|  |     'auto_install': False, | ||||
|  |     'application': False, | ||||
|  | } | ||||
| @ -0,0 +1,24 @@ | |||||
|  | # -*- coding: utf-8 -*- | ||||
|  | ############################################################################### | ||||
|  | # | ||||
|  | #    Cybrosys Technologies Pvt. Ltd. | ||||
|  | # | ||||
|  | #    Copyright (C) 2023-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) | ||||
|  | #    Author: Mohammed Savad, Ahammed Harshad  (odoo@cybrosys.com) | ||||
|  | # | ||||
|  | #    This program is under the terms of the Odoo Proprietary License v1.0(OPL-1) | ||||
|  | #    It is forbidden to publish, distribute, sublicense, or sell copies of the | ||||
|  | #    Software or modified copies of the Software. | ||||
|  | # | ||||
|  | #    THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
|  | #    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
|  | #    FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL | ||||
|  | #    THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,DAMAGES OR OTHER | ||||
|  | #    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,ARISING | ||||
|  | #    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | ||||
|  | #    DEALINGS IN THE SOFTWARE. | ||||
|  | # | ||||
|  | ############################################################################### | ||||
|  | from . import enhanced_survey_management | ||||
|  | from . import website_visibility | ||||
|  | from . import xlsx_main | ||||
| @ -0,0 +1,120 @@ | |||||
|  | # -*- coding: utf-8 -*- | ||||
|  | ############################################################################### | ||||
|  | # | ||||
|  | #    Cybrosys Technologies Pvt. Ltd. | ||||
|  | # | ||||
|  | #    Copyright (C) 2023-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) | ||||
|  | #    Author: Mohammed Savad, Ahammed Harshad  (odoo@cybrosys.com) | ||||
|  | # | ||||
|  | #    This program is under the terms of the Odoo Proprietary License v1.0(OPL-1) | ||||
|  | #    It is forbidden to publish, distribute, sublicense, or sell copies of the | ||||
|  | #    Software or modified copies of the Software. | ||||
|  | # | ||||
|  | #    THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
|  | #    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
|  | #    FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL | ||||
|  | #    THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,DAMAGES OR OTHER | ||||
|  | #    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,ARISING | ||||
|  | #    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | ||||
|  | #    DEALINGS IN THE SOFTWARE. | ||||
|  | # | ||||
|  | ############################################################################### | ||||
|  | from odoo.addons.portal.controllers.portal import CustomerPortal | ||||
|  | from odoo import http | ||||
|  | from odoo.http import request | ||||
|  | 
 | ||||
|  | 
 | ||||
|  | class SurveyAnswerPortal(CustomerPortal): | ||||
|  |     """ Inherited CustomerPortal to add new portal view""" | ||||
|  | 
 | ||||
|  |     def _prepare_home_portal_values(self, counters): | ||||
|  |         """ Function : Prepare portal values for attended survey count | ||||
|  |             @return : Survey counts | ||||
|  |         """ | ||||
|  |         values = super(SurveyAnswerPortal, self)._prepare_home_portal_values( | ||||
|  |             counters) | ||||
|  |         if 'survey_count' in counters: | ||||
|  |             values['survey_count'] = request.env[ | ||||
|  |                 'survey.survey'].sudo().search_count([ | ||||
|  |                 ('user_id', '=', request.uid), ('visibility', '=', True)]) | ||||
|  |         return values | ||||
|  | 
 | ||||
|  | 
 | ||||
|  | class SurveyPortalView(http.Controller): | ||||
|  |     """ Survey portal controller """ | ||||
|  | 
 | ||||
|  |     @http.route('/my/survey/ans', type='http', auth="public", | ||||
|  |                 website=True) | ||||
|  |     def portal_my_survey(self): | ||||
|  |         """ Controller to send survey data to portal """ | ||||
|  |         survey = request.env['survey.survey'].sudo().search( | ||||
|  |             [('user_id', '=', request.uid)]) | ||||
|  |         values = { | ||||
|  |             'survey_list': [{'id': rec.id, | ||||
|  |                              'survey': rec.title, | ||||
|  |                              'user_id': rec.user_id.name, | ||||
|  |                              'email': rec.user_id.partner_id.email, | ||||
|  |                              'status': rec.session_state | ||||
|  |                              } for rec in survey if rec.visibility], | ||||
|  |             'page_name': 'survey' | ||||
|  |         } | ||||
|  |         return request.render( | ||||
|  |             """enhanced_survey_management.portal_survey_result""", values) | ||||
|  | 
 | ||||
|  |     @http.route('/my/survey/<int:survey_id>', type="http", auth="public", | ||||
|  |                 website=True) | ||||
|  |     def survey_view(self, survey_id): | ||||
|  |         """ Controller function to send specific survey data """ | ||||
|  |         question_list = [] | ||||
|  |         survey_questions_line = request.env[ | ||||
|  |             'survey.user_input.line'].sudo().search([ | ||||
|  |             ('survey_id', '=', survey_id)]) | ||||
|  |         survey = request.env['survey.survey'].sudo().browse(survey_id) | ||||
|  |         for res in survey_questions_line: | ||||
|  |             question_list.append({ | ||||
|  |                 'id': res.question_id.id, | ||||
|  |                 'questions': res.question_id.title, | ||||
|  |                 'section': res.create_date, | ||||
|  |                 'question_type': res.question_id.question_type, | ||||
|  |                 'score': res.answer_score, | ||||
|  |                 'answer': res.display_name, | ||||
|  |             }) | ||||
|  |         values = { | ||||
|  |             'survey_questions': question_list, | ||||
|  |             'survey': survey.title, | ||||
|  |             'survey_date': survey.create_date, | ||||
|  |             'name': survey.user_id.partner_id.name, | ||||
|  |             'email': survey.user_id.partner_id.email, | ||||
|  |             'access_token': survey.access_token, | ||||
|  |             'page_name': 'survey', | ||||
|  |             'survey_boolean': True | ||||
|  |         } | ||||
|  |         return request.render( | ||||
|  |             "enhanced_survey_management.portal_survey_result_view", values) | ||||
|  | 
 | ||||
|  | 
 | ||||
|  | class SurveyLoadContent(http.Controller): | ||||
|  |     """Controller to load country and state to the survey""" | ||||
|  | 
 | ||||
|  |     @http.route('/survey/load_country', type="json", auth="public", | ||||
|  |                 website=True, csrf=False) | ||||
|  |     def load_country(self): | ||||
|  |         """Function to return country names for question type country""" | ||||
|  |         country_ids = request.env['res.country'].sudo().search([]) | ||||
|  |         return { | ||||
|  |             'id': country_ids.mapped('id'), | ||||
|  |             'name': country_ids.mapped('name'), | ||||
|  |         } | ||||
|  | 
 | ||||
|  |     @http.route('/survey/load_states', type="json", auth="public", | ||||
|  |                 website=True, | ||||
|  |                 csrf=False) | ||||
|  |     def load_states(self, **kwargs): | ||||
|  |         """Function to return state names based on country""" | ||||
|  |         state_ids = request.env['res.country.state'].sudo().search([ | ||||
|  |             ('country_id.name', '=', kwargs['country_id']) | ||||
|  |         ]) | ||||
|  |         return { | ||||
|  |             'id': state_ids.mapped('id'), | ||||
|  |             'name': state_ids.mapped('name'), | ||||
|  |         } | ||||
| @ -0,0 +1,44 @@ | |||||
|  | # -*- coding: utf-8 -*- | ||||
|  | ############################################################################### | ||||
|  | # | ||||
|  | #    Cybrosys Technologies Pvt. Ltd. | ||||
|  | # | ||||
|  | #    Copyright (C) 2023-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) | ||||
|  | #    Author: Mohammed Savad, Ahammed Harshad (odoo@cybrosys.com) | ||||
|  | # | ||||
|  | #    This program is under the terms of the Odoo Proprietary License v1.0(OPL-1) | ||||
|  | #    It is forbidden to publish, distribute, sublicense, or sell copies of the | ||||
|  | #    Software or modified copies of the Software. | ||||
|  | # | ||||
|  | #    THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
|  | #    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
|  | #    FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL | ||||
|  | #    THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,DAMAGES OR OTHER | ||||
|  | #    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,ARISING | ||||
|  | #    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | ||||
|  | #    DEALINGS IN THE SOFTWARE. | ||||
|  | # | ||||
|  | ############################################################################### | ||||
|  | from odoo import http | ||||
|  | from odoo.http import request | ||||
|  | 
 | ||||
|  | 
 | ||||
|  | class WebsiteView(http.Controller): | ||||
|  |     """Inherited http.Controller to add custom route""" | ||||
|  | 
 | ||||
|  |     @http.route('/public/survey', type='http', auth="public", | ||||
|  |                 website=True) | ||||
|  |     def public_user_access(self): | ||||
|  |         """ Controller function to access survey from website """ | ||||
|  |         survey = request.env['survey.survey'].sudo().search( | ||||
|  |             [('access_mode', '=', 'website')]) | ||||
|  |         values = { | ||||
|  |             'survey_list': [{ | ||||
|  |                 'title': rec.title, | ||||
|  |                 'attempts': rec.attempts_limit, | ||||
|  |                 'date': rec.create_date, | ||||
|  |                 'access_token': rec.access_token | ||||
|  |             } for rec in survey], | ||||
|  |         } | ||||
|  |         return request.render("enhanced_survey_management.survey_visibility", | ||||
|  |                               values) | ||||
| @ -0,0 +1,87 @@ | |||||
|  | # -*- coding: utf-8 -*- | ||||
|  | ############################################################################### | ||||
|  | # | ||||
|  | #    Cybrosys Technologies Pvt. Ltd. | ||||
|  | # | ||||
|  | #    Copyright (C) 2023-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) | ||||
|  | #    Author: Mohammed Savad, Ahammed Harshad  (odoo@cybrosys.com) | ||||
|  | # | ||||
|  | #    This program is under the terms of the Odoo Proprietary License v1.0(OPL-1) | ||||
|  | #    It is forbidden to publish, distribute, sublicense, or sell copies of the | ||||
|  | #    Software or modified copies of the Software. | ||||
|  | # | ||||
|  | #    THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
|  | #    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
|  | #    FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL | ||||
|  | #    THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,DAMAGES OR OTHER | ||||
|  | #    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,ARISING | ||||
|  | #    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | ||||
|  | #    DEALINGS IN THE SOFTWARE. | ||||
|  | # | ||||
|  | ############################################################################### | ||||
|  | import io | ||||
|  | from odoo import http | ||||
|  | from odoo.http import content_disposition, request | ||||
|  | from odoo.tools.misc import xlsxwriter | ||||
|  | 
 | ||||
|  | 
 | ||||
|  | class XlsxReportController(http.Controller): | ||||
|  |     """Inherited http.Controller to add custom route""" | ||||
|  | 
 | ||||
|  |     @http.route('/xlsx_report/<model("survey.survey"):survey_id>', | ||||
|  |                 type='http', auth='user', csrf=False) | ||||
|  |     def get_report_xlsx(self, survey_id=None, **args): | ||||
|  |         """ Function to create and print XLSX report""" | ||||
|  |         user_input_ids = request.env['survey.user_input'].search( | ||||
|  |             [("survey_id", '=', survey_id.id)]) | ||||
|  |         answers, title = [], '' | ||||
|  |         for rec in user_input_ids: | ||||
|  |             for res in rec: | ||||
|  |                 for new in res.user_input_line_ids: | ||||
|  |                     new_dt = str(rec.create_date).split('.') | ||||
|  |                     answers.append([rec.id, rec.nickname, new_dt[0], | ||||
|  |                                     new.question_id.title, new.display_name]) | ||||
|  |         answers.reverse() | ||||
|  |         response = request.make_response( | ||||
|  |             None, | ||||
|  |             headers=[ | ||||
|  |                 ('Content-Type', 'application/vnd.ms-excel'), | ||||
|  |                 ('Content-Disposition', | ||||
|  |                  content_disposition(survey_id.title + '.xlsx')) | ||||
|  |             ] | ||||
|  |         ) | ||||
|  |         output = io.BytesIO() | ||||
|  |         workbook = xlsxwriter.Workbook(output, {'in_memory': True}) | ||||
|  |         sheet = workbook.add_worksheet() | ||||
|  |         sheet.set_column(1, 0, 25) | ||||
|  |         sheet.set_column(2, 0, 25) | ||||
|  |         sheet.set_column(3, 3, 50) | ||||
|  |         cell_format = workbook.add_format( | ||||
|  |             {'font_size': '12px', 'align': 'center'}) | ||||
|  |         head = workbook.add_format( | ||||
|  |             {'align': 'center', 'bold': True, 'font_size': '20px'}) | ||||
|  |         sub_title = workbook.add_format( | ||||
|  |             {'align': 'right', 'bold': True, 'font_size': '12px'}) | ||||
|  |         sub_title_content = workbook.add_format( | ||||
|  |             {'align': 'left', 'bold': True, 'font_size': '12px'}) | ||||
|  |         txt = workbook.add_format({'font_size': '10px'}) | ||||
|  |         sheet.merge_range('A2:D3', 'SURVEY MANAGEMENT REPORT', head) | ||||
|  |         sheet.write('A4', 'Title :', sub_title) | ||||
|  |         sheet.merge_range('B4:C4', survey_id.title, sub_title_content) | ||||
|  |         sheet.merge_range('A6:A7', 'Partner', cell_format) | ||||
|  |         sheet.merge_range('B6:B7', 'Submission Date & Time', cell_format) | ||||
|  |         sheet.merge_range('C6:C7', 'Question', cell_format) | ||||
|  |         sheet.merge_range('D6:D7', 'Answer', cell_format) | ||||
|  |         row = 7 | ||||
|  |         column = 0 | ||||
|  |         for rec in answers: | ||||
|  |             sheet.write(row, column, rec[1], txt) | ||||
|  |             sheet.write(row, column + 1, rec[2], txt) | ||||
|  |             sheet.write(row, column + 2, rec[3], txt) | ||||
|  |             sheet.write(row, column + 3, rec[4], txt) | ||||
|  |             row = row + 1 | ||||
|  |         workbook.close() | ||||
|  |         output.seek(0) | ||||
|  |         response.stream.write(output.read()) | ||||
|  |         output.close() | ||||
|  |         return response | ||||
| @ -0,0 +1,10 @@ | |||||
|  | <?xml version="1.0" encoding="UTF-8" ?> | ||||
|  | <odoo noupdate="1"> | ||||
|  |     <!-- Survey Website menu data --> | ||||
|  |     <record id="menu_survey" model="website.menu"> | ||||
|  |         <field name="name">Survey</field> | ||||
|  |         <field name="url">/public/survey</field> | ||||
|  |         <field name="parent_id" ref="website.main_menu"/> | ||||
|  |         <field name="sequence" type="int">80</field> | ||||
|  |     </record> | ||||
|  | </odoo> | ||||
| @ -0,0 +1,7 @@ | |||||
|  | ## Module <enhanced_survey_management> | ||||
|  | 
 | ||||
|  | #### 30.10.2023 | ||||
|  | #### Version 16.0.1.0.0 | ||||
|  | #### ADD | ||||
|  | 
 | ||||
|  | - Initial commit for Enhanced Survey Management | ||||
| @ -0,0 +1,27 @@ | |||||
|  | # -*- coding: utf-8 -*- | ||||
|  | ############################################################################### | ||||
|  | # | ||||
|  | #    Cybrosys Technologies Pvt. Ltd. | ||||
|  | # | ||||
|  | #    Copyright (C) 2023-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) | ||||
|  | #    Author: Mohammed Savad, Ahammed Harshad  (odoo@cybrosys.com) | ||||
|  | # | ||||
|  | #    This program is under the terms of the Odoo Proprietary License v1.0(OPL-1) | ||||
|  | #    It is forbidden to publish, distribute, sublicense, or sell copies of the | ||||
|  | #    Software or modified copies of the Software. | ||||
|  | # | ||||
|  | #    THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
|  | #    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
|  | #    FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL | ||||
|  | #    THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,DAMAGES OR OTHER | ||||
|  | #    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,ARISING | ||||
|  | #    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | ||||
|  | #    DEALINGS IN THE SOFTWARE. | ||||
|  | # | ||||
|  | ############################################################################### | ||||
|  | from . import question_selection | ||||
|  | from . import survey_question | ||||
|  | from . import survey_question_answer | ||||
|  | from . import survey_survey | ||||
|  | from . import survey_user_input | ||||
|  | from . import survey_user_input_line | ||||
| @ -0,0 +1,34 @@ | |||||
|  | # -*- coding: utf-8 -*- | ||||
|  | ############################################################################### | ||||
|  | # | ||||
|  | #    Cybrosys Technologies Pvt. Ltd. | ||||
|  | # | ||||
|  | #    Copyright (C) 2023-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) | ||||
|  | #    Author: Mohammed Savad, Ahammed Harshad  (odoo@cybrosys.com) | ||||
|  | # | ||||
|  | #    This program is under the terms of the Odoo Proprietary License v1.0(OPL-1) | ||||
|  | #    It is forbidden to publish, distribute, sublicense, or sell copies of the | ||||
|  | #    Software or modified copies of the Software. | ||||
|  | # | ||||
|  | #    THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
|  | #    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
|  | #    FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL | ||||
|  | #    THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,DAMAGES OR OTHER | ||||
|  | #    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,ARISING | ||||
|  | #    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | ||||
|  | #    DEALINGS IN THE SOFTWARE. | ||||
|  | # | ||||
|  | ############################################################################### | ||||
|  | from odoo import fields, models | ||||
|  | 
 | ||||
|  | 
 | ||||
|  | class QuestionSelection(models.Model): | ||||
|  |     """Model to store options for selection type question""" | ||||
|  |     _name = 'question.selection' | ||||
|  |     _description = 'Selection Question' | ||||
|  | 
 | ||||
|  |     name = fields.Char(string='Name', help="Selection value.") | ||||
|  |     question_id = fields.Many2one('survey.question', | ||||
|  |                                   string="Question", | ||||
|  |                                   help="Field to store " | ||||
|  |                                        "question id in selection type.") | ||||
| @ -0,0 +1,95 @@ | |||||
|  | # -*- coding: utf-8 -*- | ||||
|  | ############################################################################### | ||||
|  | # | ||||
|  | #    Cybrosys Technologies Pvt. Ltd. | ||||
|  | # | ||||
|  | #    Copyright (C) 2023-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) | ||||
|  | #    Author: Mohammed Savad, Ahammed Harshad  (odoo@cybrosys.com) | ||||
|  | # | ||||
|  | #    This program is under the terms of the Odoo Proprietary License v1.0(OPL-1) | ||||
|  | #    It is forbidden to publish, distribute, sublicense, or sell copies of the | ||||
|  | #    Software or modified copies of the Software. | ||||
|  | # | ||||
|  | #    THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
|  | #    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
|  | #    FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL | ||||
|  | #    THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,DAMAGES OR OTHER | ||||
|  | #    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,ARISING | ||||
|  | #    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | ||||
|  | #    DEALINGS IN THE SOFTWARE. | ||||
|  | # | ||||
|  | ############################################################################### | ||||
|  | from odoo import api, fields, models, _ | ||||
|  | from odoo.exceptions import ValidationError | ||||
|  | 
 | ||||
|  | 
 | ||||
|  | class SurveyQuestion(models.Model): | ||||
|  |     """ Inherited survey.question to add custom question type""" | ||||
|  |     _inherit = 'survey.question' | ||||
|  | 
 | ||||
|  |     selection_ids = fields.One2many('question.selection', | ||||
|  |                                     'question_id', | ||||
|  |                                     string='Select', | ||||
|  |                                     help="""Field used to create selection type | ||||
|  |                                      questions""") | ||||
|  |     question_type = fields.Selection(selection_add=[ | ||||
|  |         ('time', 'Time'), | ||||
|  |         ('month', 'Month'), | ||||
|  |         ('name', 'Name'), | ||||
|  |         ('address', 'Address'), | ||||
|  |         ('email', 'Email'), | ||||
|  |         ('password', 'Password'), | ||||
|  |         ('qr', 'Qrcode'), | ||||
|  |         ('url', 'URL'), | ||||
|  |         ('week', 'Week'), | ||||
|  |         ('color', 'Color'), | ||||
|  |         ('range', 'Range'), | ||||
|  |         ('many2one', 'Many2one'), | ||||
|  |         ('file', 'Upload File'), | ||||
|  |         ('date', 'Date'), | ||||
|  |         ('many2many', 'Many2many'), | ||||
|  |         ('selection', 'Selection'), | ||||
|  |         ('barcode', 'Barcode') | ||||
|  |     ], help="Survey supported question types") | ||||
|  |     matrix_subtype = fields.Selection( | ||||
|  |         selection_add=[('custom', 'Custom Matrix')], | ||||
|  |         help="""Matrix selection type question""") | ||||
|  |     model_id = fields.Many2one('ir.model', string='Model', | ||||
|  |                                domain=[('transient', '=', False)], | ||||
|  |                                help="Many2one type question") | ||||
|  |     range_min = fields.Integer(string='Min', | ||||
|  |                                help='Minimum range,range type question') | ||||
|  |     range_max = fields.Integer(string='Max', | ||||
|  |                                help='Maximum range,range type question') | ||||
|  |     qrcode = fields.Text(string='Qrcode', | ||||
|  |                          help='Show qrcode in survey') | ||||
|  |     qrcode_png = fields.Binary(string='Qrcode PNG', help="Qrcode PNG") | ||||
|  |     barcode = fields.Char(string='Barcode', help="Barcode number") | ||||
|  |     barcode_png = fields.Binary(string='Barcode PNG', | ||||
|  |                                 help="Saves barcode png file") | ||||
|  | 
 | ||||
|  |     @api.onchange('barcode') | ||||
|  |     def _onchange_barcode(self): | ||||
|  |         """Onchange function to restrict barcode less-than 12 character """ | ||||
|  |         if self.barcode: | ||||
|  |             if len(self.barcode) < 12: | ||||
|  |                 raise ValidationError( | ||||
|  |                     _("Make sure barcode is at least 12 letters")) | ||||
|  |             if len(self.barcode) > 12: | ||||
|  |                 raise ValidationError( | ||||
|  |                     _("There should not be more than 12 " | ||||
|  |                       "characters in a barcode")) | ||||
|  |             if not self.barcode.isdigit(): | ||||
|  |                 raise ValidationError(_("Only digits are allowed.")) | ||||
|  | 
 | ||||
|  |     def get_selection_values(self): | ||||
|  |         """Function return options for selection type question""" | ||||
|  |         return self.selection_ids | ||||
|  | 
 | ||||
|  |     def prepare_model_id(self, model): | ||||
|  |         """Function to return options for many2one question""" | ||||
|  |         if model: | ||||
|  |             model_data = self.env[model.model].sudo().search([]) | ||||
|  |             return [rec.read([model_data._rec_name])[0] for rec in model_data] | ||||
|  |         model_data = self.env[self.model_id.model].sudo().search([]) | ||||
|  |         return [rec.read([model_data._rec_name])[0] for rec in model_data] | ||||
| @ -0,0 +1,48 @@ | |||||
|  | # -*- coding: utf-8 -*- | ||||
|  | ############################################################################### | ||||
|  | # | ||||
|  | #    Cybrosys Technologies Pvt. Ltd. | ||||
|  | # | ||||
|  | #    Copyright (C) 2023-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) | ||||
|  | #    Author: Mohammed Savad, Ahammed Harshad  (odoo@cybrosys.com) | ||||
|  | # | ||||
|  | #    This program is under the terms of the Odoo Proprietary License v1.0(OPL-1) | ||||
|  | #    It is forbidden to publish, distribute, sublicense, or sell copies of the | ||||
|  | #    Software or modified copies of the Software. | ||||
|  | # | ||||
|  | #    THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
|  | #    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
|  | #    FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL | ||||
|  | #    THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,DAMAGES OR OTHER | ||||
|  | #    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,ARISING | ||||
|  | #    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | ||||
|  | #    DEALINGS IN THE SOFTWARE. | ||||
|  | # | ||||
|  | ############################################################################### | ||||
|  | from odoo import fields, models | ||||
|  | 
 | ||||
|  | 
 | ||||
|  | class SurveyQuestionAnswer(models.Model): | ||||
|  |     """Inherit question answer model to add new answer type and model field""" | ||||
|  |     _inherit = 'survey.question.answer' | ||||
|  | 
 | ||||
|  |     answer_type = fields.Selection([ | ||||
|  |         ('text_box', 'Multiple Lines Text Box'), | ||||
|  |         ('char_box', 'Single Line Text Box'), | ||||
|  |         ('numerical_box', 'Numerical Value'), | ||||
|  |         ('date', 'Date'), | ||||
|  |         ('datetime', 'Datetime'), | ||||
|  |         ('time', 'Time'), | ||||
|  |         ('email', 'Email'), | ||||
|  |         ('password', 'Password'), | ||||
|  |         ('range', 'Range'), | ||||
|  |         ('month', 'Month'), | ||||
|  |         ('url', 'URL'), | ||||
|  |         ('week', 'Week'), | ||||
|  |         ('color', 'Color'), | ||||
|  |         ('many2one', 'Many2one')], help="Answer type", | ||||
|  |         string='Answer Type', readonly=False, store=True) | ||||
|  |     model_id = fields.Many2one('ir.model', string='Model', | ||||
|  |                                domain=[('transient', '=', False)], | ||||
|  |                                help="Select model for getting it's" | ||||
|  |                                     " values in survey") | ||||
| @ -0,0 +1,39 @@ | |||||
|  | # -*- coding: utf-8 -*- | ||||
|  | ############################################################################### | ||||
|  | # | ||||
|  | #    Cybrosys Technologies Pvt. Ltd. | ||||
|  | # | ||||
|  | #    Copyright (C) 2023-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) | ||||
|  | #    Author: Mohammed Savad, Ahammed Harshad  (odoo@cybrosys.com) | ||||
|  | # | ||||
|  | #    This program is under the terms of the Odoo Proprietary License v1.0(OPL-1) | ||||
|  | #    It is forbidden to publish, distribute, sublicense, or sell copies of the | ||||
|  | #    Software or modified copies of the Software. | ||||
|  | # | ||||
|  | #    THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
|  | #    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
|  | #    FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL | ||||
|  | #    THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,DAMAGES OR OTHER | ||||
|  | #    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,ARISING | ||||
|  | #    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | ||||
|  | #    DEALINGS IN THE SOFTWARE. | ||||
|  | # | ||||
|  | ############################################################################### | ||||
|  | from odoo import fields, models | ||||
|  | 
 | ||||
|  | 
 | ||||
|  | class Survey(models.Model): | ||||
|  |     """Inherited model to change survey visibility""" | ||||
|  |     _inherit = 'survey.survey' | ||||
|  | 
 | ||||
|  |     access_mode = fields.Selection(selection_add=[ | ||||
|  |         ('website', 'website')], ondelete={'website': 'cascade'}) | ||||
|  |     visibility = fields.Boolean(string='Portal Visibility', | ||||
|  |                                 help="""Portal visibility of this survey""") | ||||
|  | 
 | ||||
|  |     def action_answer_report_download(self): | ||||
|  |         """Function to generate report values""" | ||||
|  |         return { | ||||
|  |             'type': 'ir.actions.act_url', | ||||
|  |             'url': f'/xlsx_report/{self.id}' | ||||
|  |         } | ||||
| @ -0,0 +1,135 @@ | |||||
|  | # -*- coding: utf-8 -*- | ||||
|  | ############################################################################### | ||||
|  | # | ||||
|  | #    Cybrosys Technologies Pvt. Ltd. | ||||
|  | # | ||||
|  | #    Copyright (C) 2023-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) | ||||
|  | #    Author: Mohammed Savad, Ahammed Harshad (odoo@cybrosys.com) | ||||
|  | # | ||||
|  | #    This program is under the terms of the Odoo Proprietary License v1.0(OPL-1) | ||||
|  | #    It is forbidden to publish, distribute, sublicense, or sell copies of the | ||||
|  | #    Software or modified copies of the Software. | ||||
|  | # | ||||
|  | #    THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
|  | #    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
|  | #    FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL | ||||
|  | #    THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,DAMAGES OR OTHER | ||||
|  | #    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,ARISING | ||||
|  | #    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | ||||
|  | #    DEALINGS IN THE SOFTWARE. | ||||
|  | # | ||||
|  | ############################################################################### | ||||
|  | import json | ||||
|  | from odoo import models | ||||
|  | 
 | ||||
|  | 
 | ||||
|  | class SurveyUserInput(models.Model): | ||||
|  |     """Inherited user input to make acceptable for custom question""" | ||||
|  |     _inherit = "survey.user_input" | ||||
|  | 
 | ||||
|  |     def save_lines(self, question, answer, comment=None): | ||||
|  |         """Function to save custom answers""" | ||||
|  |         old_answers = self.env['survey.user_input.line'].search([ | ||||
|  |             ('user_input_id', '=', self.id), | ||||
|  |             ('question_id', '=', question.id), ]) | ||||
|  |         if question.question_type in ['password', 'range', 'time', 'url', | ||||
|  |                                       'email', 'range', 'many2many', | ||||
|  |                                       'file', 'many2one', 'week', 'color', | ||||
|  |                                       'month', 'address', 'name', 'selection', | ||||
|  |                                       'file', 'qr', 'barcode', 'signature']: | ||||
|  |             res = self._save_user_answers(question, old_answers, answer) | ||||
|  |         elif question.matrix_subtype == 'custom': | ||||
|  |             res = self._save_user_answers(question, old_answers, answer) | ||||
|  |         else: | ||||
|  |             res = super().save_lines(question, answer, comment) | ||||
|  |         return res | ||||
|  | 
 | ||||
|  |     def _save_user_answers(self, question, user_input_line, answer): | ||||
|  |         """Function to save custom answers""" | ||||
|  |         vals = (self._get_user_answers( | ||||
|  |             question, answer, question.question_type)) | ||||
|  |         if user_input_line: | ||||
|  |             user_input_line.write(vals) | ||||
|  |         else: | ||||
|  |             user_input_line = self.env['survey.user_input.line'].create(vals) | ||||
|  |         return user_input_line | ||||
|  | 
 | ||||
|  |     def _get_user_answers(self, question, answer, answer_type): | ||||
|  |         """Function to save custom answers""" | ||||
|  |         vals = {'user_input_id': self.id, 'question_id': question.id, | ||||
|  |                 'skipped': False, 'answer_type': answer_type, | ||||
|  |                 } | ||||
|  |         if not answer or (isinstance(answer, str) and not answer.strip()): | ||||
|  |             vals.update(answer_type=None, skipped=True) | ||||
|  |             return vals | ||||
|  |         if question.question_type == 'time': | ||||
|  |             vals['value_time'] = float(answer.replace(":", ".")) | ||||
|  |         elif question.question_type == 'url': | ||||
|  |             vals['value_url'] = answer | ||||
|  |         elif question.question_type == 'password': | ||||
|  |             vals['value_password'] = answer | ||||
|  |         elif question.question_type == 'email': | ||||
|  |             vals['value_email'] = answer | ||||
|  |         elif question.question_type == 'range': | ||||
|  |             vals['value_range'] = answer | ||||
|  |         elif question.question_type == 'many2one': | ||||
|  |             vals['value_many2one'] = answer[0] | ||||
|  |             vals['value_many2one_option'] = answer[1] | ||||
|  |         elif question.question_type == 'many2many': | ||||
|  |             vals['value_many2many'] = answer | ||||
|  |         elif question.question_type == 'week': | ||||
|  |             vals['value_week'] = answer | ||||
|  |         elif question.question_type == 'color': | ||||
|  |             vals['value_color'] = answer | ||||
|  |         elif question.question_type == 'month': | ||||
|  |             vals['value_month'] = answer | ||||
|  |         elif question.question_type == 'matrix' \ | ||||
|  |                 and question.matrix_subtype == 'custom': | ||||
|  |             vals['value_matrix'] = json.dumps(answer) | ||||
|  |         elif question.question_type == 'address': | ||||
|  |             vals['value_address'] = json.dumps(answer) | ||||
|  |         elif question.question_type == 'qr': | ||||
|  |             vals['value_qr'] = json.dumps(answer) | ||||
|  |         elif question.question_type == 'barcode': | ||||
|  |             vals['value_barcode'] = json.dumps(answer) | ||||
|  |         elif question.question_type == 'name': | ||||
|  |             vals['value_name'] = json.dumps(answer) | ||||
|  |         elif question.question_type == 'selection': | ||||
|  |             vals['value_selection'] = answer | ||||
|  |         elif question.question_type == 'file': | ||||
|  |             attachment = self.env['ir.attachment'].create({ | ||||
|  |                 'name': str(answer[1]), 'datas': answer[0], 'type': 'binary' | ||||
|  |             }) | ||||
|  |             vals['value_file'] = int(attachment.id if attachment else False) | ||||
|  |             vals['filename'] = attachment.name if attachment else False | ||||
|  |         return vals | ||||
|  | 
 | ||||
|  |     def _save_line_matrix(self, question, old_answers, answers, comment): | ||||
|  |         """Function to save custom matrix""" | ||||
|  |         if question.matrix_subtype == 'custom': | ||||
|  |             self._save_line(question, answers) | ||||
|  |         else: | ||||
|  |             vals_list = [] | ||||
|  |             if not answers and question.matrix_row_ids: | ||||
|  |                 # add a False answer to force saving a skipped line | ||||
|  |                 # this will make this question correctly considered as | ||||
|  |                 # skipped in statistics | ||||
|  |                 answers = {question.matrix_row_ids[0].id: [False]} | ||||
|  |             if answers: | ||||
|  |                 for row_key, row_answer in answers.items(): | ||||
|  |                     for answer in row_answer: | ||||
|  |                         vals = self._get_line_answer_values(question, answer, | ||||
|  |                                                             'suggestion') | ||||
|  |                         vals['matrix_row_id'] = int(row_key) | ||||
|  |                         vals_list.append(vals.copy()) | ||||
|  |             if comment: | ||||
|  |                 vals_list.append( | ||||
|  |                     self._get_line_comment_values(question, comment)) | ||||
|  |             old_answers.sudo().unlink() | ||||
|  |             return self.env['survey.user_input.line'].create(vals_list) | ||||
|  | 
 | ||||
|  |     def _save_line_selection_answer(self, question, answer): | ||||
|  |         """Function to save selection type answers""" | ||||
|  |         vals = self._get_line_answer_values(question, answer, | ||||
|  |                                             question.question_type) | ||||
|  |         return self.env['survey.user_input.line'].create(vals) | ||||
| @ -0,0 +1,189 @@ | |||||
|  | # -*- coding: utf-8 -*- | ||||
|  | ############################################################################### | ||||
|  | # | ||||
|  | #    Cybrosys Technologies Pvt. Ltd. | ||||
|  | # | ||||
|  | #    Copyright (C) 2023-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) | ||||
|  | #    Author: Mohammed Savad, Ahammed Harshad r (odoo@cybrosys.com) | ||||
|  | # | ||||
|  | #    This program is under the terms of the Odoo Proprietary License v1.0(OPL-1) | ||||
|  | #    It is forbidden to publish, distribute, sublicense, or sell copies of the | ||||
|  | #    Software or modified copies of the Software. | ||||
|  | # | ||||
|  | #    THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
|  | #    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
|  | #    FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL | ||||
|  | #    THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,DAMAGES OR OTHER | ||||
|  | #    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,ARISING | ||||
|  | #    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | ||||
|  | #    DEALINGS IN THE SOFTWARE. | ||||
|  | # | ||||
|  | ############################################################################### | ||||
|  | import json | ||||
|  | import textwrap | ||||
|  | from datetime import datetime | ||||
|  | from odoo import api, fields, models, _ | ||||
|  | 
 | ||||
|  | 
 | ||||
|  | class SurveyUserInputLine(models.Model): | ||||
|  |     """Inherited user input line to add custom answer types """ | ||||
|  |     _inherit = 'survey.user_input.line' | ||||
|  | 
 | ||||
|  |     answer_type = fields.Selection( | ||||
|  |         selection_add=[('url', 'URL'), | ||||
|  |                        ('many2one', 'Many2one'), | ||||
|  |                        ('many2many', 'Many2many'), | ||||
|  |                        ('week', 'Week'), | ||||
|  |                        ('time', 'Time'), | ||||
|  |                        ('color', 'Color'), | ||||
|  |                        ('email', 'Email'), | ||||
|  |                        ('month', 'Month'), | ||||
|  |                        ('name', 'Name'), | ||||
|  |                        ('matrix', 'Matrix'), | ||||
|  |                        ('address', 'Address'), | ||||
|  |                        ('selection', 'Selection'), | ||||
|  |                        ('time', 'Time'), | ||||
|  |                        ('password', 'Password'), | ||||
|  |                        ('email', 'Email'), | ||||
|  |                        ('range', 'Range'), | ||||
|  |                        ('file', 'File'), | ||||
|  |                        ('qr', 'Qrcode'), | ||||
|  |                        ('barcode', 'Barcode')], help="Custom answer types") | ||||
|  |     value_url = fields.Char(string='User URL', | ||||
|  |                             help='Answer question type : URL') | ||||
|  |     value_email = fields.Char(string='User Email', | ||||
|  |                               help="Answer question type : Email") | ||||
|  |     value_week = fields.Char(string='User Week', | ||||
|  |                              help="Answer question type : Week") | ||||
|  |     value_color = fields.Char(string='User Color', | ||||
|  |                               help="Answer question type : Color") | ||||
|  |     value_many2one = fields.Char(string='Survey Many2one', | ||||
|  |                                  help="Answer question type : Many2one") | ||||
|  |     value_many2one_option = fields.Char(string='Many2one selected', | ||||
|  |                                         help="Answer question type : Selected") | ||||
|  |     value_many2many = fields.Char(string='Survey Many2many', | ||||
|  |                                   help="Answer question type : Many2many") | ||||
|  |     value_time = fields.Float(string='Time Value', | ||||
|  |                               help="Answer question type : Time") | ||||
|  |     value_matrix = fields.Text(string='Custom Matrix Values', | ||||
|  |                                help="Answer question type : Custom Matrix") | ||||
|  |     value_selection = fields.Char(string='User Selection', | ||||
|  |                                   help="Answer question type : Selection") | ||||
|  |     value_password = fields.Char(string='Password Value', | ||||
|  |                                  help="Answer question type : Password") | ||||
|  |     value_range = fields.Char(string='Range Value', | ||||
|  |                               help="Answer question type:Range") | ||||
|  |     value_file = fields.Many2one('ir.attachment', | ||||
|  |                                  string='Survey file', | ||||
|  |                                  help="Answer question type : Attachment") | ||||
|  |     filename = fields.Char(string='File', help="Attachment file name") | ||||
|  |     file_data = fields.Binary(string='File Data', | ||||
|  |                               help="Attachment file data", | ||||
|  |                               related="value_file.datas") | ||||
|  |     value_month = fields.Char(string='Month Value', | ||||
|  |                               help="Answer question type : Month") | ||||
|  |     value_address = fields.Text(string='Address Value', | ||||
|  |                                 help="Answer question type : Address") | ||||
|  |     value_name = fields.Text(string='Name Values', | ||||
|  |                              help="Answer question type : Full name") | ||||
|  |     value_qr = fields.Char(string='Qr Values', | ||||
|  |                            help="Answer question type : QRcode") | ||||
|  |     value_barcode = fields.Char(string='Barcode Values', | ||||
|  |                                 help="Answer question type : Barcode") | ||||
|  | 
 | ||||
|  |     def get_value_time(self): | ||||
|  |         """Function to return answer for question type time """ | ||||
|  |         if self.value_time: | ||||
|  |             return datetime.strptime(str(self.value_time).replace('.', ':'), | ||||
|  |                                      "%H:%M").strftime("%H:%M") | ||||
|  |         return None | ||||
|  | 
 | ||||
|  | 
 | ||||
|  |     def get_value_address(self, field): | ||||
|  |         """Function to return answer for question type address""" | ||||
|  |         data = json.loads(self.value_address) | ||||
|  |         if data: | ||||
|  |             question_id = self.question_id.id | ||||
|  |             return data[f'{question_id}-{field}'] | ||||
|  |         return '' | ||||
|  | 
 | ||||
|  |     def get_value_matrix(self, item): | ||||
|  |         """Function to return answer for custom matrix""" | ||||
|  |         data = json.loads(self.value_matrix) | ||||
|  |         if data: | ||||
|  |             question_id = self.question_id.id | ||||
|  |             return data[f'{item}-{question_id}'] | ||||
|  |         return None | ||||
|  | 
 | ||||
|  |     def get_value_name(self, field): | ||||
|  |         """Function to return answer for Full name""" | ||||
|  |         data = json.loads(self.value_name) | ||||
|  |         if data: | ||||
|  |             question_id = self.question_id.id | ||||
|  |             return data[f'{question_id}-{field}'] | ||||
|  |         return '' | ||||
|  | 
 | ||||
|  |     @api.depends('answer_type') | ||||
|  |     def _compute_display_name(self): | ||||
|  |         """Override compute function to add custom answer display""" | ||||
|  |         for line in self: | ||||
|  |             if line.answer_type == 'char_box': | ||||
|  |                 line.display_name = line.value_char_box | ||||
|  |             elif line.answer_type == 'text_box' and line.value_text_box: | ||||
|  |                 line.display_name = textwrap.shorten(line.value_text_box, | ||||
|  |                                                      width=50, | ||||
|  |                                                      placeholder=" [...]") | ||||
|  |             elif line.answer_type == 'numerical_box': | ||||
|  |                 line.display_name = line.value_numerical_box | ||||
|  |             elif line.answer_type == 'time': | ||||
|  |                 line.display_name = line.value_time | ||||
|  |             elif line.answer_type == 'month': | ||||
|  |                 line.display_name = line.value_month | ||||
|  |             elif line.answer_type == 'address': | ||||
|  |                 line.display_name = line.value_address | ||||
|  |             elif line.answer_type == 'name': | ||||
|  |                 line.display_name = line.value_name | ||||
|  |             elif line.answer_type == 'url': | ||||
|  |                 line.display_name = line.value_url | ||||
|  |             elif line.answer_type == 'many2one': | ||||
|  |                 line.display_name = line.value_many2one_option | ||||
|  |             elif line.answer_type == 'many2many': | ||||
|  |                 line.display_name = line.value_many2many | ||||
|  |             elif line.answer_type == 'week': | ||||
|  |                 line.display_name = line.value_week | ||||
|  |             elif line.answer_type == 'time': | ||||
|  |                 line.display_name = line.value_time | ||||
|  |             elif line.answer_type == 'email': | ||||
|  |                 line.display_name = line.value_email | ||||
|  |             elif line.answer_type == 'range': | ||||
|  |                 line.display_name = line.value_range | ||||
|  |             elif line.answer_type == 'matrix': | ||||
|  |                 line.display_name = line.value_matrix | ||||
|  |             elif line.answer_type == 'password': | ||||
|  |                 line.display_name = line.value_password | ||||
|  |             elif line.answer_type == 'signature': | ||||
|  |                 line.display_name = line.value_signature | ||||
|  |             elif line.answer_type == 'color': | ||||
|  |                 line.display_name = line.value_color | ||||
|  |             elif line.answer_type == 'selection': | ||||
|  |                 line.display_name = line.value_selection | ||||
|  |             elif line.answer_type == 'barcode': | ||||
|  |                 line.display_name = line.value_barcode | ||||
|  |             elif line.answer_type == 'qr': | ||||
|  |                 line.display_name = line.value_qr | ||||
|  |             elif line.answer_type == 'file': | ||||
|  |                 line.display_name = line.filename | ||||
|  |             elif line.answer_type == 'date': | ||||
|  |                 line.display_name = fields.Date.to_string(line.value_date) | ||||
|  |             elif line.answer_type == 'datetime': | ||||
|  |                 line.display_name = fields.Datetime.to_string( | ||||
|  |                     line.value_datetime) | ||||
|  |             elif line.answer_type == 'suggestion': | ||||
|  |                 if line.matrix_row_id: | ||||
|  |                     line.display_name = '%s: %s' % ( | ||||
|  |                         line.suggested_answer_id.value, | ||||
|  |                         line.matrix_row_id.value) | ||||
|  |                 else: | ||||
|  |                     line.display_name = line.suggested_answer_id.value | ||||
|  |             if not line.display_name: | ||||
|  |                 line.display_name = _('Skipped') | ||||
| 
 | 
| After Width: | Height: | Size: 2.2 KiB | 
| After Width: | Height: | Size: 28 KiB | 
| After Width: | Height: | Size: 203 KiB | 
| After Width: | Height: | Size: 18 KiB | 
| After Width: | Height: | Size: 21 KiB | 
| After Width: | Height: | Size: 24 KiB | 
| After Width: | Height: | Size: 3.6 KiB | 
| After Width: | Height: | Size: 310 B | 
| After Width: | Height: | Size: 1.3 KiB | 
| After Width: | Height: | Size: 1.4 KiB | 
| After Width: | Height: | Size: 562 B | 
| After Width: | Height: | Size: 576 B | 
| After Width: | Height: | Size: 733 B | 
| After Width: | Height: | Size: 4.3 KiB | 
| After Width: | Height: | Size: 4.0 KiB | 
| After Width: | Height: | Size: 911 B | 
| After Width: | Height: | Size: 1.1 KiB | 
| After Width: | Height: | Size: 1.2 KiB | 
| After Width: | Height: | Size: 673 B | 
| After Width: | Height: | Size: 22 KiB | 
| After Width: | Height: | Size: 878 B | 
| After Width: | Height: | Size: 24 KiB | 
| After Width: | Height: | Size: 653 B | 
| After Width: | Height: | Size: 905 B | 
| After Width: | Height: | Size: 4.3 KiB | 
| After Width: | Height: | Size: 839 B | 
| After Width: | Height: | Size: 3.8 KiB | 
| After Width: | Height: | Size: 26 KiB | 
| After Width: | Height: | Size: 427 B | 
| After Width: | Height: | Size: 627 B | 
| After Width: | Height: | Size: 1.2 KiB | 
| After Width: | Height: | Size: 988 B | 
| After Width: | Height: | Size: 3.7 KiB | 
| After Width: | Height: | Size: 30 KiB | 
| After Width: | Height: | Size: 5.0 KiB | 
| After Width: | Height: | Size: 1.2 KiB | 
| After Width: | Height: | Size: 1.5 KiB | 
| After Width: | Height: | Size: 1.1 KiB | 
| After Width: | Height: | Size: 1.9 KiB | 
| After Width: | Height: | Size: 1.1 KiB | 
| After Width: | Height: | Size: 2.1 KiB | 
| After Width: | Height: | Size: 4.4 KiB | 
| After Width: | Height: | Size: 589 B | 
| After Width: | Height: | Size: 3.4 KiB | 
| After Width: | Height: | Size: 1.7 KiB | 
| After Width: | Height: | Size: 2.3 KiB | 
| After Width: | Height: | Size: 967 B | 
| After Width: | Height: | Size: 1.6 KiB | 
| After Width: | Height: | Size: 3.8 KiB | 
| After Width: | Height: | Size: 5.0 KiB | 
| After Width: | Height: | Size: 60 KiB | 
| After Width: | Height: | Size: 56 KiB | 
| After Width: | Height: | Size: 56 KiB | 
| After Width: | Height: | Size: 59 KiB | 
| After Width: | Height: | Size: 1.8 MiB | 
| After Width: | Height: | Size: 57 KiB | 
| After Width: | Height: | Size: 460 KiB | 
| After Width: | Height: | Size: 346 KiB | 
| After Width: | Height: | Size: 162 KiB | 
| After Width: | Height: | Size: 292 KiB | 
| After Width: | Height: | Size: 183 KiB | 
| After Width: | Height: | Size: 330 KiB | 
| After Width: | Height: | Size: 208 KiB | 
| After Width: | Height: | Size: 285 KiB | 
| After Width: | Height: | Size: 258 KiB | 
| After Width: | Height: | Size: 232 KiB | 
| After Width: | Height: | Size: 342 KiB | 
| After Width: | Height: | Size: 158 KiB | 
| After Width: | Height: | Size: 292 KiB | 
| After Width: | Height: | Size: 181 KiB | 
| After Width: | Height: | Size: 294 KiB | 
| After Width: | Height: | Size: 202 KiB | 
| After Width: | Height: | Size: 291 KiB | 
| After Width: | Height: | Size: 269 KiB | 
| After Width: | Height: | Size: 356 KiB | 
| After Width: | Height: | Size: 224 KiB | 
| After Width: | Height: | Size: 326 KiB | 
| After Width: | Height: | Size: 145 KiB | 
| After Width: | Height: | Size: 355 KiB | 
| After Width: | Height: | Size: 156 KiB | 
| After Width: | Height: | Size: 294 KiB | 
| After Width: | Height: | Size: 181 KiB | 
| After Width: | Height: | Size: 293 KiB |