# -*- coding: utf-8 -*- # Copyright 2024-2025 Nexa Systems Inc. # License OPL-1 (Odoo Proprietary License v1.0) from odoo import models, fields, api, _ from odoo.exceptions import UserError from markupsafe import Markup from datetime import date import logging _logger = logging.getLogger(__name__) class ReadyForSubmissionWizard(models.TransientModel): """Wizard to collect required fields before marking as Ready for Submission.""" _name = 'fusion_claims.ready.for.submission.wizard' _description = 'Ready for Submission Wizard' sale_order_id = fields.Many2one( 'sale.order', string='Sale Order', required=True, readonly=True, ) # Authorization Details claim_authorization_date = fields.Date( string='Claim Authorization Date', required=True, default=fields.Date.context_today, help='Date when the claim was authorized by the OT/Authorizer', ) # Client References (may already be filled) client_ref_1 = fields.Char( string='Client Reference 1', help='First two letters of the client\'s first name and last two letters of their last name. Example: John Doe = JODO', ) client_ref_2 = fields.Char( string='Client Reference 2', help='Last four digits of the client\'s health card number. Example: 1234', ) # Reason for Application reason_for_application = fields.Selection([ ('first_access', 'First Time Access - NO previous ADP'), ('additions', 'Additions'), ('mod_non_adp', 'Modification/Upgrade - Original NOT through ADP'), ('mod_adp', 'Modification/Upgrade - Original through ADP'), ('replace_status', 'Replacement - Change in Status'), ('replace_size', 'Replacement - Change in Body Size'), ('replace_worn', 'Replacement - Worn out (past useful life)'), ('replace_lost', 'Replacement - Lost'), ('replace_stolen', 'Replacement - Stolen'), ('replace_damaged', 'Replacement - Damaged beyond repair'), ('replace_no_longer_meets', 'Replacement - No longer meets needs'), ('growth', 'Growth/Change in condition'), ], string='Reason for Application') # Previous Funding (required for some reasons) requires_previous_funding = fields.Boolean( string='Requires Previous Funding Date', compute='_compute_requires_previous_funding', ) previous_funding_date = fields.Date( string='Previous Funding Date', help='Date of previous ADP funding (required for modifications/replacements)', ) # Show which fields are already filled has_authorization_date = fields.Boolean(compute='_compute_field_status') has_client_refs = fields.Boolean(compute='_compute_field_status') has_reason = fields.Boolean(compute='_compute_field_status') has_documents = fields.Boolean(compute='_compute_field_status') notes = fields.Text( string='Notes', help='Any notes about the submission preparation', ) @api.depends('reason_for_application') def _compute_requires_previous_funding(self): no_prev_funding_reasons = ['first_access', 'mod_non_adp'] for wizard in self: reason = wizard.reason_for_application wizard.requires_previous_funding = bool(reason) and reason not in no_prev_funding_reasons @api.depends('sale_order_id') def _compute_field_status(self): for wizard in self: order = wizard.sale_order_id wizard.has_authorization_date = bool(order.x_fc_claim_authorization_date) wizard.has_client_refs = bool(order.x_fc_client_ref_1 and order.x_fc_client_ref_2) wizard.has_reason = bool(order.x_fc_reason_for_application) wizard.has_documents = bool(order.x_fc_original_application and order.x_fc_signed_pages_11_12) @api.model def default_get(self, fields_list): res = super().default_get(fields_list) active_id = self._context.get('active_id') if active_id: order = self.env['sale.order'].browse(active_id) res['sale_order_id'] = order.id # Pre-fill from existing values if order.x_fc_claim_authorization_date: res['claim_authorization_date'] = order.x_fc_claim_authorization_date if order.x_fc_client_ref_1: res['client_ref_1'] = order.x_fc_client_ref_1 if order.x_fc_client_ref_2: res['client_ref_2'] = order.x_fc_client_ref_2 if order.x_fc_reason_for_application: res['reason_for_application'] = order.x_fc_reason_for_application if order.x_fc_previous_funding_date: res['previous_funding_date'] = order.x_fc_previous_funding_date return res def action_confirm(self): """Validate and mark as ready for submission.""" self.ensure_one() order = self.sale_order_id if order.x_fc_adp_application_status != 'application_received': raise UserError("Can only mark ready for submission from 'Application Received' status.") # Validate required fields missing = [] if not self.claim_authorization_date: missing.append('Claim Authorization Date') if not self.client_ref_1 and not order.x_fc_client_ref_1: missing.append('Client Reference 1') if not self.client_ref_2 and not order.x_fc_client_ref_2: missing.append('Client Reference 2') if not self.reason_for_application and not order.x_fc_reason_for_application: missing.append('Reason for Application') # Check previous funding if required reason = self.reason_for_application or order.x_fc_reason_for_application no_prev_funding_reasons = ['first_access', 'mod_non_adp'] if reason and reason not in no_prev_funding_reasons: if not self.previous_funding_date and not order.x_fc_previous_funding_date: missing.append('Previous Funding Date') # Check documents if not order.x_fc_original_application: missing.append('Original ADP Application (upload in Application Received step)') if not order.x_fc_signed_pages_11_12: missing.append('Page 11 & 12 Signed (upload in Application Received step)') if missing: raise UserError( "Cannot mark as Ready for Submission.\n\n" "Required fields/documents missing:\n• " + "\n• ".join(missing) ) # Build update values update_vals = { 'x_fc_adp_application_status': 'ready_submission', 'x_fc_claim_authorization_date': self.claim_authorization_date, } # Only update if new values provided if self.client_ref_1: update_vals['x_fc_client_ref_1'] = self.client_ref_1 if self.client_ref_2: update_vals['x_fc_client_ref_2'] = self.client_ref_2 if self.reason_for_application: update_vals['x_fc_reason_for_application'] = self.reason_for_application if self.previous_funding_date: update_vals['x_fc_previous_funding_date'] = self.previous_funding_date # Update sale order order.with_context(skip_status_validation=True).write(update_vals) # Post to chatter reason_label = '' if self.reason_for_application: reason_label = dict(self._fields['reason_for_application'].selection or []).get( self.reason_for_application, '' ) order.message_post( body=Markup( '
' '

Ready for Submission

' f'

Authorization Date: {self.claim_authorization_date.strftime("%B %d, %Y")}

' f'{f"

Reason: {reason_label}

" if reason_label else ""}' '

Application is ready to be submitted to ADP. Use "Submit Application" to proceed.

' '
' ), message_type='notification', subtype_xmlid='mail.mt_note', ) return {'type': 'ir.actions.act_window_close'}