Skip to content

Commit 3bffcee

Browse files
authored
Merge pull request #938 from karrioapi/karrio-patch-2026.1.2
[patch] Karrio 2026.1.2
2 parents 426932c + ad55861 commit 3bffcee

File tree

436 files changed

+84244
-12554
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

436 files changed

+84244
-12554
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,7 @@ apps/api/karrio/server/staticfiles/*
135135

136136
.karrio/
137137
packages/karriojs/api/generated
138+
packages/types/rest/docs
138139
!docker/.env
139140

140141
# Karrio plugins

AGENTS.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -446,7 +446,8 @@ karrio test --failfast karrio.server.<module>.tests # single module
446446

447447
### Django Test Writing Style (Important!)
448448

449-
- **Always add `print(response)` before `self.assertResponseNoErrors(response)`** for easier debugging
449+
- **When debugging failing tests**, add `print(response)` before assertions to see the actual response
450+
- **Remove print statements once tests pass**—keep test output clean
450451
- **Create objects via API requests**, not direct model manipulation
451452
- **Use `self.assertResponseNoErrors(response)` first**, then:
452453
- **Single comprehensive assertion**: `self.assertDictEqual` or `self.assertListEqual` with full response data
@@ -459,7 +460,7 @@ from unittest import mock
459460

460461
def test_create_shipment(self):
461462
response = self.client.post('/api/shipments', data={...})
462-
print(response) # Always add this for debugging!
463+
# print(response) # Uncomment for debugging, remove when tests pass
463464
self.assertResponseNoErrors(response)
464465
self.assertDictEqual(
465466
response.data,

CHANGELOG.md

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,39 @@
1+
# Karrio 2026.1.2
2+
3+
## Changes
4+
5+
### Feat
6+
7+
- feat(asendia): add Asendia carrier integration with shipping, tracking, manifest support and multi-package handling
8+
- feat(spring): add Spring carrier integration with shipping, tracking, cancellation and CSV-based rating
9+
- feat: add event injection API for programmatic tracking event creation
10+
- feat: introduce products GraphQL API with JSONField optimization for better query performance
11+
- feat: add options meta and document category unified enum
12+
- feat: add carrier icons for new integrations
13+
- feat: improve address, parcel and products templates with database structure optimization
14+
15+
### Fix
16+
17+
- fix(dhl_parcel_de): correct addressHouse parsing
18+
- fix(fedex): update signed_by fallback for B2B shipments
19+
- fix(fedex): OC status should not be considered picked up
20+
- fix(fedex): update TrackingStatus to new format
21+
- fix(ups): correct shipment_origin values and add pickup date to trackers
22+
- fix(frontend): add GLS to carrier images
23+
24+
### Refactor
25+
26+
- refactor: migrate order details page to shadcn components with sidebar layout
27+
- refactor: connections management for better data normalization and optimized reads
28+
- refactor: enhance tracking events with TrackingIncidentReason
29+
30+
### Chore
31+
32+
- chore: QA improvements and migration integrity fixes
33+
- test: add comprehensive tracking tests
34+
35+
---
36+
137
# Karrio 2026.1.1
238

339
## Changes

PRDs/ADDRESS_PARCEL_PRODUCT_REFACTORING.md

Lines changed: 5785 additions & 0 deletions
Large diffs are not rendered by default.

PRDs/CARRIER_CONNECTION_ARCHITECTURE_UPGRADE.md

Lines changed: 69 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -45,16 +45,82 @@ This document outlines a comprehensive architectural upgrade to the Karrio carri
4545

4646
### Key Design Decisions
4747

48+
#### Architecture Decisions
4849
1. **Brokered configs are operational only** - No credential overrides, only operational settings
49-
2. **System credentials never exposed** - BrokeredConnection.credentials always returns `None`; gateway accesses system_connection.credentials directly
50+
2. **System credentials never exposed** - BrokeredConnection.credentials always returns `None`; gateway accesses `_get_credentials()` internally
5051
3. **Capabilities are overridable** - Brokered connections can restrict/modify capabilities (e.g., disable rating)
51-
4. **Implicit visibility** - BrokeredConnection existence grants access; AccountConnection in OSS is system-wide accessible (Insiders: org-scoped)
52+
4. **Implicit visibility** - BrokeredConnection existence grants access; Carrier in OSS is system-wide accessible (Insiders: org-scoped via CarrierLink)
5253
5. **Rate sheets inherited** - Brokered uses system connection's rate sheet as-is
5354
6. **Unified REST API** - Single schema, GraphQL exposes three types separately
54-
7. **Pattern-based migration** - Detect "system-like" carriers for automatic conversion
55+
7. **Pattern-based migration** - Detect "system-like" carriers (is_system=True) for automatic conversion
5556
8. **Unified ID prefix** - All connection types use `car_xxx` prefix for consistency
5657
9. **Simple property names** - BrokeredConnection uses `config`, `carrier_id`, `display_name`, `capabilities` (not `effective_*`)
5758

59+
#### Model & Naming Decisions
60+
10. **Keep Carrier model name** - Do NOT rename to AccountConnection; remove `is_system`, `active_users`, `active_orgs` fields
61+
11. **Single utility module** - Consolidate GatewayMixin, UnifiedConnection, ConnectionResolver into single `carriers.py` utility with `resolve_carrier()` and `create_snapshot()` functions
62+
12. **Gateway logic on models** - Each model (Carrier, SystemConnection, BrokeredConnection) keeps its own `gateway` property
63+
13. **Complete gateway.Carriers replacement** - `gateway.Connections` completely replaces `gateway.Carriers` (no alias)
64+
14. **Models-only exports** - Export SystemConnection, BrokeredConnection, Carrier; keep utilities internal
65+
66+
#### Migration Decisions
67+
15. **MOVE data, not copy** - System carriers are MOVED to SystemConnection table (deleted from Carrier after migration)
68+
16. **Copy CarrierConfig to BrokeredConnection** - User/org-specific CarrierConfig.config migrated to BrokeredConnection.config_overrides
69+
17. **Delete CarrierConfig table** - Remove CarrierConfig model and table in same migration
70+
18. **Prefer orgs over users** - In Insiders mode: create BrokeredConnections for active_orgs only; OSS: active_users only
71+
19. **Unused system carriers preserved** - System carriers with no active_users/active_orgs still become SystemConnection (can be enabled later)
72+
20. **Django ORM migrations only** - No raw SQL; regenerate fresh migrations
73+
74+
#### Legacy FK Decisions
75+
21. **FK → JSONField conversion** - Remove all carrier FKs (pickup_carrier, tracking_carrier, etc.) and replace with `carrier_snapshot` JSONField
76+
22. **Drop Shipment.carriers M2M** - Remove entirely; `selected_rate` JSONField already contains carrier info
77+
23. **Carrier snapshot minimal data** - Store: connection_id, connection_type, carrier_code, carrier_id, carrier_name, test_mode (no capabilities, no config)
78+
24. **Visibility via CarrierLink only** - Remove active_users/active_orgs M2M; OSS: all carriers visible; Insiders: org-scoped via CarrierLink
79+
25. **Orgs package in same PR** - Create BrokeredConnectionLink in orgs package as part of this migration
80+
81+
#### Implementation Details
82+
26. **Utility in core/utils.py** - Add `resolve_carrier()` and `create_snapshot()` functions to existing core utils module
83+
27. **Org brokered created_by is null** - Org-scoped BrokeredConnections have created_by=null; access via BrokeredConnectionLink
84+
28. **Simple snapshot, no fallback ID** - Snapshot contains connection_id only; if connection deleted, use snapshot for display only
85+
29. **resolve_carrier() returns None** - When connection not found or access denied, return None (caller handles)
86+
30. **Brokered snapshot uses system ID** - When BrokeredConnection is used, snapshot stores SystemConnection ID (stable if brokered deleted)
87+
31. **Connection type values** - Use "account", "system", "brokered" as connection_type values in snapshots
88+
32. **SystemConnection.created_by** - Nullable FK(User, on_delete=SET_NULL) to track admin who created it
89+
33. **Brokered resolution with system ID** - When resolving type='brokered' snapshot: find user's BrokeredConnection for that SystemConnection; return it if found, else return SystemConnection
90+
34. **Brokered snapshot uses computed values** - Snapshot stores system.id as connection_id but uses brokered's computed carrier_id, carrier_name (respects overrides)
91+
35. **Connections API: list() and first()** - Keep simple: `list()` returns all matching, `first()` returns first match
92+
36. **Forward-only migration** - No reverse migration. Data is moved. Manual intervention needed for rollback.
93+
94+
### Areas Requiring Updates (Carrier References)
95+
96+
The following files/modules reference the Carrier model and will need updates:
97+
98+
**Core Module:**
99+
- `modules/core/karrio/server/core/gateway.py` - Main gateway.Carriers class
100+
- `modules/core/karrio/server/core/filters.py` - Carrier filtering
101+
- `modules/core/karrio/server/providers/serializers/base.py` - Carrier serializers
102+
- `modules/core/karrio/server/providers/views/carriers.py` - Carrier REST views
103+
- `modules/core/karrio/server/providers/admin.py` - Django admin
104+
105+
**Manager Module:**
106+
- `modules/manager/karrio/server/manager/models.py` - Pickup, Tracking, Shipment, etc.
107+
- `modules/manager/karrio/server/manager/serializers/shipment.py` - Shipment serializers
108+
109+
**Graph Module:**
110+
- `modules/graph/karrio/server/graph/schemas/base/types.py` - GraphQL types
111+
- `modules/graph/karrio/server/graph/schemas/base/mutations.py` - GraphQL mutations
112+
- `modules/graph/karrio/server/graph/utils.py` - GraphQL utilities
113+
114+
**Orgs Module (Insiders):**
115+
- `ee/insiders/modules/orgs/karrio/server/orgs/models.py` - Organization model with system_carriers M2M
116+
- `ee/insiders/modules/admin/karrio/server/admin/schemas/` - Admin GraphQL schemas
117+
118+
**Pricing Module:**
119+
- `modules/pricing/karrio/server/pricing/models.py` - Surcharge carrier accounts
120+
121+
**Data Module:**
122+
- `modules/data/karrio/server/data/resources/trackers.py` - Tracker resources
123+
58124
---
59125

60126
## 2. Problem Statement

0 commit comments

Comments
 (0)