Tower: upload cetmix_tower_yaml 16.0.2.0.3 (via marketplace)
This commit is contained in:
@@ -0,0 +1,137 @@
|
||||
import binascii
|
||||
from base64 import b64decode
|
||||
|
||||
import yaml
|
||||
|
||||
from odoo import _, fields, models
|
||||
from odoo.exceptions import ValidationError
|
||||
|
||||
|
||||
class CxTowerYamlImportWizUpload(models.TransientModel):
|
||||
"""
|
||||
Upload YAML file and perform initial validation.
|
||||
Submit YAML data to import wizard for further processing.
|
||||
"""
|
||||
|
||||
_name = "cx.tower.yaml.import.wiz.upload"
|
||||
_description = "Cetmix Tower YAML Import Wizard Upload"
|
||||
|
||||
file_name = fields.Char()
|
||||
yaml_file = fields.Binary(required=True)
|
||||
|
||||
def action_import_yaml(self):
|
||||
"""Parse YAML data to the import wizard
|
||||
|
||||
Returns:
|
||||
Action Window: Action to open the import wizard
|
||||
"""
|
||||
|
||||
decoded_file = self._extract_yaml_data()
|
||||
|
||||
import_wizard = self.env["cx.tower.yaml.import.wiz"].create(
|
||||
{
|
||||
"yaml_code": decoded_file,
|
||||
}
|
||||
)
|
||||
|
||||
return {
|
||||
"type": "ir.actions.act_window",
|
||||
"res_model": "cx.tower.yaml.import.wiz",
|
||||
"res_id": import_wizard.id,
|
||||
"view_mode": "form",
|
||||
"target": "new",
|
||||
}
|
||||
|
||||
def _extract_yaml_data(self):
|
||||
"""Extract data from YAML file and validate them
|
||||
|
||||
Returns:
|
||||
decoded_file (Text): YAML code
|
||||
Raises:
|
||||
ValidationError: If the YAML file is invalid
|
||||
or contains unsupported data
|
||||
"""
|
||||
|
||||
self.ensure_one()
|
||||
|
||||
# Decode base64 file
|
||||
try:
|
||||
raw_bytes = b64decode(self.yaml_file or b"")
|
||||
except (TypeError, binascii.Error) as e:
|
||||
# Not a valid base-64 payload
|
||||
raise ValidationError(_("File is not a valid base64-encoded file")) from e
|
||||
|
||||
if not raw_bytes:
|
||||
raise ValidationError(_("File is empty"))
|
||||
|
||||
try:
|
||||
decoded_file = raw_bytes.decode("utf-8")
|
||||
except UnicodeDecodeError as e:
|
||||
raise ValidationError(_("YAML file cannot be decoded properly")) from e
|
||||
|
||||
# Parse YAML file
|
||||
try:
|
||||
yaml_data = yaml.safe_load(decoded_file)
|
||||
except yaml.YAMLError as e:
|
||||
raise ValidationError(_("Invalid YAML file")) from e
|
||||
|
||||
if not yaml_data or not isinstance(yaml_data, dict):
|
||||
raise ValidationError(_("Yaml file doesn't contain valid data"))
|
||||
|
||||
# Check Cetmix Tower YAML version
|
||||
yaml_version = yaml_data.pop("cetmix_tower_yaml_version", None)
|
||||
supported_version = self.env["cx.tower.yaml.mixin"].CETMIX_TOWER_YAML_VERSION
|
||||
if (
|
||||
yaml_version
|
||||
and isinstance(yaml_version, int)
|
||||
and yaml_version > supported_version
|
||||
):
|
||||
raise ValidationError(
|
||||
_(
|
||||
"YAML version is higher than version"
|
||||
" supported by your Cetmix Tower instance."
|
||||
" %(code_version)s > %(tower_version)s",
|
||||
code_version=yaml_version,
|
||||
tower_version=supported_version,
|
||||
)
|
||||
)
|
||||
|
||||
# Get records from YAML
|
||||
records = yaml_data.get("records")
|
||||
if not records:
|
||||
raise ValidationError(_("YAML file doesn't contain any records"))
|
||||
|
||||
# Collect and validate all record models
|
||||
ir_model_obj = self.env["ir.model"]
|
||||
unique_models = {}
|
||||
|
||||
# First pass: check all records have models and collect unique models
|
||||
for record in records:
|
||||
record_model = record.get("cetmix_tower_model")
|
||||
if not record_model:
|
||||
raise ValidationError(
|
||||
_(
|
||||
"Record model is missing for record %s",
|
||||
record.get("reference", ""),
|
||||
)
|
||||
)
|
||||
if record_model not in unique_models:
|
||||
odoo_model = f"cx.tower.{record_model}".replace("_", ".")
|
||||
unique_models[record_model] = odoo_model
|
||||
|
||||
# Second pass: validate all unique models in a single query
|
||||
odoo_models = list(unique_models.values())
|
||||
valid_models = {
|
||||
model.model: model
|
||||
for model in ir_model_obj.search([("model", "in", odoo_models)])
|
||||
}
|
||||
|
||||
# Third pass: check models exist and support YAML import
|
||||
for record_model, odoo_model in unique_models.items():
|
||||
if odoo_model not in valid_models:
|
||||
raise ValidationError(_("'%s' is not a valid model", record_model))
|
||||
if not hasattr(self.env[odoo_model], "yaml_code"):
|
||||
raise ValidationError(
|
||||
_("Model '%s' does not support YAML import", record_model)
|
||||
)
|
||||
return decoded_file
|
||||
Reference in New Issue
Block a user