changes
This commit is contained in:
@@ -5,7 +5,7 @@
|
||||
|
||||
{
|
||||
'name': 'Fusion Plating — Logistics',
|
||||
'version': '19.0.3.8.0',
|
||||
'version': '19.0.3.9.0',
|
||||
'category': 'Manufacturing/Plating',
|
||||
'summary': (
|
||||
'Pickup & delivery for plating shops: vehicle master, driver '
|
||||
@@ -43,6 +43,7 @@ Copyright (c) 2026 Nexa Systems Inc. All rights reserved.
|
||||
'fusion_plating',
|
||||
'fusion_plating_configurator',
|
||||
'fusion_plating_receiving', # Shared "Shipping & Receiving" menu root
|
||||
'fusion_shipping',
|
||||
'hr',
|
||||
'mail',
|
||||
],
|
||||
|
||||
@@ -123,6 +123,86 @@ class FpDelivery(models.Model):
|
||||
'ir.attachment',
|
||||
string='Packing List',
|
||||
)
|
||||
|
||||
# ---- Phase A — outbound carrier + shipment link ----------------------
|
||||
# Mirrors the fields on fp.receiving. Populated by
|
||||
# fp.job._fp_create_delivery from the linked receiving when this
|
||||
# delivery is auto-created on job-done; shipping crew can override
|
||||
# at ship time.
|
||||
x_fc_carrier_id = fields.Many2one(
|
||||
'delivery.carrier', string='Outbound Carrier', tracking=True,
|
||||
ondelete='set null',
|
||||
help='Carrier picked at receiving time; can be overridden by '
|
||||
'the shipping crew before issuing the label.',
|
||||
)
|
||||
x_fc_outbound_shipment_id = fields.Many2one(
|
||||
'fusion.shipment', string='Outbound Shipment', tracking=True,
|
||||
ondelete='set null',
|
||||
copy=False,
|
||||
help='The shipment record carrying weight, dimensions, label '
|
||||
'PDF, and tracking. Usually the same shipment that was '
|
||||
'created at receiving time.',
|
||||
)
|
||||
x_fc_outbound_shipment_count = fields.Integer(
|
||||
compute='_compute_x_fc_outbound_shipment_count',
|
||||
)
|
||||
|
||||
@api.depends('x_fc_outbound_shipment_id')
|
||||
def _compute_x_fc_outbound_shipment_count(self):
|
||||
for rec in self:
|
||||
rec.x_fc_outbound_shipment_count = (
|
||||
1 if rec.x_fc_outbound_shipment_id else 0
|
||||
)
|
||||
|
||||
@api.onchange('x_fc_carrier_id')
|
||||
def _onchange_x_fc_carrier_id(self):
|
||||
for rec in self:
|
||||
ship = rec.x_fc_outbound_shipment_id
|
||||
if ship and ship.status == 'draft' and rec.x_fc_carrier_id:
|
||||
ship.carrier_id = rec.x_fc_carrier_id.id
|
||||
|
||||
def action_create_outbound_shipment(self):
|
||||
self.ensure_one()
|
||||
if self.x_fc_outbound_shipment_id:
|
||||
return self.action_view_outbound_shipment()
|
||||
if 'fusion.shipment' not in self.env:
|
||||
raise UserError(_(
|
||||
'fusion_shipping module is not installed. '
|
||||
'Cannot create an outbound shipment.'
|
||||
))
|
||||
SO = self.env['sale.order'].sudo()
|
||||
so = False
|
||||
if self.job_ref:
|
||||
Job = self.env.get('fp.job')
|
||||
if Job is not None:
|
||||
job = Job.sudo().search(
|
||||
[('name', '=', self.job_ref)], limit=1,
|
||||
)
|
||||
so = job.sale_order_id if job else False
|
||||
vals = {
|
||||
'sale_order_id': so.id if so else False,
|
||||
'carrier_id': self.x_fc_carrier_id.id if self.x_fc_carrier_id else False,
|
||||
'status': 'draft',
|
||||
}
|
||||
shipment = self.env['fusion.shipment'].sudo().create(vals)
|
||||
self.x_fc_outbound_shipment_id = shipment.id
|
||||
self.message_post(body=_(
|
||||
'Outbound shipment <b>%s</b> created (draft).'
|
||||
) % shipment.name)
|
||||
return self.action_view_outbound_shipment()
|
||||
|
||||
def action_view_outbound_shipment(self):
|
||||
self.ensure_one()
|
||||
if not self.x_fc_outbound_shipment_id:
|
||||
return False
|
||||
return {
|
||||
'type': 'ir.actions.act_window',
|
||||
'name': self.x_fc_outbound_shipment_id.name,
|
||||
'res_model': 'fusion.shipment',
|
||||
'res_id': self.x_fc_outbound_shipment_id.id,
|
||||
'view_mode': 'form',
|
||||
'target': 'current',
|
||||
}
|
||||
state = fields.Selection(
|
||||
[
|
||||
('draft', 'Draft'),
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from . import test_delivery_shipping_fields
|
||||
@@ -0,0 +1,25 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright 2026 Nexa Systems Inc.
|
||||
# License OPL-1 (Odoo Proprietary License v1.0)
|
||||
"""Phase A — mirror carrier + outbound shipment fields on fp.delivery."""
|
||||
from odoo.tests.common import TransactionCase
|
||||
|
||||
|
||||
class TestDeliveryShippingFields(TransactionCase):
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super().setUpClass()
|
||||
cls.partner = cls.env['res.partner'].create({'name': 'ShipCust'})
|
||||
|
||||
def test_carrier_id_field_exists_on_delivery(self):
|
||||
delivery = self.env['fusion.plating.delivery'].create({
|
||||
'partner_id': self.partner.id,
|
||||
})
|
||||
self.assertIn('x_fc_carrier_id', delivery._fields)
|
||||
|
||||
def test_outbound_shipment_id_field_exists_on_delivery(self):
|
||||
delivery = self.env['fusion.plating.delivery'].create({
|
||||
'partner_id': self.partner.id,
|
||||
})
|
||||
self.assertIn('x_fc_outbound_shipment_id', delivery._fields)
|
||||
@@ -59,6 +59,16 @@
|
||||
statusbar_visible="draft,scheduled,en_route,delivered"/>
|
||||
</header>
|
||||
<sheet>
|
||||
<div class="oe_button_box" name="button_box">
|
||||
<button name="action_create_outbound_shipment"
|
||||
type="object"
|
||||
class="oe_stat_button"
|
||||
icon="fa-truck">
|
||||
<field name="x_fc_outbound_shipment_count"
|
||||
widget="statinfo"
|
||||
string="Outbound Shipment"/>
|
||||
</button>
|
||||
</div>
|
||||
<div class="oe_title">
|
||||
<label for="name"/>
|
||||
<h1><field name="name" readonly="1"/></h1>
|
||||
@@ -84,7 +94,9 @@
|
||||
<field name="vehicle_id"/>
|
||||
<field name="tdg_required" widget="boolean_toggle"/>
|
||||
</group>
|
||||
<group string="Documents">
|
||||
<group string="Outbound Shipping">
|
||||
<field name="x_fc_carrier_id"
|
||||
options="{'no_create': True}"/>
|
||||
<field name="coc_attachment_id"/>
|
||||
<field name="packing_list_attachment_id"/>
|
||||
<field name="pod_id" readonly="1"/>
|
||||
|
||||
Reference in New Issue
Block a user