671 lines
36 KiB
Python
671 lines
36 KiB
Python
# -*- coding: utf-8 -*-
|
|
# Copyright 2024-2026 Nexa Systems Inc.
|
|
# License OPL-1 (Odoo Proprietary License v1.0)
|
|
|
|
import base64
|
|
import json
|
|
import logging
|
|
import xml.etree.ElementTree as ET
|
|
|
|
from odoo import api, fields, models
|
|
|
|
_logger = logging.getLogger(__name__)
|
|
|
|
|
|
class FusionAdpApplicationData(models.Model):
|
|
_name = 'fusion.adp.application.data'
|
|
_description = 'ADP Application Data (Parsed XML)'
|
|
_order = 'application_date desc, id desc'
|
|
_rec_name = 'display_name'
|
|
|
|
# ------------------------------------------------------------------
|
|
# LINKAGE
|
|
# ------------------------------------------------------------------
|
|
profile_id = fields.Many2one(
|
|
'fusion.client.profile', string='Client Profile',
|
|
ondelete='cascade', index=True,
|
|
)
|
|
sale_order_id = fields.Many2one(
|
|
'sale.order', string='Sale Order',
|
|
ondelete='set null', index=True,
|
|
)
|
|
display_name = fields.Char(
|
|
string='Name', compute='_compute_display_name', store=True,
|
|
)
|
|
|
|
# ------------------------------------------------------------------
|
|
# COMPLETE XML DATA (for round-trip export fidelity)
|
|
# ------------------------------------------------------------------
|
|
xml_data_json = fields.Text(
|
|
string='Complete XML Data (JSON)',
|
|
help='Complete 1:1 JSON representation of all ~300 XML fields for export',
|
|
)
|
|
raw_xml = fields.Text(string='Raw XML Data')
|
|
|
|
# ------------------------------------------------------------------
|
|
# APPLICATION METADATA
|
|
# ------------------------------------------------------------------
|
|
device_category = fields.Selection([
|
|
('AA', 'Ambulation Aids (Section 2a)'),
|
|
('MD', 'Mobility Devices (Section 2b/2c)'),
|
|
('PS', 'Positioning/Seating (Section 2d)'),
|
|
('MX', 'Mixed/Multiple Sections'),
|
|
], string='Device Category')
|
|
version_number = fields.Char(string='Form Version')
|
|
application_date = fields.Date(string='Application Date')
|
|
|
|
# ------------------------------------------------------------------
|
|
# SECTION 1 - APPLICANT BIOGRAPHICAL INFORMATION
|
|
# ------------------------------------------------------------------
|
|
applicant_last_name = fields.Char(string='Last Name')
|
|
applicant_first_name = fields.Char(string='First Name')
|
|
applicant_middle_initial = fields.Char(string='Middle Initial')
|
|
health_card_number = fields.Char(string='Health Card Number', index=True)
|
|
health_card_version = fields.Char(string='Health Card Version')
|
|
date_of_birth = fields.Date(string='Date of Birth')
|
|
ltch_name = fields.Char(string='Long-Term Care Home')
|
|
|
|
# Address (individual fields, not combined)
|
|
unit_number = fields.Char(string='Unit Number')
|
|
street_number = fields.Char(string='Street Number')
|
|
street_name = fields.Char(string='Street Name')
|
|
rural_route = fields.Char(string='Lot/Concession/Rural Route')
|
|
city = fields.Char(string='City', index=True)
|
|
province = fields.Char(string='Province')
|
|
postal_code = fields.Char(string='Postal Code')
|
|
|
|
# Contact
|
|
home_phone = fields.Char(string='Home Phone')
|
|
business_phone = fields.Char(string='Business Phone')
|
|
phone_extension = fields.Char(string='Phone Extension')
|
|
|
|
# ------------------------------------------------------------------
|
|
# SECTION 1 - CONFIRMATION OF BENEFITS
|
|
# ------------------------------------------------------------------
|
|
receives_social_assistance = fields.Boolean(string='Receives Social Assistance')
|
|
benefit_type = fields.Char(string='Benefit Program')
|
|
benefit_owp = fields.Boolean(string='Ontario Works Program (OWP)')
|
|
benefit_odsp = fields.Boolean(string='Ontario Disability Support Program (ODSP)')
|
|
benefit_acsd = fields.Boolean(string='Assistance to Children with Severe Disabilities (ACSD)')
|
|
wsib_eligible = fields.Boolean(string='WSIB Eligible')
|
|
vac_eligible = fields.Boolean(string='Veterans Affairs Canada (VAC) Eligible')
|
|
|
|
# ------------------------------------------------------------------
|
|
# SECTION 2 - DEVICES AND ELIGIBILITY
|
|
# ------------------------------------------------------------------
|
|
medical_condition = fields.Text(string='Medical Condition / Diagnosis')
|
|
mobility_status = fields.Text(string='Functional Mobility Status')
|
|
|
|
# Previously funded equipment
|
|
prev_funded_none = fields.Boolean(string='None Previously Funded')
|
|
prev_funded_forearm = fields.Boolean(string='Forearm Crutches (Previously)')
|
|
prev_funded_wheeled = fields.Boolean(string='Wheeled Walker (Previously)')
|
|
prev_funded_manual = fields.Boolean(string='Manual Wheelchair (Previously)')
|
|
prev_funded_power = fields.Boolean(string='Power Wheelchair (Previously)')
|
|
prev_funded_addon = fields.Boolean(string='Power Add-On Device (Previously)')
|
|
prev_funded_scooter = fields.Boolean(string='Power Scooter (Previously)')
|
|
prev_funded_seating = fields.Boolean(string='Positioning Devices (Previously)')
|
|
prev_funded_tilt = fields.Boolean(string='Power Tilt System (Previously)')
|
|
prev_funded_recline = fields.Boolean(string='Power Recline System (Previously)')
|
|
prev_funded_legrests = fields.Boolean(string='Power Elevating Leg Rests (Previously)')
|
|
prev_funded_frame = fields.Boolean(string='Paediatric Standing Frame (Previously)')
|
|
prev_funded_stroller = fields.Boolean(string='Paediatric Specialty Stroller (Previously)')
|
|
|
|
# Devices currently required
|
|
device_forearm_crutches = fields.Boolean(string='Forearm Crutches')
|
|
device_wheeled_walker = fields.Boolean(string='Wheeled Walker')
|
|
device_manual_wheelchair = fields.Boolean(string='Manual Wheelchair')
|
|
device_ambulation_manual = fields.Boolean(string='Ambulation Aid + Manual Wheelchair')
|
|
device_dependent_wheelchair = fields.Boolean(string='Manual Wheelchair (Dependent)')
|
|
device_dynamic_tilt = fields.Boolean(string='Manual Dynamic Tilt Wheelchair')
|
|
device_manual_dynamic = fields.Boolean(string='Manual Dynamic Tilt (Dependent)')
|
|
device_manual_power_addon = fields.Boolean(string='Manual Wheelchair with Power Add-On')
|
|
device_power_base = fields.Boolean(string='Power Base Only')
|
|
device_power_scooter = fields.Boolean(string='Power Scooter Only')
|
|
device_ambulation_power = fields.Boolean(string='Ambulation Aid + Power Base/Scooter')
|
|
device_positioning = fields.Boolean(string='Positioning Devices (Seating)')
|
|
device_high_tech = fields.Boolean(string='High Technology Power Base')
|
|
device_standing_frame = fields.Boolean(string='Paediatric Standing Frame')
|
|
device_adp_funded_mods = fields.Boolean(string='Modifications to ADP Funded Device(s)')
|
|
device_non_adp_funded_mods = fields.Boolean(string='Modifications to Non ADP Funded Device(s)')
|
|
|
|
# ------------------------------------------------------------------
|
|
# SECTION 2A - AMBULATION AIDS (Walkers)
|
|
# ------------------------------------------------------------------
|
|
s2a_base_device = fields.Char(string='Walker Type')
|
|
s2a_paediatric_frame = fields.Char(string='Paediatric Frame')
|
|
s2a_forearm_crutches = fields.Char(string='Forearm Crutches Type')
|
|
s2a_none = fields.Char(string='None Selected')
|
|
s2a_reason = fields.Char(string='Reason for Application')
|
|
s2a_replacement_status = fields.Char(string='Replacement - Mobility Status Change')
|
|
s2a_replacement_size = fields.Char(string='Replacement - Body Size Change')
|
|
s2a_replacement_adp = fields.Char(string='Replacement - Equipment Worn Out')
|
|
s2a_replacement_special = fields.Char(string='Replacement - Special Circumstances')
|
|
s2a_confirm1 = fields.Char(string='Confirmation 1')
|
|
s2a_confirm2 = fields.Char(string='Confirmation 2')
|
|
s2a_confirm3 = fields.Char(string='Confirmation 3')
|
|
s2a_confirm4 = fields.Char(string='Confirmation 4')
|
|
s2a_confirm5 = fields.Char(string='Confirmation 5')
|
|
s2a_confirm6 = fields.Char(string='Confirmation 6')
|
|
# Prescription
|
|
s2a_seat_height = fields.Char(string='Seat Height')
|
|
s2a_seat_height_unit = fields.Char(string='Seat Height Unit')
|
|
s2a_handle_height = fields.Char(string='Push Handle Height')
|
|
s2a_handle_height_unit = fields.Char(string='Handle Height Unit')
|
|
s2a_hand_grips = fields.Char(string='Hand Grips')
|
|
s2a_forearm_attachments = fields.Char(string='Forearm Attachments')
|
|
s2a_width_handles = fields.Char(string='Width Between Push Handles')
|
|
s2a_width_handles_unit = fields.Char(string='Width Handles Unit')
|
|
s2a_client_weight = fields.Char(string='Client Weight')
|
|
s2a_client_weight_unit = fields.Char(string='Client Weight Unit')
|
|
s2a_brakes = fields.Char(string='Brakes')
|
|
s2a_brake_type = fields.Char(string='Brake Type')
|
|
s2a_num_wheels = fields.Char(string='Number of Wheels')
|
|
s2a_wheel_size = fields.Char(string='Wheel Size')
|
|
s2a_back_support = fields.Char(string='Back Support')
|
|
# ADP options
|
|
s2a_adp_walker = fields.Char(string='ADP Adolescent Walker')
|
|
s2a_adp_frame = fields.Char(string='ADP Adolescent Frame')
|
|
s2a_adp_standing = fields.Char(string='ADP Adolescent Standing')
|
|
# Custom modifications
|
|
s2a_custom = fields.Char(string='Custom Modifications Required')
|
|
s2a_cost_labour = fields.Char(string='Cost of Labour')
|
|
|
|
# ------------------------------------------------------------------
|
|
# SECTION 2B - MANUAL WHEELCHAIRS
|
|
# ------------------------------------------------------------------
|
|
s2b_base_device = fields.Char(string='Manual Wheelchair Type')
|
|
s2b_power_addon = fields.Char(string='Power Add-On Device')
|
|
s2b_reason = fields.Char(string='Reason for Application')
|
|
s2b_replacement_status = fields.Char(string='Replacement - Mobility Status')
|
|
s2b_replacement_size = fields.Char(string='Replacement - Body Size')
|
|
s2b_replacement_adp = fields.Char(string='Replacement - Equipment Worn')
|
|
s2b_replacement_special = fields.Char(string='Replacement - Special')
|
|
s2b_confirm1 = fields.Char(string='Confirmation 1')
|
|
s2b_confirm2 = fields.Char(string='Confirmation 2')
|
|
s2b_confirm3 = fields.Char(string='Confirmation 3')
|
|
s2b_confirm4 = fields.Char(string='Confirmation 4')
|
|
s2b_confirm5 = fields.Char(string='Confirmation 5')
|
|
s2b_confirm6 = fields.Char(string='Confirmation 6')
|
|
s2b_confirm7 = fields.Char(string='Confirmation 7')
|
|
s2b_confirm8 = fields.Char(string='Confirmation 8')
|
|
s2b_confirm9 = fields.Char(string='Confirmation 9')
|
|
s2b_confirm10 = fields.Char(string='Confirmation 10')
|
|
s2b_confirm11 = fields.Char(string='Confirmation 11')
|
|
s2b_confirm12 = fields.Char(string='Confirmation 12')
|
|
s2b_confirm13 = fields.Char(string='Confirmation 13')
|
|
# Prescription
|
|
s2b_seat_width = fields.Char(string='Seat Width')
|
|
s2b_seat_width_unit = fields.Char(string='Seat Width Unit')
|
|
s2b_seat_depth = fields.Char(string='Seat Depth')
|
|
s2b_seat_depth_unit = fields.Char(string='Seat Depth Unit')
|
|
s2b_floor_height = fields.Char(string='Finished Seat to Floor Height')
|
|
s2b_floor_height_unit = fields.Char(string='Floor Height Unit')
|
|
s2b_cane_height = fields.Char(string='Back Cane Height')
|
|
s2b_cane_height_unit = fields.Char(string='Cane Height Unit')
|
|
s2b_back_height = fields.Char(string='Finished Back Height')
|
|
s2b_back_height_unit = fields.Char(string='Back Height Unit')
|
|
s2b_rest_length = fields.Char(string='Finished Leg Rest Length')
|
|
s2b_rest_length_unit = fields.Char(string='Rest Length Unit')
|
|
s2b_client_weight = fields.Char(string='Client Weight')
|
|
s2b_client_weight_unit = fields.Char(string='Client Weight Unit')
|
|
# Add-on options
|
|
s2b_adjustable_tension = fields.Boolean(string='Adjustable Tension Back Upholstery')
|
|
s2b_heavy_duty = fields.Boolean(string='Heavy Duty Cross Braces & Upholstery')
|
|
s2b_recliner = fields.Boolean(string='Recliner Option')
|
|
s2b_footplates = fields.Boolean(string='Angle Adjustable Footplates')
|
|
s2b_legrests = fields.Boolean(string='Elevating Legrests')
|
|
s2b_spoke = fields.Boolean(string='Spoke Protectors')
|
|
s2b_projected = fields.Boolean(string='Projected Handrims')
|
|
s2b_standard_manual = fields.Boolean(string='Standard Manual with Dynamic Tilt')
|
|
s2b_grade_aids = fields.Boolean(string='Grade Aids')
|
|
s2b_caster_pin = fields.Boolean(string='Caster Pin Locks')
|
|
s2b_amputee_axle = fields.Boolean(string='Amputee Axle Plates')
|
|
s2b_quick_release = fields.Boolean(string='Quick Release Axles')
|
|
s2b_stroller = fields.Boolean(string='Stroller Handles/Paediatric')
|
|
s2b_oxygen = fields.Boolean(string='Oxygen Tank Holder')
|
|
s2b_ventilator = fields.Boolean(string='Ventilator Tray')
|
|
s2b_titanium = fields.Boolean(string='Titanium Frame')
|
|
s2b_clothing_guards = fields.Boolean(string='Clothing Guards')
|
|
s2b_one_arm = fields.Boolean(string='One Arm/Lever Drive')
|
|
s2b_uni_lateral = fields.Boolean(string='Uni-Lateral Wheel Lock')
|
|
s2b_plastic = fields.Boolean(string='Plastic Coated Handrims')
|
|
s2b_rationale = fields.Text(string='Clinical Rationale')
|
|
s2b_custom = fields.Char(string='Custom Modifications Required')
|
|
s2b_cost_labour = fields.Char(string='Cost of Labour')
|
|
|
|
# ------------------------------------------------------------------
|
|
# SECTION 2C - POWER BASES AND POWER SCOOTERS
|
|
# ------------------------------------------------------------------
|
|
s2c_base_device = fields.Char(string='Power Base/Scooter Type')
|
|
s2c_reason = fields.Char(string='Reason for Application')
|
|
s2c_replacement_status = fields.Char(string='Replacement - Mobility Status')
|
|
s2c_replacement_size = fields.Char(string='Replacement - Body Size')
|
|
s2c_replacement_adp = fields.Char(string='Replacement - Equipment Worn')
|
|
s2c_replacement_special = fields.Char(string='Replacement - Special')
|
|
s2c_confirm1 = fields.Char(string='Power Base Confirmation 1')
|
|
s2c_confirm2 = fields.Char(string='Power Base Confirmation 2')
|
|
s2c_confirm3 = fields.Char(string='Scooter Confirmation 1')
|
|
s2c_confirm4 = fields.Char(string='Scooter Confirmation 2')
|
|
s2c_confirm5 = fields.Char(string='Scooter Confirmation 3')
|
|
# Prescription
|
|
s2c_seat_width = fields.Char(string='Seat Width')
|
|
s2c_seat_width_unit = fields.Char(string='Seat Width Unit')
|
|
s2c_back_height = fields.Char(string='Finished Back Height')
|
|
s2c_back_height_unit = fields.Char(string='Back Height Unit')
|
|
s2c_floor_height = fields.Char(string='Finished Seat to Floor Height')
|
|
s2c_floor_height_unit = fields.Char(string='Floor Height Unit')
|
|
s2c_rest_length = fields.Char(string='Leg Rest Length')
|
|
s2c_rest_length_unit = fields.Char(string='Rest Length Unit')
|
|
s2c_seat_depth = fields.Char(string='Seat Depth')
|
|
s2c_seat_depth_unit = fields.Char(string='Seat Depth Unit')
|
|
s2c_client_weight = fields.Char(string='Client Weight')
|
|
s2c_client_weight_unit = fields.Char(string='Client Weight Unit')
|
|
# Add-on options
|
|
s2c_adjustable_tension = fields.Boolean(string='Adjustable Tension Back Upholstery')
|
|
s2c_midline = fields.Boolean(string='Midline Control')
|
|
s2c_manual_recline = fields.Boolean(string='Manual Recline Option')
|
|
s2c_footplates = fields.Boolean(string='Angle Adjustable Footplates')
|
|
s2c_legrests = fields.Boolean(string='Manual Elevating Legrests')
|
|
s2c_swingaway = fields.Boolean(string='Swingaway Mounting Bracket')
|
|
s2c_one_piece = fields.Boolean(string='One Piece 90/90 Front Riggings')
|
|
s2c_seat_package_1 = fields.Boolean(string='Seat Package 1 for Power Bases')
|
|
s2c_seat_package_2 = fields.Boolean(string='Seat Package 2 for Power Bases')
|
|
s2c_oxygen = fields.Boolean(string='Oxygen Tank Holder')
|
|
s2c_ventilator = fields.Boolean(string='Ventilator Tray')
|
|
# Specialty controls
|
|
s2c_sp_controls_1 = fields.Boolean(string='Specialty Controls 1 - Non Standard Joystick')
|
|
s2c_sp_controls_2 = fields.Boolean(string='Specialty Controls 2 - Chin/Rim Control')
|
|
s2c_sp_controls_3 = fields.Boolean(string='Specialty Controls 3 - Simple Touch')
|
|
s2c_sp_controls_4 = fields.Boolean(string='Specialty Controls 4 - Proximity Control')
|
|
s2c_sp_controls_5 = fields.Boolean(string='Specialty Controls 5 - Breath Control')
|
|
s2c_sp_controls_6 = fields.Boolean(string='Specialty Controls 6 - Scanners')
|
|
s2c_auto_correction = fields.Boolean(string='Auto Correction System')
|
|
s2c_rationale = fields.Text(string='Clinical Rationale')
|
|
# Power positioning
|
|
s2c_power_tilt = fields.Boolean(string='Power Tilt Only')
|
|
s2c_power_recline = fields.Boolean(string='Power Recline Only')
|
|
s2c_tilt_and_recline = fields.Boolean(string='Power Tilt and Recline')
|
|
s2c_power_elevating = fields.Boolean(string='Power Elevating Footrests')
|
|
s2c_control_box = fields.Boolean(string='Multi-Function Control Box')
|
|
s2c_custom = fields.Char(string='Custom Modifications Required')
|
|
s2c_cost_labour = fields.Char(string='Cost of Labour')
|
|
|
|
# ------------------------------------------------------------------
|
|
# SECTION 2D - POSITIONING DEVICES (SEATING) FOR MOBILITY
|
|
# ------------------------------------------------------------------
|
|
# Seat Cushion
|
|
s2d_seat_modular = fields.Boolean(string='Seat Cushion - Modular')
|
|
s2d_seat_custom = fields.Boolean(string='Seat Cushion - Custom Fabricated')
|
|
s2d_seat_cover_modular = fields.Boolean(string='Seat Cover - Modular')
|
|
s2d_seat_cover_custom = fields.Boolean(string='Seat Cover - Custom Fabricated')
|
|
s2d_seat_option_modular = fields.Boolean(string='Seat Options - Modular')
|
|
s2d_seat_option_custom = fields.Boolean(string='Seat Options - Custom Fabricated')
|
|
s2d_seat_hardware_modular = fields.Boolean(string='Seat Hardware - Modular')
|
|
s2d_seat_hardware_custom = fields.Boolean(string='Seat Hardware - Custom Fabricated')
|
|
s2d_adductor_modular = fields.Boolean(string='Pommel/Adductors - Modular')
|
|
s2d_adductor_custom = fields.Boolean(string='Pommel/Adductors - Custom Fabricated')
|
|
s2d_pommel_custom = fields.Boolean(string='Pommel Hardware - Custom Fabricated')
|
|
# Back Support
|
|
s2d_back_modular = fields.Boolean(string='Back Support - Modular')
|
|
s2d_back_custom = fields.Boolean(string='Back Support - Custom Fabricated')
|
|
s2d_back_option_modular = fields.Boolean(string='Back Options - Modular')
|
|
s2d_back_option_custom = fields.Boolean(string='Back Options - Custom Fabricated')
|
|
s2d_back_cover_custom = fields.Boolean(string='Back Cover - Custom Fabricated')
|
|
s2d_back_hardware_modular = fields.Boolean(string='Back Hardware - Modular')
|
|
s2d_back_hardware_custom = fields.Boolean(string='Back Hardware - Custom Fabricated')
|
|
# Complete Assembly
|
|
s2d_complete_modular = fields.Boolean(string='Complete Assembly - Modular')
|
|
s2d_complete_custom = fields.Boolean(string='Complete Assembly - Custom Fabricated')
|
|
# Headrest/Neckrest
|
|
s2d_headrest_modular = fields.Boolean(string='Headrest/Neckrest - Modular')
|
|
s2d_headrest_custom = fields.Boolean(string='Headrest/Neckrest - Custom Fabricated')
|
|
s2d_head_option_custom = fields.Boolean(string='Headrest Options - Custom Fabricated')
|
|
s2d_head_hardware_modular = fields.Boolean(string='Headrest Hardware - Modular')
|
|
s2d_head_hardware_custom = fields.Boolean(string='Headrest Hardware - Custom Fabricated')
|
|
# Positioning Belts
|
|
s2d_belt_modular = fields.Boolean(string='Positioning Belt - Modular')
|
|
s2d_belt_custom = fields.Boolean(string='Positioning Belt - Custom Fabricated')
|
|
s2d_belt_option_custom = fields.Boolean(string='Belt Options - Custom Fabricated')
|
|
# Arm Supports
|
|
s2d_arm_modular = fields.Boolean(string='Arm Support - Modular')
|
|
s2d_arm_custom = fields.Boolean(string='Arm Support - Custom Fabricated')
|
|
s2d_arm_option_modular = fields.Boolean(string='Arm Options - Modular')
|
|
s2d_arm_option_custom = fields.Boolean(string='Arm Options - Custom Fabricated')
|
|
s2d_arm_hardware_modular = fields.Boolean(string='Arm Hardware - Modular')
|
|
s2d_arm_hardware_custom = fields.Boolean(string='Arm Hardware - Custom Fabricated')
|
|
# Tray
|
|
s2d_tray_modular = fields.Boolean(string='Tray - Modular')
|
|
s2d_tray_custom = fields.Boolean(string='Tray - Custom Fabricated')
|
|
s2d_tray_option_modular = fields.Boolean(string='Tray Options - Modular')
|
|
s2d_tray_option_custom = fields.Boolean(string='Tray Options - Custom Fabricated')
|
|
# Lateral Supports
|
|
s2d_lateral_modular = fields.Boolean(string='Lateral Support - Modular')
|
|
s2d_lateral_custom = fields.Boolean(string='Lateral Support - Custom Fabricated')
|
|
s2d_lateral_option_custom = fields.Boolean(string='Lateral Options - Custom Fabricated')
|
|
s2d_lateral_hardware_custom = fields.Boolean(string='Lateral Hardware - Custom Fabricated')
|
|
# Foot/Leg Supports
|
|
s2d_foot_modular = fields.Boolean(string='Foot/Leg Support - Modular')
|
|
s2d_foot_custom = fields.Boolean(string='Foot/Leg Support - Custom Fabricated')
|
|
s2d_foot_option_modular = fields.Boolean(string='Foot Options - Modular')
|
|
s2d_foot_option_custom = fields.Boolean(string='Foot Options - Custom Fabricated')
|
|
s2d_foot_hardware_modular = fields.Boolean(string='Foot Hardware - Modular')
|
|
s2d_foot_hardware_custom = fields.Boolean(string='Foot Hardware - Custom Fabricated')
|
|
# Seating reason and confirmations
|
|
s2d_reason = fields.Char(string='Reason for Application')
|
|
s2d_replacement_status = fields.Char(string='Replacement - Mobility Status')
|
|
s2d_replacement_size = fields.Char(string='Replacement - Body Size')
|
|
s2d_replacement_adp = fields.Char(string='Replacement - Equipment Worn')
|
|
s2d_replacement_special = fields.Char(string='Replacement - Special')
|
|
s2d_confirm1 = fields.Char(string='Seating Confirmation 1')
|
|
s2d_confirm2 = fields.Char(string='Seating Confirmation 2')
|
|
s2d_custom = fields.Char(string='Custom Modifications Required')
|
|
s2d_cost_labour = fields.Char(string='Cost of Labour')
|
|
|
|
# ------------------------------------------------------------------
|
|
# SECTION 3 - APPLICANT CONSENT AND SIGNATURE
|
|
# ------------------------------------------------------------------
|
|
consent_date = fields.Date(string='Consent Date')
|
|
consent_signed_by = fields.Selection([
|
|
('applicant', 'Applicant'),
|
|
('agent', 'Agent'),
|
|
], string='Signed By')
|
|
# Agent/Contact info (if signed by agent)
|
|
agent_relationship = fields.Char(string='Agent Relationship')
|
|
agent_last_name = fields.Char(string='Agent Last Name')
|
|
agent_first_name = fields.Char(string='Agent First Name')
|
|
agent_middle_initial = fields.Char(string='Agent Middle Initial')
|
|
agent_unit = fields.Char(string='Agent Unit')
|
|
agent_street_no = fields.Char(string='Agent Street Number')
|
|
agent_street_name = fields.Char(string='Agent Street Name')
|
|
agent_rural_route = fields.Char(string='Agent Rural Route')
|
|
agent_city = fields.Char(string='Agent City')
|
|
agent_province = fields.Char(string='Agent Province')
|
|
agent_postal_code = fields.Char(string='Agent Postal Code')
|
|
agent_home_phone = fields.Char(string='Agent Home Phone')
|
|
agent_bus_phone = fields.Char(string='Agent Business Phone')
|
|
agent_phone_ext = fields.Char(string='Agent Phone Ext')
|
|
|
|
# ------------------------------------------------------------------
|
|
# SECTION 4 - AUTHORIZER
|
|
# ------------------------------------------------------------------
|
|
authorizer_last_name = fields.Char(string='Authorizer Last Name')
|
|
authorizer_first_name = fields.Char(string='Authorizer First Name')
|
|
authorizer_phone = fields.Char(string='Authorizer Phone')
|
|
authorizer_phone_ext = fields.Char(string='Authorizer Phone Ext')
|
|
authorizer_adp_number = fields.Char(string='Authorizer ADP Registration Number')
|
|
assessment_date = fields.Date(string='Assessment Date')
|
|
|
|
# ------------------------------------------------------------------
|
|
# SECTION 4 - VENDOR 1
|
|
# ------------------------------------------------------------------
|
|
vendor_business_name = fields.Char(string='Vendor Business Name')
|
|
vendor_adp_number = fields.Char(string='Vendor ADP Registration Number')
|
|
vendor_representative = fields.Char(string='Vendor Representative (Last, First)')
|
|
vendor_position = fields.Char(string='Vendor Position Title')
|
|
vendor_location = fields.Char(string='Vendor Location')
|
|
vendor_phone = fields.Char(string='Vendor Phone')
|
|
vendor_phone_ext = fields.Char(string='Vendor Phone Ext')
|
|
vendor_sign_date = fields.Date(string='Vendor Sign Date')
|
|
|
|
# ------------------------------------------------------------------
|
|
# SECTION 4 - VENDOR 2
|
|
# ------------------------------------------------------------------
|
|
vendor2_business_name = fields.Char(string='Vendor 2 Business Name')
|
|
vendor2_adp_number = fields.Char(string='Vendor 2 ADP Registration')
|
|
vendor2_representative = fields.Char(string='Vendor 2 Representative')
|
|
vendor2_position = fields.Char(string='Vendor 2 Position')
|
|
vendor2_location = fields.Char(string='Vendor 2 Location')
|
|
vendor2_phone = fields.Char(string='Vendor 2 Phone')
|
|
vendor2_phone_ext = fields.Char(string='Vendor 2 Phone Ext')
|
|
vendor2_sign_date = fields.Date(string='Vendor 2 Sign Date')
|
|
|
|
# ------------------------------------------------------------------
|
|
# SECTION 4 - EQUIPMENT SPEC & PROOF OF DELIVERY
|
|
# ------------------------------------------------------------------
|
|
equip_vendor_invoice_no = fields.Char(string='Vendor Invoice Number')
|
|
equip_vendor_adp_reg = fields.Char(string='Vendor ADP Reg (Page 12)')
|
|
equip_cell1 = fields.Char(string='ADP Device Code')
|
|
equip_cell2 = fields.Char(string='Description of Item')
|
|
equip_cell3 = fields.Char(string='Base Device')
|
|
equip_cell4 = fields.Char(string='ADP Portion')
|
|
equip_cell5 = fields.Char(string='Client Portion')
|
|
pod_received_by = fields.Char(string='Proof of Delivery - Received By')
|
|
pod_date = fields.Date(string='Proof of Delivery Date')
|
|
|
|
# ------------------------------------------------------------------
|
|
# SECTION 4 - NOTE TO ADP (sections submitted checklist)
|
|
# ------------------------------------------------------------------
|
|
note_section1 = fields.Boolean(string='Section 1 Submitted')
|
|
note_section2a = fields.Boolean(string='Section 2a Submitted')
|
|
note_section2b = fields.Boolean(string='Section 2b Submitted')
|
|
note_section2c = fields.Boolean(string='Section 2c Submitted')
|
|
note_section2d = fields.Boolean(string='Section 2d Submitted')
|
|
note_section3and4 = fields.Boolean(string='Section 3 & 4 Submitted')
|
|
note_vendor_replacement = fields.Char(string='Vendor Quote - Replacement')
|
|
note_vendor_custom = fields.Char(string='Vendor Quote - Custom Modifications')
|
|
note_funding_chart = fields.Char(string='Justification for Funding Chart')
|
|
note_letter = fields.Char(string='Letter of Rationale')
|
|
|
|
# Computed summary
|
|
sections_submitted = fields.Char(
|
|
string='Sections Submitted',
|
|
compute='_compute_sections_submitted', store=True,
|
|
)
|
|
|
|
# Legacy compat fields
|
|
base_device = fields.Char(
|
|
string='Base Device Selected',
|
|
compute='_compute_base_device', store=True,
|
|
)
|
|
reason_for_application = fields.Char(
|
|
string='Reason for Application',
|
|
compute='_compute_reason', store=True,
|
|
)
|
|
|
|
# ------------------------------------------------------------------
|
|
# COMPUTED
|
|
# ------------------------------------------------------------------
|
|
@api.depends('applicant_last_name', 'applicant_first_name', 'application_date')
|
|
def _compute_display_name(self):
|
|
for rec in self:
|
|
name_parts = [rec.applicant_last_name or '', rec.applicant_first_name or '']
|
|
name = ', '.join(p for p in name_parts if p) or 'Unknown'
|
|
date_str = rec.application_date.strftime('%Y-%m-%d') if rec.application_date else 'No Date'
|
|
rec.display_name = f'{name} ({date_str})'
|
|
|
|
@api.depends('note_section1', 'note_section2a', 'note_section2b',
|
|
'note_section2c', 'note_section2d', 'note_section3and4')
|
|
def _compute_sections_submitted(self):
|
|
for rec in self:
|
|
parts = []
|
|
if rec.note_section1:
|
|
parts.append('1')
|
|
if rec.note_section2a:
|
|
parts.append('2a')
|
|
if rec.note_section2b:
|
|
parts.append('2b')
|
|
if rec.note_section2c:
|
|
parts.append('2c')
|
|
if rec.note_section2d:
|
|
parts.append('2d')
|
|
if rec.note_section3and4:
|
|
parts.append('3+4')
|
|
rec.sections_submitted = ', '.join(parts) if parts else ''
|
|
|
|
@api.depends('s2a_base_device', 's2b_base_device', 's2c_base_device')
|
|
def _compute_base_device(self):
|
|
for rec in self:
|
|
rec.base_device = rec.s2a_base_device or rec.s2b_base_device or rec.s2c_base_device or ''
|
|
|
|
@api.depends('s2a_reason', 's2b_reason', 's2c_reason', 's2d_reason')
|
|
def _compute_reason(self):
|
|
for rec in self:
|
|
rec.reason_for_application = rec.s2a_reason or rec.s2b_reason or rec.s2c_reason or rec.s2d_reason or ''
|
|
|
|
# ------------------------------------------------------------------
|
|
# XML EXPORT
|
|
# ------------------------------------------------------------------
|
|
def action_export_xml(self):
|
|
"""Reconstruct ADP XML from stored JSON data."""
|
|
self.ensure_one()
|
|
if not self.xml_data_json:
|
|
# Fall back to raw_xml if available
|
|
if self.raw_xml:
|
|
xml_content = self.raw_xml.encode('utf-8')
|
|
attachment = self.env['ir.attachment'].create({
|
|
'name': f'{self.applicant_last_name}_{self.applicant_first_name}_data.xml',
|
|
'type': 'binary',
|
|
'datas': base64.b64encode(xml_content),
|
|
'mimetype': 'application/xml',
|
|
})
|
|
return {
|
|
'type': 'ir.actions.act_url',
|
|
'url': f'/web/content/{attachment.id}?download=true',
|
|
'target': 'new',
|
|
}
|
|
return False
|
|
|
|
try:
|
|
data = json.loads(self.xml_data_json)
|
|
xml_str = self._json_to_xml(data)
|
|
attachment = self.env['ir.attachment'].create({
|
|
'name': f'{self.applicant_last_name or "export"}_{self.applicant_first_name or "data"}_data.xml',
|
|
'type': 'binary',
|
|
'datas': base64.b64encode(xml_str.encode('utf-8')),
|
|
'mimetype': 'application/xml',
|
|
})
|
|
return {
|
|
'type': 'ir.actions.act_url',
|
|
'url': f'/web/content/{attachment.id}?download=true',
|
|
'target': 'new',
|
|
}
|
|
except Exception as e:
|
|
_logger.exception('XML export error: %s', e)
|
|
return False
|
|
|
|
def _json_to_xml(self, data):
|
|
"""Reconstruct the ADP XML from flat JSON dictionary."""
|
|
# Build the XML tree following the exact ADP structure
|
|
root = ET.Element('form1')
|
|
form = ET.SubElement(root, 'Form')
|
|
|
|
# Simple top-level fields
|
|
self._set_el(form, 'deviceCategory', data.get('deviceCategory', ''))
|
|
self._set_el(form, 'VersionNumber', data.get('VersionNumber', ''))
|
|
|
|
# Section 1
|
|
s1 = ET.SubElement(form, 'section1')
|
|
s1_fields = [
|
|
'applicantLastname', 'applicantFirstname', 'applicantMiddleinitial',
|
|
'healthNo', 'versionNo', 'DateOfBirth', 'nameLTCH',
|
|
'unitNo', 'streetNo', 'streetName', 'rrRoute',
|
|
'city', 'province', 'postalCode',
|
|
'homePhone', 'busPhone', 'phoneExtension',
|
|
]
|
|
for f in s1_fields:
|
|
self._set_el(s1, f, data.get(f'section1.{f}', ''))
|
|
|
|
# Confirmation of benefit
|
|
cob = ET.SubElement(s1, 'confirmationOfBenefit')
|
|
for f in ['q1Yn', 'q1Ifyes', 'q2Yn', 'q3Yn']:
|
|
self._set_el(cob, f, data.get(f'section1.confirmationOfBenefit.{f}', ''))
|
|
|
|
# Section 2
|
|
s2 = ET.SubElement(form, 'section2')
|
|
|
|
# Devices and Eligibility
|
|
de = ET.SubElement(s2, 'devicesandEligibility')
|
|
de_fields = [
|
|
'condition', 'status', 'none', 'forearm', 'wheeled', 'manual',
|
|
'power', 'addOn', 'scooter', 'seating', 'tiltSystem', 'reclineSystem',
|
|
'legRests', 'frame', 'stroller', 'deviceForearm', 'deviceWheeled',
|
|
'deviceManual', 'deviceAmbulation', 'deviceDependent', 'deviceDynamic',
|
|
'manualDyanmic', 'manualWheelchair', 'powerBase', 'powerScooter',
|
|
'ambulation', 'positioning', 'highTech', 'standingFrame',
|
|
'adpFunded', 'nonADPFunded',
|
|
]
|
|
for f in de_fields:
|
|
self._set_el(de, f, data.get(f'section2.devicesandEligibility.{f}', ''))
|
|
|
|
# Sections 2a, 2b, 2c, 2d
|
|
for section_key in ['section2a', 'section2b', 'section2c', 'section2d']:
|
|
section_data = {k.split(f'section2.{section_key}.')[1]: v
|
|
for k, v in data.items()
|
|
if k.startswith(f'section2.{section_key}.')}
|
|
sec = ET.SubElement(s2, section_key)
|
|
# Preserve field order from the data keys
|
|
ordered_keys = [k.split(f'section2.{section_key}.')[1]
|
|
for k in sorted(data.keys())
|
|
if k.startswith(f'section2.{section_key}.')]
|
|
for f in ordered_keys:
|
|
self._set_el(sec, f, section_data.get(f, ''))
|
|
|
|
# Section 3
|
|
s3 = ET.SubElement(form, 'section3')
|
|
sig = ET.SubElement(s3, 'sig')
|
|
for f in ['signature', 'person', 'Date']:
|
|
self._set_el(sig, f, data.get(f'section3.sig.{f}', ''))
|
|
contact = ET.SubElement(s3, 'contact')
|
|
contact_fields = [
|
|
'relationship', 'applicantLastname', 'applicantFirstname',
|
|
'applicantMiddleinitial', 'unitNo', 'streetNo', 'streetName',
|
|
'rrRoute', 'city', 'province', 'postalCode',
|
|
'homePhone', 'busPhone', 'phoneExtension',
|
|
]
|
|
for f in contact_fields:
|
|
self._set_el(contact, f, data.get(f'section3.contact.{f}', ''))
|
|
|
|
# Section 4
|
|
s4 = ET.SubElement(form, 'section4')
|
|
# Authorizer
|
|
auth = ET.SubElement(s4, 'authorizer')
|
|
for f in ['authorizerLastname', 'authorizerFirstname', 'busPhone',
|
|
'phoneExtension', 'adpNo', 'signature', 'Date']:
|
|
self._set_el(auth, f, data.get(f'section4.authorizer.{f}', ''))
|
|
# Vendor
|
|
vendor = ET.SubElement(s4, 'vendor')
|
|
for f in ['vendorBusName', 'adpVendorRegNo', 'vendorLastfirstname',
|
|
'positionTitle', 'vendorLocation', 'busPhone',
|
|
'phoneExtension', 'signature', 'Date']:
|
|
self._set_el(vendor, f, data.get(f'section4.vendor.{f}', ''))
|
|
# Vendor 2
|
|
v2 = ET.SubElement(s4, 'vendor2')
|
|
for f in ['vendorBusName', 'adpVendorRegNo', 'vendorLastfirstname',
|
|
'positionTitle', 'vendorLocation', 'busPhone',
|
|
'phoneExtension', 'signature', 'Date']:
|
|
self._set_el(v2, f, data.get(f'section4.vendor2.{f}', ''))
|
|
# Equipment Spec
|
|
eq = ET.SubElement(s4, 'equipmentSpec')
|
|
self._set_el(eq, 'vendorInvoiceNo', data.get('section4.equipmentSpec.vendorInvoiceNo', ''))
|
|
self._set_el(eq, 'vendorADPRegNo', data.get('section4.equipmentSpec.vendorADPRegNo', ''))
|
|
t2 = ET.SubElement(eq, 'Table2')
|
|
r1 = ET.SubElement(t2, 'Row1')
|
|
for c in ['Cell1', 'Cell2', 'Cell3', 'Cell4', 'Cell5']:
|
|
self._set_el(r1, c, data.get(f'section4.equipmentSpec.Table2.Row1.{c}', ''))
|
|
# Proof of delivery
|
|
pod = ET.SubElement(s4, 'proofOfDelivery')
|
|
for f in ['signature', 'receivedBy', 'Date']:
|
|
self._set_el(pod, f, data.get(f'section4.proofOfDelivery.{f}', ''))
|
|
# Note to ADP
|
|
note = ET.SubElement(s4, 'noteToADP')
|
|
for f in ['section1', 'section2a', 'section2b', 'section2c', 'section2d',
|
|
'section3and4', 'vendorReplacement', 'vendorCustom',
|
|
'fundingChart', 'letter']:
|
|
self._set_el(note, f, data.get(f'section4.noteToADP.{f}', ''))
|
|
|
|
# Convert to string
|
|
tree = ET.ElementTree(root)
|
|
ET.indent(tree, space='')
|
|
import io
|
|
buf = io.BytesIO()
|
|
tree.write(buf, encoding='unicode', xml_declaration=True)
|
|
return buf.getvalue()
|
|
|
|
@staticmethod
|
|
def _set_el(parent, tag, value):
|
|
"""Create a child element, self-closing if empty."""
|
|
el = ET.SubElement(parent, tag)
|
|
if value:
|
|
el.text = str(value)
|