# -*- coding: utf-8 -*- from odoo import api, fields, models, _ class WheelchairConfigFlowNode(models.Model): _name = 'fusion.wc.config.flow.node' _description = 'Configuration Flow Node' _order = 'sequence, id' flow_id = fields.Many2one('fusion.wc.config.flow', string='Flow', required=True, ondelete='cascade', index=True) name = fields.Char(string='Name', required=True, default='New Node') sequence = fields.Integer(default=10) node_type = fields.Selection([ ('start', 'Start'), ('end', 'End'), ('decision', 'Decision (If/Then)'), ('option_group', 'Option Group'), ('product_select', 'Product Selection'), ('measurement_check', 'Measurement Check'), ('action', 'Action (Enable/Disable/Require)'), ], string='Type', required=True, default='action') # Canvas position pos_x = fields.Float(string='X Position', default=100.0) pos_y = fields.Float(string='Y Position', default=100.0) # Visual color = fields.Char(string='Color', default='#3b82f6') icon = fields.Char(string='Icon', default='fa-circle') # Extensible config for type-specific settings config_json = fields.Text(string='Configuration', default='{}', help='Type-specific configuration as JSON') # Link to existing section section_id = fields.Many2one('fusion.wc.section', string='Section', help='Link this node to a wheelchair section') # Node options (for option_group / product_select) node_option_ids = fields.One2many('fusion.wc.config.flow.node.option', 'node_id', string='Options') # ── Decision node fields ── decision_field = fields.Selection([ ('equipment_type', 'Equipment Type'), ('wheelchair_type', 'Wheelchair Category'), ('powerchair_type', 'Power Chair Category'), ('build_type', 'Build Type'), ('client_type', 'Client Type'), ('reason_for_application', 'Reason for Application'), ('seat_width', 'Seat Width (inches)'), ('seat_depth', 'Seat Depth (inches)'), ('client_weight', 'Client Weight (lbs)'), ('back_height', 'Back Height (inches)'), ('seat_to_floor', 'Seat to Floor Height (inches)'), ('leg_rest_length', 'Leg Rest Length (inches)'), ('custom', 'Custom Expression'), ('custom_field', 'Custom Field (from equipment data)'), ], string='Decision Field') custom_field_name = fields.Char(string='Custom Field Name', help='JSON key to check in equipment_data_json (for custom_field decisions)') decision_operator = fields.Selection([ ('eq', '='), ('neq', '!='), ('gt', '>'), ('gte', '>='), ('lt', '<'), ('lte', '<='), ('in', 'In List'), ], string='Operator') decision_value = fields.Char(string='Expected Value', help='For "In List" use comma-separated values') # ── Measurement check fields (reuses upcharge rule pattern) ── measurement_field = fields.Selection([ ('seat_width', 'Seat Width'), ('seat_depth', 'Seat Depth'), ('back_width', 'Backrest Width'), ('back_height', 'Back Height'), ('seat_to_floor', 'Seat to Floor Height'), ('leg_rest_length', 'Leg Rest Length'), ('client_weight', 'Client Weight'), ], string='Measurement') comparison = fields.Selection([ ('gt', 'Greater Than'), ('gte', 'Greater Than or Equal'), ('lt', 'Less Than'), ('eq', 'Equal To'), ('neq', 'Not Equal To'), ], string='Comparison') threshold_value = fields.Float(string='Threshold') # ── Action node fields ── action_type = fields.Selection([ ('enable', 'Enable Options'), ('disable', 'Disable Options'), ('require', 'Require Options'), ('skip_step', 'Skip Portal Step'), ('set_value', 'Set Field Value'), ], string='Action Type') target_option_ids = fields.Many2many( 'fusion.wc.section.option', 'wc_flow_node_target_option_rel', 'node_id', 'option_id', string='Target Options', help='Section options affected by this action') target_step = fields.Integer(string='Target Step', help='Portal form step number to skip (for skip_step action)') # ── Connections (computed for convenience) ── outgoing_connection_ids = fields.One2many( 'fusion.wc.config.flow.connection', 'source_node_id', string='Outgoing Connections') incoming_connection_ids = fields.One2many( 'fusion.wc.config.flow.connection', 'target_node_id', string='Incoming Connections')