# -*- coding: utf-8 -*- # Copyright 2024-2026 Nexa Systems Inc. # License OPL-1 (Odoo Proprietary License v1.0) # Part of the Fusion Claim Assistant product family. from odoo import api, fields, models from markupsafe import Markup import logging _logger = logging.getLogger(__name__) class FusionSubmissionHistory(models.Model): """Track submission history for ADP applications. Each record represents one submission or resubmission to ADP, including the documents submitted, the result, and any rejection reasons. """ _name = 'fusion.submission.history' _description = 'ADP Submission History' _order = 'submission_date desc, id desc' _rec_name = 'display_name' # ========================================================================== # RELATIONSHIPS # ========================================================================== sale_order_id = fields.Many2one( 'sale.order', string='Sale Order', required=True, ondelete='cascade', index=True, ) # ========================================================================== # SUBMISSION DETAILS # ========================================================================== display_name = fields.Char( string='Display Name', compute='_compute_display_name', store=True, ) submission_number = fields.Integer( string='Submission #', default=1, help='Sequence number for this submission (1 = first submission, 2+ = resubmissions)', ) submission_type = fields.Selection( selection=[ ('initial', 'Initial Submission'), ('resubmission', 'Resubmission'), ('correction', 'Correction'), ], string='Type', default='initial', ) submission_date = fields.Date( string='Submission Date', default=fields.Date.today, required=True, ) submitted_by_id = fields.Many2one( 'res.users', string='Submitted By', default=lambda self: self.env.user, ) # ========================================================================== # DOCUMENTS SUBMITTED (copies at time of submission) # ========================================================================== final_application = fields.Binary( string='Final Application (PDF)', attachment=True, help='Copy of the final application PDF at time of submission', ) final_application_filename = fields.Char( string='Final Application Filename', ) xml_file = fields.Binary( string='XML File', attachment=True, help='Copy of the XML file at time of submission', ) xml_filename = fields.Char( string='XML Filename', ) # ========================================================================== # RESULT TRACKING # ========================================================================== result = fields.Selection( selection=[ ('pending', 'Pending'), ('accepted', 'Accepted'), ('rejected', 'Rejected'), ('approved', 'Approved'), ('denied', 'Denied'), ], string='Result', default='pending', ) result_date = fields.Date( string='Result Date', help='Date when the result was received from ADP', ) # ========================================================================== # REJECTION DETAILS (if rejected) # ========================================================================== rejection_reason = fields.Selection( selection=[ ('name_correction', 'Name Correction Needed'), ('healthcard_correction', 'Health Card Correction Needed'), ('duplicate_claim', 'Duplicate Claim Exists'), ('xml_format_error', 'XML Format/Validation Error'), ('missing_info', 'Missing Required Information'), ('other', 'Other'), ], string='Rejection Reason', ) rejection_details = fields.Text( string='Rejection Details', help='Additional details about the rejection', ) # ========================================================================== # CORRECTION NOTES (for resubmissions) # ========================================================================== correction_notes = fields.Text( string='Correction Notes', help='Notes about what was corrected for this resubmission', ) # ========================================================================== # COMPUTED FIELDS # ========================================================================== @api.depends('sale_order_id', 'submission_number', 'submission_type') def _compute_display_name(self): for record in self: order_name = record.sale_order_id.name or 'New' type_label = dict(record._fields['submission_type'].selection).get( record.submission_type, record.submission_type ) record.display_name = f"{order_name} - Submission #{record.submission_number} ({type_label})" # ========================================================================== # HELPER METHODS # ========================================================================== @api.model def create_from_submission(self, sale_order, submission_type='initial', correction_notes=None): """Create a submission history record from a sale order submission. Args: sale_order: The sale.order record being submitted submission_type: 'initial', 'resubmission', or 'correction' correction_notes: Optional notes about corrections made Returns: The created fusion.submission.history record """ # Get next submission number existing_count = self.search_count([('sale_order_id', '=', sale_order.id)]) submission_number = existing_count + 1 # If submission_number > 1, it's a resubmission if submission_number > 1 and submission_type == 'initial': submission_type = 'resubmission' vals = { 'sale_order_id': sale_order.id, 'submission_number': submission_number, 'submission_type': submission_type, 'submission_date': fields.Date.today(), 'submitted_by_id': self.env.user.id, 'correction_notes': correction_notes, } # Copy current documents if sale_order.x_fc_final_submitted_application: vals['final_application'] = sale_order.x_fc_final_submitted_application vals['final_application_filename'] = sale_order.x_fc_final_application_filename if sale_order.x_fc_xml_file: vals['xml_file'] = sale_order.x_fc_xml_file vals['xml_filename'] = sale_order.x_fc_xml_filename record = self.create(vals) # Post to chatter sale_order.message_post( body=Markup( '
' f' Submission #{submission_number} Recorded
' '| Type: | {dict(self._fields["submission_type"].selection).get(submission_type)} |
| Date: | {fields.Date.today().strftime("%B %d, %Y")} |
| By: | {self.env.user.name} |
Corrections: {correction_notes}
' if correction_notes else '') + '