# -*- coding: utf-8 -*- from odoo import _, api, fields, models from odoo.exceptions import UserError class LoyaltyProgram(models.Model): _name = 'loyalty.program' _inherit = ['loyalty.program', 'mail.thread', 'mail.activity.mixin'] state = fields.Selection([ ('draft', 'Draft'), ('pending', 'Pending Approval'), ('approved', 'Approved') ], default='draft', string='Status', tracking=True) def action_request_approval(self): for program in self: if program.state != 'draft': continue program.write({'state': 'pending'}) program.message_post(body=_("Approval requested for this marketing program.")) def action_approve(self): for program in self: if program.state != 'pending': continue # Check authorization target_company = program.company_id or self.env.company approver = target_company._get_marketing_program_approver() if approver: if self.env.user.id != approver.id: raise UserError(_("Only the designated Marketing Program Approver (%s) can approve this program.") % approver.name) else: is_manager = self.env.user.has_group('pos_loyalty_marketing_access.group_marketing_manager') if not is_manager: raise UserError(_("Only a Marketing Manager can approve this program as no designated approver is configured.")) program.write({'state': 'approved'}) program.message_post(body=_("Marketing program has been approved and is now active.")) def action_reset_draft(self): for program in self: program.write({'state': 'draft'}) program.message_post(body=_("Marketing program reset to Draft.")) def write(self, vals): # Fields that do not require re-approval when modified (e.g., sequence reordering, archiving, or chatter/activity updates) non_trigger_fields = { 'sequence', 'state', 'active', 'write_uid', 'write_date', 'message_follower_ids', 'message_ids', 'message_main_attachment_id', 'activity_ids', 'activity_state', 'activity_user_id', 'activity_type_id', 'activity_date_deadline', 'activity_summary' } # If all modified fields are in the non-trigger list, skip reset logic if all(k in non_trigger_fields for k in vals): return super().write(vals) # Skip reset logic if Odoo is installing/upgrading modules or explicitly bypassed if (self.env.context.get('install_mode') or self.env.context.get('no_marketing_reset') or self.env.context.get('module')): return super().write(vals) # For modifications, check if they are in pending/approved state programs_to_reset = self.filtered(lambda p: p.state in ['pending', 'approved']) if programs_to_reset: vals['state'] = 'draft' for program in programs_to_reset: program.message_post(body=_("The marketing program was modified and has been reset to Draft status for re-approval.")) return super().write(vals)