"""Game-neutral card reference models.""" from odoo import _, api, fields, models from odoo.exceptions import UserError class MvdTcgCard(models.Model): """Represent a game-neutral card reference entry.""" _name = "mvd.tcg.card" _description = "TCG Card" _inherit = "image.mixin" _order = "game_id, sequence, name, id" active = fields.Boolean(default=True) sequence = fields.Integer(default=10) state = fields.Selection( selection=[ ("draft", "Draft"), ("validated", "Validated"), ], default="draft", required=True, index=True, copy=False, ) name = fields.Char(required=True, translate=True, index="trigram") game_id = fields.Many2one( "mvd.tcg.game", required=True, index=True, ondelete="restrict", ) external_ref = fields.Char( index=True, help="Adapter-specific identifier for this card reference.", ) description = fields.Html( translate=True, ) note = fields.Text( translate=True, help="Internal neutral note stored on the card reference.", ) _external_ref_unique = models.Constraint( "UNIQUE (game_id, external_ref)", "The external reference must be unique per game.", ) def _mvd_tcg_can_edit_external_ref(self): """Return whether the current user may edit adapter reference ids. Returns: bool: ``True`` for TCG administrators and system users. """ return self.env.is_superuser() or any( self.env.user.has_group(xmlid) for xmlid in ( "mvd_tcg_base.mvd_tcg_base_group_administrator", "base.group_system", ) ) @api.model_create_multi def create(self, vals_list): """Protect technical external references during card creation. Args: vals_list: Standard ORM payloads for new cards. Returns: Model: Created card records. """ prepared_vals_list = [] for vals in vals_list: prepared_vals = dict(vals) if ( prepared_vals.get("external_ref") and not self.env.context.get("mvd_tcg_bypass_external_ref_write") and not self._mvd_tcg_can_edit_external_ref() ): raise UserError( _( "Adapter reference ids can only be set by TCG administrators." ) ) prepared_vals_list.append(prepared_vals) return super().create(prepared_vals_list) def write(self, vals): """Prevent accidental edits on validated reference cards. Args: vals: Field values to update. Returns: bool: Result of the underlying ORM write. Raises: UserError: If a validated card is modified outside the allowed paths. """ if ( "external_ref" in vals and not self.env.context.get("mvd_tcg_bypass_external_ref_write") and not self._mvd_tcg_can_edit_external_ref() ): raise UserError( _( "Adapter reference ids can only be changed by TCG administrators." ) ) if not self.env.context.get("mvd_tcg_bypass_validated_write"): validated_cards = self.filtered(lambda card: card.state == "validated") is_reset_to_draft = set(vals) == {"state"} and vals.get("state") == "draft" if validated_cards and not is_reset_to_draft: raise UserError( _( "Validated cards are read-only. Reset the card to Draft first " "if you really want to edit it." ) ) return super().write(vals) def action_validate(self): """Lock the current cards as validated reference data. Returns: bool: ``True`` when the operation completed. """ self.write({"state": "validated"}) return True def action_reset_to_draft(self): """Move the current cards back into editable draft state. Returns: bool: ``True`` when the operation completed. """ self.write({"state": "draft"}) return True def _mvd_tcg_get_deck_image_binary(self): """Return the preferred card image for deck previews. Returns: str | bool: Base64 image data for deck-related previews. """ self.ensure_one() return self.image_512 or self.image_1920 or False