Tower: upload at_master_order 18.0.10.0 (via marketplace)
This commit is contained in:
284
addons/at_master_order/INVOICE_SHIPMENT_TRACKING.md
Normal file
284
addons/at_master_order/INVOICE_SHIPMENT_TRACKING.md
Normal file
@@ -0,0 +1,284 @@
|
|||||||
|
# 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
|
||||||
|
|
||||||
|
```python
|
||||||
|
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
|
||||||
|
|
||||||
|
```python
|
||||||
|
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
|
||||||
Reference in New Issue
Block a user