feat(fusion_repairs): Bundle 1 - wizard polish (C1 + C5 + C6 + D2 + T1)
C1 duplicate-call detection - Wizard computes duplicate_count + duplicate_repair_ids when partner is picked (open repairs from the configurable window, default 14 days). - Yellow banner with "Open Existing Repair" button to jump to the most recent duplicate so CS can add a note instead of creating a new repair. C5 outstanding-balance warning - Wizard sums posted unpaid account.move.amount_residual across all invoices of the partner. - Red banner shown when balance >= fusion_repairs.outstanding_balance_threshold (default $100) with a "View Invoices" button. C6 quote-only mode - New quote_only boolean on the wizard; passed through the shared intake service. Skips dispatch-task creation for urgent/safety AND for catalogue auto_schedule. Chatter note "Created in Quote Only mode" posted on the resulting repair.order. D2 skills filter on dispatch picker - _pick_dispatch_technician(repair) prefers users whose x_fc_repair_skills Many2many contains the repair's product category. Three-tier preference: 1) intake user if field staff AND has the skill 2) any active field-staff user with the skill 3) any active field-staff user (no skill filter) - last-resort - Logs a warning + skips task creation if no field-staff user exists at all. T1 Open in Maps on technician task - action_open_in_maps() returns ir.actions.act_url to https://www.google.com/maps?q=<URL-encoded address>. Deep-links into Apple Maps / Google Maps native apps on iOS / Android, browser otherwise. - Header button added on the fusion.technician.task form (after the existing buttons) plus a "View Repair" button when x_fc_repair_order_id is set. Verified end-to-end on local westin-v19: Existing repair: RO-202605-06 C1 duplicate_count = 5 (>=1 expected) - last duplicate: RO-202605-06 C5 balance check ran without error (target partner had $0) C6 quote-only repair: RO-202605-07 tech_tasks = 0 (expected 0) D2 picked the only stairlift-skilled field-staff user T1 Maps URL: https://www.google.com/maps?q=15+Fisherman+Dr%2C+Brampton%2C+ON+L7A+1B7%2C+Canad... Bumped to 19.0.1.1.0. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -4,7 +4,7 @@
|
||||
|
||||
from markupsafe import Markup
|
||||
|
||||
from odoo import fields, models
|
||||
from odoo import _, fields, models
|
||||
|
||||
|
||||
class FusionTechnicianTaskRepairs(models.Model):
|
||||
@@ -69,3 +69,34 @@ class FusionTechnicianTaskRepairs(models.Model):
|
||||
'view_mode': 'form',
|
||||
'res_id': self.x_fc_repair_order_id.id,
|
||||
}
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# T1: Open in Maps - returns an act_url action that opens the device's
|
||||
# default maps app (Apple Maps on iOS, Google Maps on Android, browser
|
||||
# otherwise). Address is built from the task's address fields with the
|
||||
# partner address as a fallback.
|
||||
# ------------------------------------------------------------------
|
||||
def action_open_in_maps(self):
|
||||
self.ensure_one()
|
||||
from urllib.parse import quote_plus
|
||||
parts = []
|
||||
for f in ('address_street', 'address_city', 'address_zip'):
|
||||
v = getattr(self, f, None)
|
||||
if v:
|
||||
parts.append(str(v))
|
||||
if not parts and self.partner_id:
|
||||
for f in ('street', 'street2', 'city', 'state_id', 'zip'):
|
||||
v = getattr(self.partner_id, f, None)
|
||||
if v:
|
||||
parts.append(v.name if hasattr(v, 'name') else str(v))
|
||||
if not parts:
|
||||
from odoo.exceptions import UserError
|
||||
raise UserError(_('No address on this task or its client.'))
|
||||
query = quote_plus(', '.join(parts))
|
||||
# https://www.google.com/maps?q=ADDR works on every platform and
|
||||
# automatically deep-links into the native app where supported.
|
||||
return {
|
||||
'type': 'ir.actions.act_url',
|
||||
'url': f'https://www.google.com/maps?q={query}',
|
||||
'target': 'new',
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user