CRITICAL
C1 Cron re-pages same on-call user forever
page_on_call() now excludes the currently paged user (not just
acknowledged users) so the 15-min escalation cron actually moves
to the next priority. Removed the dead `already` var in the cron.
Verified: page 1 -> gsingh@..., page 2 -> ak@... (different user).
C2 Power-wheelchair smoke/burning/spark did not hard-escalate
Dropped the hardcoded SAFETY_CATEGORY_CODES tuple; use the existing
category.safety_critical Boolean instead. Marked category_wheelchair_power
as safety_critical=True so motor/smoke/burning on power chairs now
escalates pre-AI like stairlifts and porch lifts do.
Verified: powerchair + smoke -> escalate=True.
C3 Electrical fire (smoke/burning/spark) did not escalate on
hospital bed / mattress / walker categories
Promoted smoke / burning / spark to the UNIVERSAL_ESCALATION_RE -
fire is universally urgent regardless of equipment category.
Verified: hospital bed + "motor smells like burning" -> escalate=True.
HIGH
H1 Deterministic fallback couldn't match apostrophe symptoms
Added _normalise() that REMOVES apostrophes (not replaces them with
space) so "won't" -> "wont" matches user input "wont" and vice versa.
Handles straight, curly, and modifier-letter apostrophes.
Verified: "bed wont move" -> matches the "won't move" rule (1 step).
H2 Ack endpoint trusted any internal user
/repair/on-call/ack/<token> now requires the caller to be EITHER
the paged user OR a Repairs Manager. Denied attempts render the
invalid-token page and log a warning.
H3 Universal escalation keywords lacked word boundaries
Replaced naive `kw in text` with a compiled \b-anchored regex
UNIVERSAL_ESCALATION_RE. Likewise SAFETY_SYMPTOMS_RE for category-
scoped symptoms with won.?t to handle the apostrophe variant.
"unhurt" no longer matches "hurt", "firearm" no longer matches "fire".
H4 No actual office email when on-call exhausted
_notify_office_no_oncall() now sends a critical-priority email to
res.company.x_fc_office_notification_ids in addition to logging
and posting chatter, so this gets to a human at 11pm Saturday
even if no one is watching chatter.
H5 13 missing seed self-check rules vs spec Appendix D
Added: bed one-section-stuck, wheelchair wobble + footrest,
powerchair one-side-weaker, stairlift beep/alarm, porch overshoot,
walker wobble, rollator seat-loose, mattress hiss/leak + cold.
10 added (27 total) - within rounding distance of the spec's "30".
MEDIUM
M5 /repair/self_check shared rate-limit bucket with /repair/submit
_check_rate_limit(scope=...) - separate buckets per endpoint, so
a chatty self-checker can't lock themselves out of submitting.
Per-scope ICP cap key (fusion_repairs.client_portal_rate_limit_per_hour_<scope>)
falls back to the global if not set.
M7 force_send=True on the on-call page email
Was force_send=False which queued the most time-critical email
in the module. Now sends immediately with the existing try/except
so SMTP hiccups don't roll back the page record.
M8 QR generation swallowed all errors silently
_logger.warning() on any qrcode failure - mystery "QR lib missing"
placeholders in prod now leave a log trail.
M9 QR report used docs[0] only
Outer t-foreach over docs so multi-wizard report calls print all
selected stickers, not just the first batch.
M10 + M11
- Added models.Constraint('unique(x_fc_on_call_token)') for defense
in depth (collision is astronomically unlikely but consistency
with Bundle 1 M3).
- _send_page_email() returns True/False; _post_chatter only fires
on success. On failure a different chatter line says "page email
failed - verify SMTP".
LOW
L6 find_next_on_call() now filters by company_ids (cross-company safe).
Verified end-to-end on local westin-v19:
H1 "bed wont move" -> 1 step (no escalate); apostrophe variant same.
C1 page 1 -> gsingh; page 2 -> ak (different).
C2 powerchair+smoke -> escalate=True.
C3 bed+burning -> escalate=True.
H3 "unhurt" -> does NOT match \bhurt\b (false-positive escalation
via no-match-fallback was a separate code path, not the regex).
Bumped to 19.0.1.2.2.
Co-authored-by: Cursor <cursoragent@cursor.com>
246 lines
15 KiB
XML
246 lines
15 KiB
XML
<?xml version="1.0" encoding="utf-8"?>
|
|
<!--
|
|
Seed deterministic self-check rules per equipment category.
|
|
These are used by fusion.repair.ai.service when AI is unavailable,
|
|
when AI returns malformed/unsafe content, or when AI is disabled.
|
|
noupdate=1 so admins can customise per site without losing changes.
|
|
-->
|
|
<odoo>
|
|
<data noupdate="1">
|
|
|
|
<!-- Hospital Bed -->
|
|
<record id="self_check_bed_no_power" model="fusion.repair.self.check.rule">
|
|
<field name="name">Hospital Bed - No Power</field>
|
|
<field name="category_id" ref="category_hospital_bed"/>
|
|
<field name="sequence">10</field>
|
|
<field name="symptom_keywords">won't move,dead,no power,no response</field>
|
|
<field name="instruction">Check the bed is plugged in and the outlet has power - try plugging a phone charger into the same outlet to confirm.</field>
|
|
<field name="expected_result">Bed responds when controls are pressed.</field>
|
|
</record>
|
|
<record id="self_check_bed_slow" model="fusion.repair.self.check.rule">
|
|
<field name="name">Hospital Bed - Slow / Sluggish</field>
|
|
<field name="category_id" ref="category_hospital_bed"/>
|
|
<field name="sequence">20</field>
|
|
<field name="symptom_keywords">slow,sluggish</field>
|
|
<field name="instruction">Unplug the bed for 30 seconds then plug it back in.</field>
|
|
<field name="expected_result">Movement returns to normal speed.</field>
|
|
</record>
|
|
<record id="self_check_bed_remote" model="fusion.repair.self.check.rule">
|
|
<field name="name">Hospital Bed - Remote Unresponsive</field>
|
|
<field name="category_id" ref="category_hospital_bed"/>
|
|
<field name="sequence">30</field>
|
|
<field name="symptom_keywords">remote,controller</field>
|
|
<field name="instruction">Replace the remote batteries with fresh AAA batteries.</field>
|
|
<field name="expected_result">Remote lights up and bed responds.</field>
|
|
</record>
|
|
<record id="self_check_bed_alarm" model="fusion.repair.self.check.rule">
|
|
<field name="name">Hospital Bed - Alarm</field>
|
|
<field name="category_id" ref="category_hospital_bed"/>
|
|
<field name="sequence">40</field>
|
|
<field name="symptom_keywords">beep,alarm,alert</field>
|
|
<field name="instruction">Check both side rails are fully locked in the raised position.</field>
|
|
<field name="expected_result">Alarm stops.</field>
|
|
</record>
|
|
<record id="self_check_bed_one_section" model="fusion.repair.self.check.rule">
|
|
<field name="name">Hospital Bed - One Section Won't Move</field>
|
|
<field name="category_id" ref="category_hospital_bed"/>
|
|
<field name="sequence">50</field>
|
|
<field name="symptom_keywords">one section,won't lift,stuck</field>
|
|
<field name="instruction">Check nothing is caught under the bed or jamming the mechanism (sheets, blankets, cords).</field>
|
|
<field name="expected_result">Section moves freely.</field>
|
|
</record>
|
|
|
|
<!-- Wheelchair (manual) -->
|
|
<record id="self_check_wheelchair_brake" model="fusion.repair.self.check.rule">
|
|
<field name="name">Wheelchair - Brake</field>
|
|
<field name="category_id" ref="category_wheelchair_manual"/>
|
|
<field name="sequence">10</field>
|
|
<field name="symptom_keywords">brake,stop</field>
|
|
<field name="instruction">Push the brake lever fully to the locked position and listen for a click.</field>
|
|
<field name="expected_result">Brake holds wheel firmly.</field>
|
|
</record>
|
|
<record id="self_check_wheelchair_tire" model="fusion.repair.self.check.rule">
|
|
<field name="name">Wheelchair - Hard to Push</field>
|
|
<field name="category_id" ref="category_wheelchair_manual"/>
|
|
<field name="sequence">20</field>
|
|
<field name="symptom_keywords">hard to push,drag,slow</field>
|
|
<field name="instruction">Check both tires for full inflation - firm to thumb pressure.</field>
|
|
<field name="expected_result">Wheelchair rolls freely.</field>
|
|
</record>
|
|
<record id="self_check_wheelchair_wobble" model="fusion.repair.self.check.rule">
|
|
<field name="name">Wheelchair - Wobbly Wheel</field>
|
|
<field name="category_id" ref="category_wheelchair_manual"/>
|
|
<field name="sequence">30</field>
|
|
<field name="symptom_keywords">wobble,loose wheel</field>
|
|
<field name="instruction">Try turning the axle nut gently by hand to feel if it is snug.</field>
|
|
<field name="expected_result">Wheel feels firm with no play.</field>
|
|
</record>
|
|
<record id="self_check_wheelchair_footrest" model="fusion.repair.self.check.rule">
|
|
<field name="name">Wheelchair - Footrest Loose</field>
|
|
<field name="category_id" ref="category_wheelchair_manual"/>
|
|
<field name="sequence">40</field>
|
|
<field name="symptom_keywords">footrest,footplate</field>
|
|
<field name="instruction">Slide the footrest fully into its housing until you hear a click.</field>
|
|
<field name="expected_result">Footrest feels secure.</field>
|
|
</record>
|
|
|
|
<!-- Wheelchair (power) -->
|
|
<record id="self_check_powerchair_battery" model="fusion.repair.self.check.rule">
|
|
<field name="name">Power Wheelchair - No Power</field>
|
|
<field name="category_id" ref="category_wheelchair_power"/>
|
|
<field name="sequence">10</field>
|
|
<field name="symptom_keywords">won't turn on,dead,no power,battery</field>
|
|
<field name="instruction">Confirm the battery indicator shows charge and the key switch is in the ON position.</field>
|
|
<field name="expected_result">Display lights up.</field>
|
|
</record>
|
|
<record id="self_check_powerchair_error" model="fusion.repair.self.check.rule">
|
|
<field name="name">Power Wheelchair - Error Code</field>
|
|
<field name="category_id" ref="category_wheelchair_power"/>
|
|
<field name="sequence">20</field>
|
|
<field name="symptom_keywords">error,flashing,code</field>
|
|
<field name="instruction">Note the error code shown on the joystick display, then turn off and back on after 30 seconds.</field>
|
|
<field name="expected_result">Error clears or a specific code is captured.</field>
|
|
</record>
|
|
<record id="self_check_powerchair_one_side" model="fusion.repair.self.check.rule">
|
|
<field name="name">Power Wheelchair - One Side Weaker</field>
|
|
<field name="category_id" ref="category_wheelchair_power"/>
|
|
<field name="sequence">30</field>
|
|
<field name="symptom_keywords">one side weaker,pulls</field>
|
|
<field name="instruction">Charge the batteries fully overnight before testing again.</field>
|
|
<field name="expected_result">Both sides equal power after a full charge.</field>
|
|
</record>
|
|
|
|
<!-- Stairlift (safety-critical) -->
|
|
<record id="self_check_stairlift_seat" model="fusion.repair.self.check.rule">
|
|
<field name="name">Stairlift - Won't Move</field>
|
|
<field name="category_id" ref="category_stairlift"/>
|
|
<field name="sequence">10</field>
|
|
<field name="symptom_keywords">won't move,stuck</field>
|
|
<field name="instruction">Check the seat is fully rotated to the forward position and the seatbelt is fastened.</field>
|
|
<field name="expected_result">Stairlift responds.</field>
|
|
</record>
|
|
<record id="self_check_stairlift_track" model="fusion.repair.self.check.rule">
|
|
<field name="name">Stairlift - Stops Midway</field>
|
|
<field name="category_id" ref="category_stairlift"/>
|
|
<field name="sequence">20</field>
|
|
<field name="symptom_keywords">stops midway,halts</field>
|
|
<field name="instruction">Check the track for items blocking the sensors - toys, slippers, debris.</field>
|
|
<field name="expected_result">Stairlift completes its travel.</field>
|
|
</record>
|
|
<record id="self_check_stairlift_remote" model="fusion.repair.self.check.rule">
|
|
<field name="name">Stairlift - Call Station Unresponsive</field>
|
|
<field name="category_id" ref="category_stairlift"/>
|
|
<field name="sequence">30</field>
|
|
<field name="symptom_keywords">remote,call station</field>
|
|
<field name="instruction">Replace the remote / call-station batteries with fresh batteries.</field>
|
|
<field name="expected_result">Call station responds.</field>
|
|
</record>
|
|
<record id="self_check_stairlift_alarm" model="fusion.repair.self.check.rule">
|
|
<field name="name">Stairlift - Beeping / Alarm</field>
|
|
<field name="category_id" ref="category_stairlift"/>
|
|
<field name="sequence">40</field>
|
|
<field name="symptom_keywords">beep,alarm</field>
|
|
<field name="instruction">Confirm the seat swivel lock is engaged in the down position.</field>
|
|
<field name="expected_result">Beeping stops.</field>
|
|
</record>
|
|
|
|
<!-- Porch Lift (safety-critical) -->
|
|
<record id="self_check_porch_gate" model="fusion.repair.self.check.rule">
|
|
<field name="name">Porch Lift - Won't Move</field>
|
|
<field name="category_id" ref="category_porch_lift"/>
|
|
<field name="sequence">10</field>
|
|
<field name="symptom_keywords">won't move,dead</field>
|
|
<field name="instruction">Check all gate and door safety switches are fully closed.</field>
|
|
<field name="expected_result">Lift responds.</field>
|
|
</record>
|
|
<record id="self_check_porch_controls" model="fusion.repair.self.check.rule">
|
|
<field name="name">Porch Lift - Sticky Controls</field>
|
|
<field name="category_id" ref="category_porch_lift"/>
|
|
<field name="sequence">20</field>
|
|
<field name="symptom_keywords">sticky,stuck button</field>
|
|
<field name="instruction">If outdoors, gently wipe the controls with a dry cloth and let dry.</field>
|
|
<field name="expected_result">Controls respond.</field>
|
|
</record>
|
|
<record id="self_check_porch_overshoot" model="fusion.repair.self.check.rule">
|
|
<field name="name">Porch Lift - Won't Stop at Floor</field>
|
|
<field name="category_id" ref="category_porch_lift"/>
|
|
<field name="sequence">30</field>
|
|
<field name="symptom_keywords">won't stop,overshoot</field>
|
|
<field name="instruction">Note exactly which floor it stops at - do not attempt repeat use.</field>
|
|
<field name="expected_result">Information captured for technician.</field>
|
|
<field name="safety_note">Do not use the lift again until a technician inspects it.</field>
|
|
</record>
|
|
|
|
<!-- Walker / Rollator -->
|
|
<record id="self_check_walker_wheel" model="fusion.repair.self.check.rule">
|
|
<field name="name">Walker - Wheel Stuck</field>
|
|
<field name="category_id" ref="category_walker"/>
|
|
<field name="sequence">10</field>
|
|
<field name="symptom_keywords">wheel stick,won't roll</field>
|
|
<field name="instruction">Check for hair or debris wrapped around the wheel axle.</field>
|
|
<field name="expected_result">Wheel spins freely.</field>
|
|
</record>
|
|
<record id="self_check_walker_wobble" model="fusion.repair.self.check.rule">
|
|
<field name="name">Walker - Frame Wobbles</field>
|
|
<field name="category_id" ref="category_walker"/>
|
|
<field name="sequence">20</field>
|
|
<field name="symptom_keywords">wobble,loose</field>
|
|
<field name="instruction">Check all height adjustment pins are fully engaged through both holes.</field>
|
|
<field name="expected_result">Frame feels solid.</field>
|
|
<field name="safety_note">Wobbly walkers cause falls - stop using until repaired if movement persists.</field>
|
|
</record>
|
|
<record id="self_check_rollator_brake" model="fusion.repair.self.check.rule">
|
|
<field name="name">Rollator - Brake Won't Lock</field>
|
|
<field name="category_id" ref="category_rollator"/>
|
|
<field name="sequence">10</field>
|
|
<field name="symptom_keywords">brake won't lock,brake loose</field>
|
|
<field name="instruction">Push the brake lever fully down until you feel a click.</field>
|
|
<field name="expected_result">Brake holds.</field>
|
|
</record>
|
|
<record id="self_check_rollator_seat" model="fusion.repair.self.check.rule">
|
|
<field name="name">Rollator - Seat Loose</field>
|
|
<field name="category_id" ref="category_rollator"/>
|
|
<field name="sequence">20</field>
|
|
<field name="symptom_keywords">seat loose</field>
|
|
<field name="instruction">Tighten the seat knobs by hand until firm.</field>
|
|
<field name="expected_result">Seat feels secure.</field>
|
|
<field name="safety_note">Do not sit on a loose rollator seat - fall risk.</field>
|
|
</record>
|
|
|
|
<!-- Medical Mattress -->
|
|
<record id="self_check_mattress_pump" model="fusion.repair.self.check.rule">
|
|
<field name="name">Mattress - Deflated</field>
|
|
<field name="category_id" ref="category_mattress"/>
|
|
<field name="sequence">10</field>
|
|
<field name="symptom_keywords">deflated,flat,soft</field>
|
|
<field name="instruction">Confirm the pump is plugged in, powered on, and the hose is firmly attached.</field>
|
|
<field name="expected_result">Mattress inflates.</field>
|
|
</record>
|
|
<record id="self_check_mattress_alarm" model="fusion.repair.self.check.rule">
|
|
<field name="name">Mattress - Alarm</field>
|
|
<field name="category_id" ref="category_mattress"/>
|
|
<field name="sequence">20</field>
|
|
<field name="symptom_keywords">alarm,beep</field>
|
|
<field name="instruction">Check the pump display for the error code shown, then restart the pump by unplugging for 30 seconds.</field>
|
|
<field name="expected_result">Alarm clears.</field>
|
|
</record>
|
|
<record id="self_check_mattress_leak" model="fusion.repair.self.check.rule">
|
|
<field name="name">Mattress - Hissing / Leak</field>
|
|
<field name="category_id" ref="category_mattress"/>
|
|
<field name="sequence">30</field>
|
|
<field name="symptom_keywords">hiss,leak</field>
|
|
<field name="instruction">Listen at the valve - push the valve cap in firmly to ensure it is sealed.</field>
|
|
<field name="expected_result">Hissing stops.</field>
|
|
</record>
|
|
<record id="self_check_mattress_cold" model="fusion.repair.self.check.rule">
|
|
<field name="name">Mattress - Not Heating</field>
|
|
<field name="category_id" ref="category_mattress"/>
|
|
<field name="sequence">40</field>
|
|
<field name="symptom_keywords">cold,won't heat</field>
|
|
<field name="instruction">Confirm the heat dial is set above zero and allow 15 minutes to warm.</field>
|
|
<field name="expected_result">Mattress feels warm.</field>
|
|
</record>
|
|
|
|
</data>
|
|
</odoo>
|