CL6/CL7 AI self-check engine
- New fusion.repair.ai.service AbstractModel with single guardrailed
suggest_self_check(category_id, symptoms, urgency) entry point.
- Hard-escalation FIRST (before any AI call): stairlift / porch lift +
safety symptoms (smoke / burning / spark / stuck / motor), OR any
mention of fire / injury / hurt / bleeding / trapped, OR urgency=safety
-> escalate immediately regardless of AI availability.
- AI call via fusion.api.service.call_openai() (consumer='fusion_repairs',
feature='client_self_triage') with try/fallback per project rule -
no hard fusion_api dep, no install error if it's missing.
- Strict response validation: JSON schema check, max 3 steps, max 200
chars per field, forbidden-phrase regex (diagnose, you have, medical
condition, stop using, consult doctor, price patterns) - on any
failure falls back to deterministic rules.
- 24h in-memory cache keyed by (category, symptom_hash) so repeat calls
during AI cost-cap incidents come from cache.
- System prompt + JSON schema published as ir.config_parameter so office
can refine without code changes (default prompt + schema in spec
Appendix A).
- New fusion.repair.self.check.rule model + 17 seeded rules across all
7 product categories (data/self_check_data.xml) - these are the
deterministic fallback AND the canonical seed if AI is disabled.
- New /repair/self_check jsonrpc route (auth=public) gated by the
per-IP rate-limit; defensive input bounds (max 5 symptoms, 500 chars
each) defend against prompt-injection bloat.
CL15 weekend safety escalation + on-call paging
- New fusion.repair.on.call.service AbstractModel with:
* find_next_on_call(exclude=...) -> lowest x_fc_on_call_priority
* page_on_call(repair) -> sends mail to next available + writes
x_fc_on_call_token / x_fc_on_call_paged_user_id / paged_at on the
repair, posts chatter
* acknowledge(repair, user) -> records ack, posts chatter
* cron_escalate_unacknowledged() -> every 5 min, re-pages the next
priority for repairs paged >15 min ago without ack
- Auto-fires from intake service whenever x_fc_urgency='safety' is
submitted. _is_business_hours() defaults to "page" when no calendar
is set or after working hours.
- New email_template_on_call_page with 4px red accent + acknowledge
CTA button linking to /repair/on-call/ack/<token>.
- /repair/on-call/ack/<token> http route (auth=user, must be the paged
manager OR any internal user) records the ack and renders confirmation.
- 5-minute cron 'Fusion Repairs: Escalate unacknowledged on-call pages'
with configurable window via fusion_repairs.on_call_escalate_minutes
(default 15).
- New repair.order fields x_fc_on_call_token, x_fc_on_call_paged_user_id,
x_fc_on_call_paged_at, x_fc_on_call_acknowledged_user_ids,
x_fc_on_call_acknowledged_at - all copy=False so duplicates start fresh.
CL17 QR sticker generator
- New fusion.repair.qr.sticker.wizard TransientModel takes a Many2many
of stock.lot records (optionally filtered by product).
- QWeb PDF report fusion_repairs.report_qr_stickers prints a 4-up
sticker sheet on letter paper: 80mm x 50mm per sticker with the
QR code (38mm), product name, serial number, and the canonical
portal URL (from web.base.url + fusion_repairs.client_portal_url).
- QR encodes /repair?sn=<serial> which the public client portal
already pre-fills via the ?sn= query param.
- Uses the qrcode library if available; renders 'QR lib missing'
placeholder otherwise so the PDF still prints.
- New menu Configuration > Generate QR Stickers + standalone wizard.
Verified end-to-end on local westin-v19:
CL6 stairlift+smoke -> escalate=True source=escalated reason=safety
CL6 bed (no AI) -> fallback returned escalate=True (safe default)
CL15 admin paged for RO-202605-10 with 27-char token
CL17 sticker URL: /repair?sn=001124032521528404
QR data URI: data:image/png;base64,iVBORw... (PNG OK)
Bumped to 19.0.1.2.0 (minor bump - new public-facing capabilities).
Co-authored-by: Cursor <cursoragent@cursor.com>
123 lines
4.4 KiB
Python
123 lines
4.4 KiB
Python
# -*- coding: utf-8 -*-
|
|
# Copyright 2024-2026 Nexa Systems Inc.
|
|
# License OPL-1 (Odoo Proprietary License v1.0)
|
|
|
|
{
|
|
'name': 'Fusion Repairs',
|
|
'version': '19.0.1.2.0',
|
|
'category': 'Inventory/Repairs',
|
|
'summary': 'Guided medical equipment repair intake, dispatch, maintenance, and self-service portal',
|
|
'description': """
|
|
Fusion Repairs
|
|
==============
|
|
|
|
Comprehensive repairs and maintenance management for medical equipment retailers
|
|
and service providers (hospital beds, wheelchairs, stairlifts, porch lifts,
|
|
walkers, mattresses, rollators).
|
|
|
|
Phase 1 - MVP
|
|
-------------
|
|
- Three intake surfaces sharing one service layer:
|
|
* Backend wizard for CS reps on the phone
|
|
* Sales rep portal (/my/repair/new) for reps on the road
|
|
* Public client self-service portal (/repair) - voicemail ready
|
|
- Guided question templates per medical equipment category
|
|
- Phone-first partner lookup with duplicate-call detection
|
|
- Multi-equipment per call (one repair.order per unit)
|
|
- Photo / video capture during intake
|
|
- Third-party equipment support (equipment we didn't sell)
|
|
- Auto warranty detection from original sale order
|
|
- Office notification recipients + 4 follow-up activities
|
|
- repair.order extensions linked to fusion.technician.task
|
|
|
|
Phase 2-4 (roadmap)
|
|
-------------------
|
|
- AI self-check engine with strict medical safety guardrails
|
|
- Upsell engine and direct-buy parts/plans
|
|
- Repair warranty tracking (free re-do window)
|
|
- Visit report wizard with Poynt terminal payment
|
|
- Maintenance contracts with client self-booking
|
|
- Weekend safety on-call paging
|
|
- SMS notifications, compliance certificates, analytics
|
|
|
|
Copyright (C) 2024-2026 Nexa Systems Inc. All rights reserved.
|
|
""",
|
|
'author': 'Nexa Systems Inc.',
|
|
'website': 'https://www.nexasystems.ca',
|
|
'maintainer': 'Nexa Systems Inc.',
|
|
'support': 'support@nexasystems.ca',
|
|
'license': 'OPL-1',
|
|
'price': 0.00,
|
|
'currency': 'CAD',
|
|
'depends': [
|
|
'base',
|
|
'mail',
|
|
'portal',
|
|
'website',
|
|
'sale_management',
|
|
'stock',
|
|
'repair',
|
|
'maintenance',
|
|
'fusion_tasks',
|
|
'fusion_poynt',
|
|
'fusion_authorizer_portal',
|
|
],
|
|
'data': [
|
|
# Security
|
|
'security/security.xml',
|
|
'security/ir.model.access.csv',
|
|
# Data (must load before views that reference records)
|
|
'data/ir_sequence_data.xml',
|
|
'data/ir_config_parameter_data.xml',
|
|
'data/ir_cron_data.xml',
|
|
'data/mail_activity_type_data.xml',
|
|
'data/mail_template_data.xml',
|
|
'data/repair_product_category_data.xml',
|
|
'data/intake_template_data.xml',
|
|
'data/self_check_data.xml',
|
|
# Views
|
|
'views/repair_product_category_views.xml',
|
|
'views/intake_template_views.xml',
|
|
'views/service_catalog_views.xml',
|
|
'views/repair_warranty_views.xml',
|
|
'views/maintenance_contract_views.xml',
|
|
'views/repair_dashboard_views.xml',
|
|
'views/repair_order_views.xml',
|
|
'views/sale_order_views.xml',
|
|
'views/technician_task_views.xml',
|
|
'views/res_partner_views.xml',
|
|
'views/res_users_views.xml',
|
|
'views/res_config_settings_views.xml',
|
|
# Portal templates
|
|
'views/portal_sales_rep_templates.xml',
|
|
'views/portal_client_repair_templates.xml',
|
|
'views/portal_maintenance_templates.xml',
|
|
# Wizards
|
|
'wizard/repair_intake_wizard_views.xml',
|
|
'wizard/repair_visit_report_wizard_views.xml',
|
|
'wizard/qr_sticker_wizard_views.xml',
|
|
# Reports
|
|
'report/qr_sticker_report.xml',
|
|
# Menus (last, after all referenced actions exist)
|
|
'views/menus.xml',
|
|
],
|
|
'assets': {
|
|
'web.assets_backend': [
|
|
# Tokens MUST load first - dashboard.scss references its variables.
|
|
'fusion_repairs/static/src/scss/_fr_tokens.scss',
|
|
'fusion_repairs/static/src/scss/dashboard.scss',
|
|
'fusion_repairs/static/src/components/dashboard/dashboard.js',
|
|
'fusion_repairs/static/src/components/dashboard/dashboard.xml',
|
|
],
|
|
'web.assets_frontend': [
|
|
'fusion_repairs/static/src/scss/portal_repair_mobile.scss',
|
|
'fusion_repairs/static/src/scss/portal_client_repair.scss',
|
|
'fusion_repairs/static/src/js/portal_repair_intake.js',
|
|
],
|
|
},
|
|
'images': ['static/description/icon.png'],
|
|
'installable': True,
|
|
'application': True,
|
|
'auto_install': False,
|
|
}
|