Files
Odoo-Modules/fusion_repairs/data/intake_template_data.xml
gsinghpal 429084e0bf feat(fusion_repairs): Phase 1 MVP - backend intake wizard + core models
Scaffolds the fusion_repairs module that extends Odoo 19 repair.order with
a guided medical-equipment intake workflow.

Models
- fusion.repair.product.category (8 medical equipment categories seeded)
- fusion.repair.intake.template / .question / .answer (7 templates,
  32 questions seeded across hospital bed, stairlift, porch lift,
  wheelchair, walker/rollator, mattress)
- fusion.repair.intake.service (AbstractModel) - single entry point used
  by backend wizard, sales rep portal, and public client portal so all
  three surfaces produce identical outcomes
- repair.order extensions (x_fc_intake_*, x_fc_third_party_equipment,
  x_fc_photo_ids, x_fc_urgency, x_fc_estimated/actual_cost, AI summary)
- fusion.technician.task back-link (x_fc_repair_order_id)
- res.partner service preferences (preferred tech, time window, access notes)
- res.users repair extensions (skills, cost rate, on-call rotation fields)
- res.config.settings for variance thresholds, portal URL, rate limit

UI
- Backend intake wizard with multi-equipment loop, third-party flag, photos
- repair.order form: Intake tab, Photos, Pricing tab, AI tab, smart buttons
  (technician tasks, intake answers, original SO)
- Kanban + list view urgency badges
- Fusion Repairs app menu (New Service Call, Repair Orders, Config)

Activities & Email
- 4 follow-up activity types (CS callback, tech dispatch, visit follow-up,
  manager review) with urgency-tiered deadlines
- 2 mail templates (client confirmation + office notification) with the
  same dark/light-safe styling as fusion_claims ADP templates

Security
- New res.groups.privilege + 3 groups (User, Dispatcher, Manager)
- Reuses fusion_tasks.group_field_technician (do NOT recreate)
- Reuses fusion_authorizer_portal.group_sales_rep_portal
- Multi-company global rule + technician scoping rule on repair.order

Verified end-to-end on local westin-v19 dev DB via odoo-shell - creates
multiple repairs in one session, auto-creates dispatch task for urgent,
attaches 4 activity types correctly per urgency tier and third-party flag.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-20 21:35:52 -04:00

379 lines
21 KiB
XML

<?xml version="1.0" encoding="utf-8"?>
<!--
Seed intake templates - one per major medical equipment category.
Question banks based on the design spec Section "Configurable intake".
All templates noupdate=1 so customers can customise without losing data on upgrade.
-->
<odoo>
<data noupdate="1">
<!-- ============================================================== -->
<!-- DEFAULT (fallback) - applies to any category without override -->
<!-- ============================================================== -->
<record id="intake_template_default" model="fusion.repair.intake.template">
<field name="name">Default - General Intake</field>
<field name="code">default</field>
<field name="sequence">1</field>
<field name="is_default" eval="True"/>
<field name="description"><![CDATA[<p>Generic question set used when no equipment-specific template is configured.</p>]]></field>
</record>
<record id="q_default_caller_relationship" model="fusion.repair.intake.question">
<field name="template_id" ref="intake_template_default"/>
<field name="sequence">10</field>
<field name="name">Who is calling? (self / family / caregiver / other)</field>
<field name="code">caller_relationship</field>
<field name="question_type">char</field>
<field name="required" eval="True"/>
</record>
<record id="q_default_address_match" model="fusion.repair.intake.question">
<field name="template_id" ref="intake_template_default"/>
<field name="sequence">20</field>
<field name="name">Is the service address the same as the contact address on file?</field>
<field name="code">address_match</field>
<field name="question_type">boolean</field>
<field name="required" eval="True"/>
</record>
<record id="q_default_purchased_from_us" model="fusion.repair.intake.question">
<field name="template_id" ref="intake_template_default"/>
<field name="sequence">30</field>
<field name="name">Was this equipment purchased from us?</field>
<field name="code">purchased_from_us</field>
<field name="question_type">boolean</field>
</record>
<record id="q_default_purchase_date" model="fusion.repair.intake.question">
<field name="template_id" ref="intake_template_default"/>
<field name="sequence">40</field>
<field name="name">Approximate purchase date (if known)</field>
<field name="code">purchase_date</field>
<field name="question_type">date</field>
</record>
<record id="q_default_issue_summary" model="fusion.repair.intake.question">
<field name="template_id" ref="intake_template_default"/>
<field name="sequence">50</field>
<field name="name">Describe the issue in your own words</field>
<field name="code">issue_summary</field>
<field name="question_type">text</field>
<field name="required" eval="True"/>
</record>
<record id="q_default_safety_concern" model="fusion.repair.intake.question">
<field name="template_id" ref="intake_template_default"/>
<field name="sequence">60</field>
<field name="name">Does this issue affect anyone's safety right now?</field>
<field name="code">safety_concern</field>
<field name="question_type">boolean</field>
<field name="required" eval="True"/>
</record>
<record id="q_default_access_notes" model="fusion.repair.intake.question">
<field name="template_id" ref="intake_template_default"/>
<field name="sequence">70</field>
<field name="name">Anything the technician should know about access? (stairs, parking, gate code, pet)</field>
<field name="code">access_notes</field>
<field name="question_type">text</field>
<field name="help_text">e.g. "dog in front yard, use side gate"</field>
</record>
<!-- ============================================================== -->
<!-- HOSPITAL BED -->
<!-- ============================================================== -->
<record id="intake_template_hospital_bed" model="fusion.repair.intake.template">
<field name="name">Hospital Bed - Intake</field>
<field name="code">hospital_bed</field>
<field name="sequence">10</field>
<field name="product_category_ids" eval="[(6, 0, [ref('category_hospital_bed')])]"/>
</record>
<record id="q_bed_powered" model="fusion.repair.intake.question">
<field name="template_id" ref="intake_template_hospital_bed"/>
<field name="sequence">10</field>
<field name="name">Is the bed plugged in and does it power on?</field>
<field name="code">powered</field>
<field name="question_type">selection</field>
<field name="selection_options">Yes - powers on normally
No - no lights/sound at all
Powers on but won't move</field>
<field name="required" eval="True"/>
</record>
<record id="q_bed_remote_works" model="fusion.repair.intake.question">
<field name="template_id" ref="intake_template_hospital_bed"/>
<field name="sequence">20</field>
<field name="name">Does the remote control respond when buttons are pressed?</field>
<field name="code">remote_works</field>
<field name="question_type">boolean</field>
</record>
<record id="q_bed_motor_side" model="fusion.repair.intake.question">
<field name="template_id" ref="intake_template_hospital_bed"/>
<field name="sequence">30</field>
<field name="name">Which motor seems affected? (head, foot, height, all)</field>
<field name="code">motor_side</field>
<field name="question_type">char</field>
<field name="symptom_keywords">motor</field>
</record>
<record id="q_bed_rails" model="fusion.repair.intake.question">
<field name="template_id" ref="intake_template_hospital_bed"/>
<field name="sequence">40</field>
<field name="name">Are the side rails functioning normally?</field>
<field name="code">rails_ok</field>
<field name="question_type">boolean</field>
<field name="symptom_keywords">rail,side</field>
</record>
<record id="q_bed_mattress" model="fusion.repair.intake.question">
<field name="template_id" ref="intake_template_hospital_bed"/>
<field name="sequence">50</field>
<field name="name">Is the mattress included in this issue?</field>
<field name="code">mattress_involved</field>
<field name="question_type">boolean</field>
</record>
<!-- ============================================================== -->
<!-- STAIRLIFT -->
<!-- ============================================================== -->
<record id="intake_template_stairlift" model="fusion.repair.intake.template">
<field name="name">Stairlift - Intake</field>
<field name="code">stairlift</field>
<field name="sequence">20</field>
<field name="product_category_ids" eval="[(6, 0, [ref('category_stairlift')])]"/>
</record>
<record id="q_stairlift_powered" model="fusion.repair.intake.question">
<field name="template_id" ref="intake_template_stairlift"/>
<field name="sequence">10</field>
<field name="name">Does the stairlift power on? (any lights, beeps)</field>
<field name="code">powered</field>
<field name="question_type">boolean</field>
<field name="required" eval="True"/>
</record>
<record id="q_stairlift_error_code" model="fusion.repair.intake.question">
<field name="template_id" ref="intake_template_stairlift"/>
<field name="sequence">20</field>
<field name="name">Is there an error code displayed? (note the number/letter shown)</field>
<field name="code">error_code</field>
<field name="question_type">char</field>
<field name="symptom_keywords">error code</field>
</record>
<record id="q_stairlift_stuck_position" model="fusion.repair.intake.question">
<field name="template_id" ref="intake_template_stairlift"/>
<field name="sequence">30</field>
<field name="name">Is anyone currently stuck on the stairlift?</field>
<field name="code">person_stuck</field>
<field name="question_type">boolean</field>
<field name="required" eval="True"/>
<field name="help_text">If yes, this is a safety issue - escalate immediately.</field>
</record>
<record id="q_stairlift_stops_midway" model="fusion.repair.intake.question">
<field name="template_id" ref="intake_template_stairlift"/>
<field name="sequence">40</field>
<field name="name">Does it stop partway up or down the track?</field>
<field name="code">stops_midway</field>
<field name="question_type">boolean</field>
<field name="symptom_keywords">stops midway</field>
</record>
<record id="q_stairlift_burning" model="fusion.repair.intake.question">
<field name="template_id" ref="intake_template_stairlift"/>
<field name="sequence">50</field>
<field name="name">Any burning smell, smoke, or unusual noise?</field>
<field name="code">burning_smell</field>
<field name="question_type">boolean</field>
<field name="required" eval="True"/>
<field name="symptom_keywords">burning smell,smoke</field>
</record>
<!-- ============================================================== -->
<!-- PORCH LIFT -->
<!-- ============================================================== -->
<record id="intake_template_porch_lift" model="fusion.repair.intake.template">
<field name="name">Porch Lift - Intake</field>
<field name="code">porch_lift</field>
<field name="sequence">30</field>
<field name="product_category_ids" eval="[(6, 0, [ref('category_porch_lift')])]"/>
</record>
<record id="q_porch_powered" model="fusion.repair.intake.question">
<field name="template_id" ref="intake_template_porch_lift"/>
<field name="sequence">10</field>
<field name="name">Does the lift respond when you press the call/send button?</field>
<field name="code">powered</field>
<field name="question_type">boolean</field>
<field name="required" eval="True"/>
</record>
<record id="q_porch_gate_switches" model="fusion.repair.intake.question">
<field name="template_id" ref="intake_template_porch_lift"/>
<field name="sequence">20</field>
<field name="name">Are all gate and door safety switches fully closed?</field>
<field name="code">gate_switches</field>
<field name="question_type">boolean</field>
</record>
<record id="q_porch_stuck" model="fusion.repair.intake.question">
<field name="template_id" ref="intake_template_porch_lift"/>
<field name="sequence">30</field>
<field name="name">Is anyone currently stuck on the lift?</field>
<field name="code">person_stuck</field>
<field name="question_type">boolean</field>
<field name="required" eval="True"/>
</record>
<record id="q_porch_outdoor" model="fusion.repair.intake.question">
<field name="template_id" ref="intake_template_porch_lift"/>
<field name="sequence">40</field>
<field name="name">Is the lift outdoors exposed to weather?</field>
<field name="code">outdoor</field>
<field name="question_type">boolean</field>
</record>
<!-- ============================================================== -->
<!-- WHEELCHAIR (MANUAL + POWER - shared template) -->
<!-- ============================================================== -->
<record id="intake_template_wheelchair" model="fusion.repair.intake.template">
<field name="name">Wheelchair - Intake</field>
<field name="code">wheelchair</field>
<field name="sequence">40</field>
<field name="product_category_ids" eval="[(6, 0, [ref('category_wheelchair_manual'), ref('category_wheelchair_power')])]"/>
</record>
<record id="q_wc_brakes" model="fusion.repair.intake.question">
<field name="template_id" ref="intake_template_wheelchair"/>
<field name="sequence">10</field>
<field name="name">Do the brakes engage and hold the wheelchair?</field>
<field name="code">brakes_ok</field>
<field name="question_type">boolean</field>
<field name="required" eval="True"/>
<field name="symptom_keywords">brake</field>
</record>
<record id="q_wc_tires" model="fusion.repair.intake.question">
<field name="template_id" ref="intake_template_wheelchair"/>
<field name="sequence">20</field>
<field name="name">Are both tires inflated and undamaged?</field>
<field name="code">tires_ok</field>
<field name="question_type">boolean</field>
</record>
<record id="q_wc_frame" model="fusion.repair.intake.question">
<field name="template_id" ref="intake_template_wheelchair"/>
<field name="sequence">30</field>
<field name="name">Is there any visible damage to the frame or footrests?</field>
<field name="code">frame_damage</field>
<field name="question_type">boolean</field>
</record>
<record id="q_wc_battery" model="fusion.repair.intake.question">
<field name="template_id" ref="intake_template_wheelchair"/>
<field name="sequence">40</field>
<field name="name">For power chairs: does the battery hold a charge?</field>
<field name="code">battery_holds_charge</field>
<field name="question_type">boolean</field>
<field name="symptom_keywords">battery,charge</field>
</record>
<record id="q_wc_joystick" model="fusion.repair.intake.question">
<field name="template_id" ref="intake_template_wheelchair"/>
<field name="sequence">50</field>
<field name="name">For power chairs: any error code shown on the joystick display?</field>
<field name="code">joystick_error</field>
<field name="question_type">char</field>
</record>
<!-- ============================================================== -->
<!-- WALKER / ROLLATOR (shared) -->
<!-- ============================================================== -->
<record id="intake_template_walker_rollator" model="fusion.repair.intake.template">
<field name="name">Walker / Rollator - Intake</field>
<field name="code">walker_rollator</field>
<field name="sequence">50</field>
<field name="product_category_ids" eval="[(6, 0, [ref('category_walker'), ref('category_rollator')])]"/>
</record>
<record id="q_walker_wheels" model="fusion.repair.intake.question">
<field name="template_id" ref="intake_template_walker_rollator"/>
<field name="sequence">10</field>
<field name="name">Do all wheels roll freely?</field>
<field name="code">wheels_roll</field>
<field name="question_type">boolean</field>
</record>
<record id="q_walker_brakes" model="fusion.repair.intake.question">
<field name="template_id" ref="intake_template_walker_rollator"/>
<field name="sequence">20</field>
<field name="name">Do the brakes lock when engaged? (rollator only)</field>
<field name="code">brakes_lock</field>
<field name="question_type">boolean</field>
</record>
<record id="q_walker_frame" model="fusion.repair.intake.question">
<field name="template_id" ref="intake_template_walker_rollator"/>
<field name="sequence">30</field>
<field name="name">Is the frame stable, with no wobble or loose parts?</field>
<field name="code">frame_stable</field>
<field name="question_type">boolean</field>
</record>
<!-- ============================================================== -->
<!-- MEDICAL MATTRESS -->
<!-- ============================================================== -->
<record id="intake_template_mattress" model="fusion.repair.intake.template">
<field name="name">Medical Mattress - Intake</field>
<field name="code">mattress</field>
<field name="sequence">60</field>
<field name="product_category_ids" eval="[(6, 0, [ref('category_mattress')])]"/>
</record>
<record id="q_mattress_pump_powered" model="fusion.repair.intake.question">
<field name="template_id" ref="intake_template_mattress"/>
<field name="sequence">10</field>
<field name="name">Is the pump plugged in and showing any indicator lights?</field>
<field name="code">pump_powered</field>
<field name="question_type">boolean</field>
<field name="required" eval="True"/>
</record>
<record id="q_mattress_leak" model="fusion.repair.intake.question">
<field name="template_id" ref="intake_template_mattress"/>
<field name="sequence">20</field>
<field name="name">Is the mattress leaking or losing air?</field>
<field name="code">leak</field>
<field name="question_type">boolean</field>
<field name="symptom_keywords">leak,deflate</field>
</record>
<record id="q_mattress_alarm" model="fusion.repair.intake.question">
<field name="template_id" ref="intake_template_mattress"/>
<field name="sequence">30</field>
<field name="name">Is the pump showing an error code or alarm?</field>
<field name="code">alarm</field>
<field name="question_type">char</field>
</record>
<!-- ============================================================== -->
<!-- Backfill category defaults -->
<!-- ============================================================== -->
<function model="fusion.repair.product.category" name="write">
<value model="fusion.repair.product.category" eval="[ref('category_hospital_bed')]"/>
<value eval="{'intake_template_id': ref('intake_template_hospital_bed')}"/>
</function>
<function model="fusion.repair.product.category" name="write">
<value model="fusion.repair.product.category" eval="[ref('category_stairlift')]"/>
<value eval="{'intake_template_id': ref('intake_template_stairlift')}"/>
</function>
<function model="fusion.repair.product.category" name="write">
<value model="fusion.repair.product.category" eval="[ref('category_porch_lift')]"/>
<value eval="{'intake_template_id': ref('intake_template_porch_lift')}"/>
</function>
<function model="fusion.repair.product.category" name="write">
<value model="fusion.repair.product.category" eval="[ref('category_wheelchair_manual')]"/>
<value eval="{'intake_template_id': ref('intake_template_wheelchair')}"/>
</function>
<function model="fusion.repair.product.category" name="write">
<value model="fusion.repair.product.category" eval="[ref('category_wheelchair_power')]"/>
<value eval="{'intake_template_id': ref('intake_template_wheelchair')}"/>
</function>
<function model="fusion.repair.product.category" name="write">
<value model="fusion.repair.product.category" eval="[ref('category_walker')]"/>
<value eval="{'intake_template_id': ref('intake_template_walker_rollator')}"/>
</function>
<function model="fusion.repair.product.category" name="write">
<value model="fusion.repair.product.category" eval="[ref('category_rollator')]"/>
<value eval="{'intake_template_id': ref('intake_template_walker_rollator')}"/>
</function>
<function model="fusion.repair.product.category" name="write">
<value model="fusion.repair.product.category" eval="[ref('category_mattress')]"/>
<value eval="{'intake_template_id': ref('intake_template_default')}"/>
</function>
<function model="fusion.repair.product.category" name="write">
<value model="fusion.repair.product.category" eval="[ref('category_other')]"/>
<value eval="{'intake_template_id': ref('intake_template_default')}"/>
</function>
</data>
</odoo>