Tower: upload at_master_order 18.0.10.0 (via marketplace)

This commit is contained in:
2026-04-30 19:03:50 +00:00
parent b3c96f6416
commit 285e2e807a

View 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