# -*- 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 datetime import datetime, timedelta from markupsafe import Markup import logging _logger = logging.getLogger(__name__) class ScheduleAssessmentWizard(models.TransientModel): """Wizard to schedule an assessment and create a calendar event.""" _name = 'fusion_claims.schedule.assessment.wizard' _description = 'Schedule Assessment Wizard' sale_order_id = fields.Many2one( 'sale.order', string='Sale Order', required=True, readonly=True, ) # Assessment Details assessment_date = fields.Date( string='Assessment Date', required=True, default=fields.Date.context_today, ) assessment_time = fields.Float( string='Assessment Time', required=True, default=9.0, # 9:00 AM help='Time in 24-hour format (e.g., 14.5 = 2:30 PM)', ) duration = fields.Float( string='Duration (hours)', required=True, default=2.0, ) # Location and Notes location = fields.Char( string='Location', help='Assessment location (client address, etc.)', ) notes = fields.Text( string='Notes', help='Additional notes for the assessment', ) # Attendees assessor_id = fields.Many2one( 'res.users', string='Assessor', default=lambda self: self.env.user, required=True, help='User who will conduct the assessment', ) # Calendar options create_calendar_event = fields.Boolean( string='Create Calendar Event', default=True, help='Create an event in Odoo calendar', ) send_reminder = fields.Boolean( string='Send Reminder', default=True, help='Send email reminder before the assessment', ) @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 location with client address if available if order.partner_id: partner = order.partner_id address_parts = [ partner.street, partner.street2, partner.city, partner.state_id.name if partner.state_id else None, partner.zip, ] res['location'] = ', '.join(filter(None, address_parts)) return res def action_schedule(self): """Schedule the assessment and optionally create a calendar event.""" self.ensure_one() order = self.sale_order_id # Validate status if order.x_fc_adp_application_status != 'quotation': raise UserError("Can only schedule assessment from 'Quotation' status.") # Calculate datetime assessment_datetime = datetime.combine( self.assessment_date, datetime.min.time() ) + timedelta(hours=self.assessment_time) # Create calendar event if requested calendar_event = None if self.create_calendar_event: calendar_event = self._create_calendar_event(assessment_datetime) # Update sale order order.with_context(skip_status_validation=True).write({ 'x_fc_adp_application_status': 'assessment_scheduled', 'x_fc_assessment_start_date': self.assessment_date, }) # Post to chatter time_str = self._format_time(self.assessment_time) event_link = '' if calendar_event: event_link = f'

View Calendar Event

' order.message_post( body=Markup( '
' '

Assessment Scheduled

' f'

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

' f'

Time: {time_str}

' f'

Duration: {self.duration} hour(s)

' f'

Assessor: {self.assessor_id.name}

' f'{f"

Location: {self.location}

" if self.location else ""}' f'{f"

Notes: {self.notes}

" if self.notes else ""}' f'{event_link}' '
' ), message_type='notification', subtype_xmlid='mail.mt_note', ) return {'type': 'ir.actions.act_window_close'} def _create_calendar_event(self, start_datetime): """Create a calendar event for the assessment.""" order = self.sale_order_id end_datetime = start_datetime + timedelta(hours=self.duration) # Build attendee list partner_ids = [self.assessor_id.partner_id.id] if order.partner_id: partner_ids.append(order.partner_id.id) event_vals = { 'name': f'ADP Assessment - {order.partner_id.name} ({order.name})', 'start': start_datetime, 'stop': end_datetime, 'allday': False, 'location': self.location or '', 'description': self._build_event_description(), 'partner_ids': [(6, 0, partner_ids)], 'user_id': self.assessor_id.id, } # Add alarm if reminder requested if self.send_reminder: # Find or create a 1-day email reminder alarm = self.env['calendar.alarm'].search([ ('alarm_type', '=', 'email'), ('duration', '=', 1), ('interval', '=', 'days'), ], limit=1) if not alarm: alarm = self.env['calendar.alarm'].create({ 'name': '1 Day Before', 'alarm_type': 'email', 'duration': 1, 'interval': 'days', }) event_vals['alarm_ids'] = [(6, 0, [alarm.id])] return self.env['calendar.event'].create(event_vals) def _build_event_description(self): """Build the calendar event description.""" order = self.sale_order_id lines = [ f"ADP Assessment for {order.partner_id.name}", f"Sale Order: {order.name}", "", ] if order.x_fc_reason_for_application: reason_label = dict(order._fields['x_fc_reason_for_application'].selection or []).get( order.x_fc_reason_for_application, 'N/A' ) lines.append(f"Reason: {reason_label}") if self.notes: lines.append("") lines.append(f"Notes: {self.notes}") return '\n'.join(lines) def _format_time(self, time_float): """Convert float time (e.g., 14.5) to readable format (2:30 PM).""" hours = int(time_float) minutes = int((time_float - hours) * 60) period = 'AM' if hours < 12 else 'PM' display_hours = hours if hours <= 12 else hours - 12 if display_hours == 0: display_hours = 12 return f"{display_hours}:{minutes:02d} {period}"