# -*- coding: utf-8 -*- # Copyright 2024-2026 Nexa Systems Inc. # License OPL-1 (Odoo Proprietary License v1.0) from odoo import models, fields, api, _ from odoo.exceptions import UserError import base64 import logging _logger = logging.getLogger(__name__) class OdspSubmitToOdspWizard(models.TransientModel): _name = 'fusion_claims.submit.to.odsp.wizard' _description = 'Submit Quotation & Authorizer Letter to ODSP' sale_order_id = fields.Many2one('sale.order', required=True, readonly=True) client_name = fields.Char(string='Client Name', readonly=True) member_id = fields.Char(string='ODSP Member ID', readonly=True) order_name = fields.Char(string='Order #', readonly=True) odsp_office_id = fields.Many2one( 'res.partner', string='ODSP Office', domain="[('x_fc_contact_type', '=', 'odsp_office')]", help='Override the ODSP office for this submission', ) authorizer_letter = fields.Binary( string='Authorizer Letter', help='Upload the authorizer letter to include in the submission', ) authorizer_letter_filename = fields.Char(string='Authorizer Letter Filename') email_body_notes = fields.Text( string='Email Body Notes', help='Notes to include at the top of the email body (e.g. urgency, special instructions)', ) @api.model def default_get(self, fields_list): res = super().default_get(fields_list) order_id = self.env.context.get('active_id') if order_id: order = self.env['sale.order'].browse(order_id) res.update({ 'sale_order_id': order.id, 'client_name': order.partner_id.name or '', 'member_id': order.x_fc_odsp_member_id or '', 'order_name': order.name or '', 'odsp_office_id': order.x_fc_odsp_office_id.id if order.x_fc_odsp_office_id else False, }) if order.x_fc_odsp_authorizer_letter: res['authorizer_letter'] = order.x_fc_odsp_authorizer_letter res['authorizer_letter_filename'] = order.x_fc_odsp_authorizer_letter_filename return res def _sync_odsp_office(self): """Sync the selected ODSP office back to the sale order.""" if self.odsp_office_id and self.odsp_office_id != self.sale_order_id.x_fc_odsp_office_id: self.sale_order_id.x_fc_odsp_office_id = self.odsp_office_id def _generate_attachments(self): """Generate quotation PDF and authorizer letter attachment, return list of ir.attachment IDs.""" order = self.sale_order_id Attachment = self.env['ir.attachment'].sudo() att_ids = [] report = self.env.ref('sale.action_report_saleorder') quote_pdf, _ct = report._render_qweb_pdf(report.id, [order.id]) quote_filename = f'{order.name}.pdf' quote_att = Attachment.create({ 'name': quote_filename, 'type': 'binary', 'datas': base64.b64encode(quote_pdf), 'res_model': 'sale.order', 'res_id': order.id, 'mimetype': 'application/pdf', }) att_ids.append(quote_att.id) if self.authorizer_letter: letter_filename = self.authorizer_letter_filename or 'Authorizer_Letter.pdf' order.write({ 'x_fc_odsp_authorizer_letter': self.authorizer_letter, 'x_fc_odsp_authorizer_letter_filename': letter_filename, }) letter_att = Attachment.create({ 'name': letter_filename, 'type': 'binary', 'datas': self.authorizer_letter, 'res_model': 'sale.order', 'res_id': order.id, 'mimetype': 'application/pdf', }) att_ids.append(letter_att.id) return att_ids def _advance_status(self, order): """Advance status to submitted_to_odsp.""" current = order._get_odsp_status() if current in ('quotation', 'documents_ready'): order._odsp_advance_status('submitted_to_odsp', "Quotation and authorizer letter submitted to ODSP.") def action_send_email(self): """Generate quotation PDF, attach authorizer letter, and email to ODSP office.""" self.ensure_one() self._sync_odsp_office() order = self.sale_order_id office = self.odsp_office_id or order.x_fc_odsp_office_id if not office or not office.email: raise UserError(_( "No ODSP Office with an email address is set. " "Please select an ODSP Office before sending." )) att_ids = self._generate_attachments() order._send_odsp_submission_email( attachment_ids=att_ids, email_body_notes=self.email_body_notes, ) self._advance_status(order) order.message_post( body=_("Quotation and authorizer letter emailed to %s.") % office.name, message_type='comment', attachment_ids=att_ids, ) return { 'type': 'ir.actions.client', 'tag': 'display_notification', 'params': { 'title': _('Email Sent'), 'message': _('Documents emailed to %s.') % office.email, 'type': 'success', 'sticky': False, 'next': {'type': 'ir.actions.act_window_close'}, }, } def action_send_fax(self): """Generate quotation PDF, attach authorizer letter, and open fax wizard.""" self.ensure_one() self._sync_odsp_office() order = self.sale_order_id office = self.odsp_office_id or order.x_fc_odsp_office_id att_ids = self._generate_attachments() self._advance_status(order) ctx = { 'default_sale_order_id': order.id, 'default_partner_id': office.id if office else False, 'default_generate_pdf': False, 'forward_attachment_ids': att_ids, } if office and hasattr(office, 'x_ff_fax_number') and office.x_ff_fax_number: ctx['default_fax_number'] = office.x_ff_fax_number return { 'type': 'ir.actions.act_window', 'name': _('Send Fax - ODSP Submission'), 'res_model': 'fusion_faxes.send.fax.wizard', 'view_mode': 'form', 'target': 'new', 'context': ctx, } def action_send_fax_and_email(self): """Generate documents, send email first, then open fax wizard.""" self.ensure_one() self._sync_odsp_office() order = self.sale_order_id office = self.odsp_office_id or order.x_fc_odsp_office_id if not office or not office.email: raise UserError(_( "No ODSP Office with an email address is set. " "Please select an ODSP Office before sending." )) att_ids = self._generate_attachments() order._send_odsp_submission_email( attachment_ids=att_ids, email_body_notes=self.email_body_notes, ) self._advance_status(order) order.message_post( body=_("Quotation and authorizer letter emailed to %s.") % office.name, message_type='comment', attachment_ids=att_ids, ) ctx = { 'default_sale_order_id': order.id, 'default_partner_id': office.id, 'default_generate_pdf': False, 'forward_attachment_ids': att_ids, } if hasattr(office, 'x_ff_fax_number') and office.x_ff_fax_number: ctx['default_fax_number'] = office.x_ff_fax_number fax_action = { 'type': 'ir.actions.act_window', 'name': _('Send Fax - ODSP Submission'), 'res_model': 'fusion_faxes.send.fax.wizard', 'view_mode': 'form', 'target': 'new', 'context': ctx, } return { 'type': 'ir.actions.client', 'tag': 'display_notification', 'params': { 'title': _('Email Sent'), 'message': _('Email sent to %s. Now proceeding to fax...') % office.email, 'type': 'success', 'sticky': False, 'next': fax_action, }, }