diff --git a/fusion_claims/models/technician_task.py b/fusion_claims/models/technician_task.py index a74a80cc..7371b6bc 100644 --- a/fusion_claims/models/technician_task.py +++ b/fusion_claims/models/technician_task.py @@ -72,6 +72,15 @@ class FusionTechnicianTaskClaims(models.Model): default=False, ) + # ------------------------------------------------------------------ + # SERVICE BOOKING FIELDS + # ------------------------------------------------------------------ + + x_fc_service_call_type = fields.Char( + string='Service Call Type', + help='Rate code resolved by the booking wizard (e.g. callout_standard_rush).', + ) + # ------------------------------------------------------------------ # ONCHANGES # ------------------------------------------------------------------ @@ -389,6 +398,55 @@ class FusionTechnicianTaskClaims(models.Model): order.name, e, ) + # ------------------------------------------------------------------ + # SERVICE BOOKING HELPERS + # ------------------------------------------------------------------ + + @api.model + def _resolve_service_lines(self, category, timing, in_shop, distance_km): + """Return a list of sale.order.line vals dicts for a service booking, + priced from fusion.service.rate. Empty when in-shop (labour-only, added later).""" + Rate = self.env['fusion.service.rate'] + lines = [] + callout = Rate.get_callout(category, timing, in_shop=in_shop) + if not callout: + return lines + lines.append({ + 'product_id': callout.product_id.id, + 'name': callout.name, + 'product_uom_qty': 1.0, + 'price_unit': callout.price, + 'name_is_km': False, + }) + if callout.adds_per_km and distance_km: + per_km = Rate.get_rate('per_km') + if per_km: + lines.append({ + 'product_id': per_km.product_id.id, + 'name': '%s — %.1f km \xd7 2-way' % (per_km.name, distance_km), + 'product_uom_qty': round(distance_km * 2.0, 1), + 'price_unit': per_km.price, + 'name_is_km': True, + }) + return lines + + @api.model + def _build_service_so(self, partner, category, timing, in_shop, distance_km): + """Create a draft repair sale.order with the resolved call-out (+per-km) lines. + + Repair-SO identity is the x_fc_is_service_repair boolean (no crm.tag: fusion_claims + has no crm dependency). x_fc_sale_type is intentionally left blank — a service repair + is not one of the ADP/ODSP funder workflows, and the draft is editable afterwards. + """ + line_vals = self._resolve_service_lines(category, timing, in_shop, distance_km) + order_lines = [(0, 0, {k: v for k, v in l.items() if k != 'name_is_km'}) for l in line_vals] + so_vals = { + 'partner_id': partner.id, + 'x_fc_is_service_repair': True, + 'order_line': order_lines, + } + return self.env['sale.order'].create(so_vals) + # ------------------------------------------------------------------ # VIEW ACTIONS # ------------------------------------------------------------------ diff --git a/fusion_claims/tests/test_service_booking.py b/fusion_claims/tests/test_service_booking.py index 699ddc0a..ffc13921 100644 --- a/fusion_claims/tests/test_service_booking.py +++ b/fusion_claims/tests/test_service_booking.py @@ -29,3 +29,25 @@ class TestServiceBooking(TransactionCase): def test_sale_order_has_service_repair_flag(self): so = self.env['sale.order'].new({}) self.assertIn('x_fc_is_service_repair', so._fields) + + def test_resolve_service_lines_standard_rush(self): + Task = self.Task + lines = Task._resolve_service_lines('standard', 'rush', in_shop=False, distance_km=10.0) + # call-out $120 + per-km line qty 20 @ $0.70 + callout = [l for l in lines if l['price_unit'] == 120.0] + per_km = [l for l in lines if l['name_is_km']] + self.assertTrue(callout) + self.assertEqual(per_km[0]['product_uom_qty'], 20.0) + self.assertEqual(per_km[0]['price_unit'], 0.70) + + def test_resolve_service_lines_in_shop_empty_callout(self): + lines = self.Task._resolve_service_lines('standard', 'normal', in_shop=True, distance_km=5.0) + self.assertEqual(lines, []) + + def test_build_service_so(self): + partner = self.env['res.partner'].create({'name': 'Walk-in Wanda'}) + so = self.Task._build_service_so(partner, 'standard', 'normal', False, 0.0) + self.assertEqual(so.state, 'draft') + self.assertTrue(so.x_fc_is_service_repair) + self.assertEqual(so.partner_id, partner) + self.assertEqual(so.order_line[0].price_unit, 95.0)