Files
odoo-addons/addons/at_master_order/INVOICE_SHIPMENT_TRACKING.md

9.9 KiB

Invoice-Centric Shipment Tracking

Overview

This document describes the implementation of shipment tracking integrated directly into customer invoices, replacing the separate Shipment tab in Master Order.


Business Requirements

Core Principle

Invoice = Commercial + Shipment unit Shipment does not exist without invoice. Customer tracks shipment by invoice.

Key Decisions

Decision Value
Shipping Methods Sea, Air (only)
Shipping Company Source res.partner with is_shipper flag
Shipping Selection Optional at invoice creation, editable on invoice form
Shipping Charge Added later via button, creates vendor bill
Old Shipment Model Delete at.master.order.shipment (testing phase)

Workflow

Step 1: Create Invoice

┌─────────────────────────────────────────────────────────────┐
│ CREATE INVOICE WIZARD                                       │
├─────────────────────────────────────────────────────────────┤
│ Products: [Product A, Product B...]                         │
│                                                             │
│ ☐ Include Shipping (Optional)                               │
│   └── IF checked:                                           │
│       Shipping Company: [MSC Shipping ▼]                    │
│       Shipping Method:  [Sea ▼ / Air ▼]                     │
│                                                             │
│                                    [Create Invoice]         │
└─────────────────────────────────────────────────────────────┘

Result: Invoice created with optional shipping context (no charge yet)

Step 2: Add/Edit Shipping Details (On Invoice Form)

┌─────────────────────────────────────────────────────────────┐
│ INVOICE FORM - Shipment Tracking Section                    │
├─────────────────────────────────────────────────────────────┤
│ Shipping Company: [MSC ▼]        Method: [🚢 Sea ▼]        │
│ Container #:      [MSKU8821456]  Status: [In Transit]       │
│ ETD:              [2026-01-15]   Actual Ship: [2026-01-16]  │
│ ETA:              [2026-02-12]   Delivered:   [________]    │
│ Notes:            [Customs cleared...]                      │
└─────────────────────────────────────────────────────────────┘

Step 3: Add Shipping Charge (Creates Bill)

User clicks [Add Shipping Charge] button on invoice:

┌─────────────────────────────────────────────────────────────┐
│ ADD SHIPPING CHARGE                                         │
├─────────────────────────────────────────────────────────────┤
│ Shipping Company:  MSC Shipping (from invoice)              │
│ Shipping Cost:     $800         ← Pay to shipper            │
│ Shipping Charge:   $1,000       ← Charge customer           │
│                                                             │
│ ☑ Add to Customer Invoice (as line)                         │
│ ☑ Create Vendor Bill for Shipping Cost                      │
│                                                             │
│                                         [Confirm]           │
└─────────────────────────────────────────────────────────────┘

Result:

  • Invoice line added: "Shipping Charge: $1,000"
  • Vendor bill created: Partner=MSC, Amount=$800, auto-confirmed
  • Shipping margin tracked: $200 profit

Data Model Changes

1. New Field on res.partner

Field Type Purpose
is_shipper Boolean Filter for shipping company dropdown

2. New Fields on account.move (Customer Invoices)

Field Type Required Purpose
shipper_id Many2one (res.partner) No Shipping company
shipment_method Selection No 'sea' / 'air'
container_tracking Char No Container # or AWB
etd Date No Estimated Time of Departure
eta Date No Estimated Time of Arrival
actual_ship_date Date No When goods shipped
actual_delivery_date Date No When goods delivered
shipment_status Selection (Computed) Auto Status based on dates
shipment_notes Text No Notes about shipment
shipping_cost Float No Cost paid to shipper
shipping_charge Float No Amount charged to customer
shipping_margin Float (Computed) Auto charge - cost
shipping_bill_id Many2one (account.move) No Link to shipping vendor bill

3. New Field on at.master.order

Field Type Purpose
overall_shipment_status Selection (Computed) Aggregated from invoices

Shipment Status Logic

Invoice Level

IF not shipper_id:
    status = 'no_shipping'
ELIF actual_delivery_date:
    status = 'delivered'
ELIF actual_ship_date:
    IF eta AND today > eta:
        status = 'delayed'
    ELSE:
        status = 'in_transit'
ELIF shipper_id:
    status = 'pending'
ELSE:
    status = 'draft'

Master Order Level

invoice_statuses = [inv.shipment_status for inv in posted_invoices]

IF all(s == 'delivered' for s in invoice_statuses):
    status = 'delivered'
ELIF any(s == 'delayed' for s in invoice_statuses):
    status = 'delayed'
ELIF any(s == 'in_transit' for s in invoice_statuses):
    status = 'in_transit'
ELIF any(s == 'pending' for s in invoice_statuses):
    status = 'pending'
ELIF len(set(invoice_statuses)) > 1:
    status = 'partial'
ELSE:
    status = 'not_shipped'

View Changes

1. Master Order Form

REMOVE:

  • <page string="Shipping" name="shipping"> entire section

MODIFY - Invoice Tab: Add columns to invoice list:

  • Shipment Status (badge)
  • Ship Method (icon)
  • Container/Tracking
  • ETA

ADD - Header:

  • Overall shipment status field

2. Invoice Form

ADD - Before Notebook:

  • Shipment Tracking section (visible only for out_invoice)

ADD - Button:

  • "Add Shipping Charge" button in header

3. Create Invoice Wizard

ADD:

  • Optional shipping company selection
  • Shipping method selection

Files to Modify

File Action
models/shipment.py DELETE entire file
models/__init__.py Remove shipment import
views/shipment_views.xml DELETE entire file
views/master_order_views.xml Remove Shipping tab, enhance Invoice tab
security/ir.model.access.csv Remove shipment model access
data/ir_sequence_data.xml Remove shipment sequence (if exists)
__manifest__.py Remove shipment_views.xml reference
models/account_move.py Add shipment tracking fields
models/res_partner.py CREATE - Add is_shipper field
models/master_order.py Add overall_shipment_status, remove shipment references
wizard/create_invoice_wizard.py Add shipping company selection
wizard/create_invoice_wizard_views.xml Add shipping fields to wizard

Implementation Phases

Phase 1: Cleanup

  1. Delete at.master.order.shipment model and related files
  2. Remove Shipping tab from Master Order views
  3. Clean up manifest and security files

Phase 2: Partner Enhancement

  1. Add is_shipper field to res.partner
  2. Create partner form extension view

Phase 3: Invoice Enhancement

  1. Add shipment tracking fields to account.move
  2. Add computed shipment_status field
  3. Add Shipment Tracking section to invoice form
  4. Add shipment columns to invoice list in Master Order

Phase 4: Shipping Charge Workflow

  1. Create "Add Shipping Charge" wizard
  2. Implement invoice line creation
  3. Implement vendor bill creation (auto-confirmed)

Phase 5: Master Order Integration

  1. Add overall_shipment_status computed field
  2. Update Invoice tab view with shipment columns
  3. Add status display in header

Phase 6: Create Invoice Wizard Update

  1. Add optional shipping company field
  2. Add shipping method selection
  3. Pass values to created invoice

Status Badge Colors

Status Color Icon
No Shipping Gray
Draft Gray
Pending Yellow 🟡
In Transit Blue 🚚
Delayed Red 🔴
Delivered Green

Customer Portal (Future)

Portal enhancements will include:

  • Shipment status visible on invoice list
  • Shipment tracking section on invoice detail
  • Carrier tracking link integration

Accounting Safety

  • Shipment fields are informational only
  • No impact on journal entries or reconciliation
  • Shipping bill uses standard Odoo vendor bill workflow
  • All changes tracked via Odoo tracking mechanism

Migration Notes

  • No data migration needed (shipment model was in testing)
  • Existing invoices will have empty shipment fields
  • Users can populate shipment data on existing invoices manually