95 lines
3.9 KiB
Python
95 lines
3.9 KiB
Python
# -*- coding: utf-8 -*-
|
|
# Copyright 2026 Nexa Systems Inc.
|
|
# License OPL-1 (Odoo Proprietary License v1.0)
|
|
"""Phase A — carrier field + outbound shipment link tests on fp.receiving.
|
|
|
|
See docs/superpowers/specs/2026-05-18-phase-a-shipping-carrier-foundation-design.md.
|
|
"""
|
|
from odoo.tests.common import TransactionCase
|
|
|
|
|
|
class TestCarrierFields(TransactionCase):
|
|
|
|
@classmethod
|
|
def setUpClass(cls):
|
|
super().setUpClass()
|
|
cls.partner = cls.env['res.partner'].create({'name': 'CarrierCust'})
|
|
cls.product = cls.env['product.product'].create({'name': 'Widget'})
|
|
cls.so = cls.env['sale.order'].create({
|
|
'partner_id': cls.partner.id,
|
|
'order_line': [(0, 0, {
|
|
'product_id': cls.product.id,
|
|
'product_uom_qty': 1,
|
|
})],
|
|
})
|
|
# Carrier records seeded by data/delivery_carrier_seed_data.xml.
|
|
cls.carrier_ups = cls.env.ref(
|
|
'fusion_plating_receiving.delivery_carrier_ups',
|
|
)
|
|
cls.carrier_fedex = cls.env.ref(
|
|
'fusion_plating_receiving.delivery_carrier_fedex',
|
|
)
|
|
|
|
def _make_receiving(self, **kw):
|
|
vals = {'sale_order_id': self.so.id}
|
|
vals.update(kw)
|
|
return self.env['fp.receiving'].create(vals)
|
|
|
|
# ---- Field existence ------------------------------------------------
|
|
|
|
def test_carrier_id_field_exists_on_receiving(self):
|
|
recv = self._make_receiving()
|
|
self.assertIn('x_fc_carrier_id', recv._fields)
|
|
|
|
def test_outbound_shipment_id_field_exists_on_receiving(self):
|
|
recv = self._make_receiving()
|
|
self.assertIn('x_fc_outbound_shipment_id', recv._fields)
|
|
|
|
# ---- action_create_outbound_shipment --------------------------------
|
|
|
|
def test_action_create_outbound_shipment_creates_draft(self):
|
|
recv = self._make_receiving(x_fc_carrier_id=self.carrier_ups.id)
|
|
self.assertFalse(recv.x_fc_outbound_shipment_id)
|
|
recv.action_create_outbound_shipment()
|
|
self.assertTrue(recv.x_fc_outbound_shipment_id)
|
|
ship = recv.x_fc_outbound_shipment_id
|
|
self.assertEqual(ship.status, 'draft')
|
|
self.assertEqual(ship.carrier_id, self.carrier_ups)
|
|
self.assertEqual(ship.sale_order_id, self.so)
|
|
|
|
def test_action_create_outbound_shipment_idempotent(self):
|
|
recv = self._make_receiving(x_fc_carrier_id=self.carrier_ups.id)
|
|
recv.action_create_outbound_shipment()
|
|
first_ship = recv.x_fc_outbound_shipment_id
|
|
recv.action_create_outbound_shipment()
|
|
# Second call must not create a new shipment.
|
|
self.assertEqual(recv.x_fc_outbound_shipment_id, first_ship)
|
|
count = self.env['fusion.shipment'].search_count([
|
|
('sale_order_id', '=', self.so.id),
|
|
])
|
|
self.assertEqual(count, 1)
|
|
|
|
# ---- onchange propagation -------------------------------------------
|
|
|
|
def test_carrier_id_change_propagates_to_draft_shipment(self):
|
|
recv = self._make_receiving(x_fc_carrier_id=self.carrier_ups.id)
|
|
recv.action_create_outbound_shipment()
|
|
ship = recv.x_fc_outbound_shipment_id
|
|
self.assertEqual(ship.carrier_id, self.carrier_ups)
|
|
# Onchange triggers via the Form helper — we simulate by calling
|
|
# the handler directly after writing.
|
|
recv.x_fc_carrier_id = self.carrier_fedex.id
|
|
recv._onchange_x_fc_carrier_id()
|
|
self.assertEqual(ship.carrier_id, self.carrier_fedex)
|
|
|
|
def test_carrier_id_change_does_not_propagate_to_confirmed_shipment(self):
|
|
recv = self._make_receiving(x_fc_carrier_id=self.carrier_ups.id)
|
|
recv.action_create_outbound_shipment()
|
|
ship = recv.x_fc_outbound_shipment_id
|
|
# Confirm the shipment — propagation must stop.
|
|
ship.status = 'confirmed'
|
|
recv.x_fc_carrier_id = self.carrier_fedex.id
|
|
recv._onchange_x_fc_carrier_id()
|
|
# Confirmed shipment retains the original carrier.
|
|
self.assertEqual(ship.carrier_id, self.carrier_ups)
|