# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). from __future__ import annotations import base64 import json import os from typing import TYPE_CHECKING from odoo import _, models from odoo.exceptions import ValidationError if TYPE_CHECKING: from odoo.addons.survey_extra_fields.models.survey_question import SurveyQuestion class SurveyUserInput(models.Model): _inherit = "survey.user_input" def save_lines(self, question: SurveyQuestion, answer: str | None, comment: str | None = None) -> None: if question.question_type == "file": old_answers = self.env["survey.user_input.line"].search([ ("user_input_id", "=", self.id), ("question_id", "=", question.id), ]) vals = { "user_input_id": self.id, "question_id": question.id, "skipped": False, "answer_type": "file", } if answer: file_data = json.loads(answer) file_b64 = file_data.get("data", "") file_name = file_data.get("name", "") self._check_file_constraints(question, file_b64, file_name) vals["value_file"] = file_b64 vals["value_file_fname"] = file_name else: vals.update(answer_type=None, skipped=True) if old_answers: old_answers.write(vals) else: self.env["survey.user_input.line"].create(vals) else: return super().save_lines(question, answer, comment=comment) def _check_file_constraints( self, question: SurveyQuestion, file_b64: str, file_name: str ) -> None: if question.max_file_size: file_size = len(base64.b64decode(file_b64)) max_bytes = question.max_file_size * 1024 * 1024 if file_size > max_bytes: raise ValidationError( _("The file '%(name)s' exceeds the maximum allowed size of %(size)s MB.", name=file_name, size=question.max_file_size) ) if question.allowed_extensions: allowed = [ allowed_extension.strip().lower() for allowed_extension in question.allowed_extensions.split(",") if allowed_extension.strip() ] file_extension = os.path.splitext(file_name)[1].lower() if file_extension not in allowed: raise ValidationError( _("The file '%(name)s' is not allowed. Accepted formats: %(exts)s.", name=file_name, exts=question.allowed_extensions) )