Shipping Device DB Reference Migration Plan
This document continues from the Shipping Device DB Reference Plan into the SQL migration design level. The focus is the order of migration files, the contents of each file, the primary constraints, and the design decisions that must be preserved before final implementation under kesles_reference/reference_database/sql/ (the standalone reference repo, db_reference).
Status (2026-06-23): shipped. Migrations
015–022(plus themerchantschema, seeds, and later coverage/rate expansion migrations) are applied inkesles_reference/reference_database/sql/.
Companion documents:
- Shipping Device DB Reference Plan
- Shipping Device Seed Checklist (moved →
merchant_docs/docs/development/shipping-device-seed-checklist.md)
Goal
The goal of this migration plan is to:
- translate the device shipping policy into a reference table structure ready to implement
- keep naming and schema patterns consistent with the
merchantschema indb_reference - ensure that rate, coverage, and fallback data can be managed without hardcoding
General Migration Principles
- All new tables live in the
merchantschema. - Table names follow the
merchant.ref_*pattern. - Migrations are additive and backward-compatible.
- Initial seed data is separated from the schema migration as much as possible.
- Constraints are used to block invalid data from the start.
Recommended File Numbering
After the latest current file 014_create_ref_mcc_code.sql, the recommended file order is:
015_create_ref_shipping_partner.sql016_create_ref_shipping_service.sql017_create_ref_shipping_origin.sql018_create_ref_shipping_destination_region_group.sql019_create_ref_shipping_partner_service.sql020_create_ref_shipping_partner_coverage.sql021_create_ref_shipping_rate.sql022_create_ref_shipping_fallback_rule.sql
If we want to separate the basic reference seeds, the seed files can start after that, for example:
023_seed_ref_shipping_service.sql024_seed_ref_shipping_partner.sql
But if this repo has historically mixed create and seed in a single file for certain references, the final approach can be adjusted. For the shipping use case, I still recommend keeping schema and seed separate.
015 Create Shipping Partner
Table name
merchant.ref_shipping_partner
Function
Stores the master list of courier partners allowed by the system.
Core columns
shipping_partner_ididentity primary keypartner_codevarchar uniquepartner_namevarcharpriority_ranksmallintis_primarybooleansupports_regularbooleansupports_cargobooleanis_activebooleannotestextcreated_atupdated_at
Primary constraints
partner_codeuniquepriority_rank > 0- if
is_primary = true, only one active primary partner is allowed at a time
Implementation notes:
- the uniqueness for a single active primary can be handled with a partial unique index
priority_rankis still stored even though there is a fallback table, because it is useful for default ordering
016 Create Shipping Service
Table name
merchant.ref_shipping_service
Function
Stores the internal service categories the system recognizes.
Initial values
regularcargo
Core columns
shipping_service_ididentity primary keyservice_codevarchar uniqueservice_namevarcharsort_ordersmallintis_activebooleancreated_atupdated_at
Primary constraints
service_codeuniqueservice_coderestricted to lowercase snake_case or lowercase plain code
017 Create Shipping Origin
Table name
merchant.ref_shipping_origin
Function
Stores shipping origin nodes. The initial phase still uses Makassar, but this model is prepared for possible multi-origin support later.
Core columns
shipping_origin_ididentity primary keyorigin_codevarchar uniqueorigin_namevarcharcountry_codeprovince_codeor a foreign key reference to the region table when availablecity_codeor a foreign key reference to the region table when availableis_defaultbooleanis_activebooleancreated_atupdated_at
Primary constraints
origin_codeunique- at most one active default origin
018 Create Shipping Destination Region Group
Table name
merchant.ref_shipping_destination_region_group
Function
Stores destination groupings for the shipping policy.
Initial values
SULAWESINON_SULAWESI
Core columns
shipping_destination_region_group_ididentity primary keydestination_city_codeor FK to the city referenceregion_group_coderegion_group_nameis_activecreated_atupdated_at
Primary constraints
- a single destination may only have one active
region_group_code region_group_codeis restricted by an initial enum check:SULAWESI,NON_SULAWESI
Notes:
- the choice between
destination_city_codeand a final FK depends on the source-of-truth region table already available indb_reference
019 Create Shipping Partner Service
Table name
merchant.ref_shipping_partner_service
Function
Stores the mapping between an internal service and the partner's service code.
Core columns
shipping_partner_service_ididentity primary keyshipping_partner_idFK toref_shipping_partnershipping_service_idFK toref_shipping_servicepartner_service_codepartner_service_nameis_activecreated_atupdated_at
Primary constraints
- the combination
shipping_partner_id + partner_service_codeis unique - the combination
shipping_partner_id + shipping_service_id + partner_service_codeis unique if we want to be more explicit
020 Create Shipping Partner Coverage
Table name
merchant.ref_shipping_partner_coverage
Function
Determines whether a given partner serves a given destination for a given service from a given origin.
Core columns
shipping_partner_coverage_ididentity primary keyshipping_partner_idFKshipping_service_idFKshipping_origin_idFKdestination_city_codeor final FKregion_group_codeis_availablesla_min_dayssla_max_dayseffective_fromeffective_tois_activecoverage_notescreated_atupdated_at
Primary constraints
sla_min_days >= 0sla_max_days >= sla_min_days- active periods may not overlap for the same combination of partner, service, origin, and destination
Notes:
- active overlap usually requires an exclusion constraint or must be enforced at the application layer
- to keep things simple at the start, use a unique combination on active data + disciplined update process
021 Create Shipping Rate
Table name
merchant.ref_shipping_rate
Function
Stores the master shipping rate for a combination of partner, service, origin, and destination.
Core columns
shipping_rate_ididentity primary keyshipping_partner_idFKshipping_service_idFKshipping_origin_idFKdestination_city_codeor final FKcurrencyprice_amountprice_unitmin_billable_weight_kgweight_increment_kgrounding_rule_codesla_min_dayssla_max_dayseffective_fromeffective_tois_activerate_sourcerate_notescreated_atupdated_at
Primary constraints
price_amount >= 0min_billable_weight_kg > 0weight_increment_kg > 0sla_max_days >= sla_min_daysprice_unitis restricted to initial values, e.g.per_kg,flat_per_shipmentrounding_rule_codeis restricted to initial values, e.g.ceil_kg,floor_kg,nearest_kg
Design notes
For the initial phase, the safest design:
- all rates use
currency = 'IDR' - the majority of rates use
price_unit = per_kg - weight rounding uses
ceil_kg
This model is still flexible enough without being overly complex.