backend requirements onthe xustomer app
This commit is contained in:
@@ -47,6 +47,19 @@ func Migrate(db *gorm.DB) error {
|
||||
&models.MilerDutyLog{},
|
||||
&models.MilerBreakLog{},
|
||||
&models.MilerSupportTicket{},
|
||||
|
||||
// Customer app (doormile_cx). All additive: new tables plus new
|
||||
// nullable/zero-default columns on pickupbookings, so an existing row
|
||||
// and every console-created booking stay valid with no backfill.
|
||||
&models.ServiceableState{},
|
||||
&models.ServiceableDistrict{},
|
||||
&models.PickupSlotTemplate{},
|
||||
&models.CustomerBookingLimit{},
|
||||
&models.BookingDestination{},
|
||||
&models.BookingParcelPhoto{},
|
||||
&models.BookingStageEvent{},
|
||||
&models.CustomerRefreshToken{},
|
||||
&models.CustomerDevice{},
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
@@ -94,5 +107,47 @@ func Migrate(db *gorm.DB) error {
|
||||
utils.Info("✅ consignments_status_check constraint includes Collected_By_Miler")
|
||||
}
|
||||
|
||||
// Human-facing identifiers for the customer app: DM-###### for a pickup
|
||||
// booking, DMX######## for an order. Sequence-backed rather than random,
|
||||
// because both columns are UNIQUE and a random short id collides long
|
||||
// before a short id runs out — a collision here is a failed booking at the
|
||||
// moment of payment, not a retry.
|
||||
//
|
||||
// No CYCLE and no MAXVALUE on purpose: past 999999 the format simply grows
|
||||
// a digit (DM-1000000) instead of wrapping onto an id that already exists.
|
||||
// Existing rows keep their old DM-BK-/DM-TRK- strings; nothing parses
|
||||
// either format, so the two coexist safely.
|
||||
if res := db.Exec(`CREATE SEQUENCE IF NOT EXISTS cx_booking_reference_seq START 100000 INCREMENT 1`); res.Error != nil {
|
||||
utils.Error("❌ Failed to create cx_booking_reference_seq", "error", res.Error)
|
||||
} else {
|
||||
utils.Info("✅ cx_booking_reference_seq ready")
|
||||
}
|
||||
if res := db.Exec(`CREATE SEQUENCE IF NOT EXISTS cx_tracking_seq START 10000000 INCREMENT 1`); res.Error != nil {
|
||||
utils.Error("❌ Failed to create cx_tracking_seq", "error", res.Error)
|
||||
} else {
|
||||
utils.Info("✅ cx_tracking_seq ready")
|
||||
}
|
||||
|
||||
// One booking must not hold two destinations at the same position: the
|
||||
// customer addresses a destination by index in
|
||||
// PATCH /customer/bookings/{ref}/destinations/{index}, so a duplicate seq
|
||||
// makes that route ambiguous and would let an edit land on the wrong
|
||||
// address.
|
||||
if res := db.Exec(`CREATE UNIQUE INDEX IF NOT EXISTS idx_bookingdestinations_booking_seq
|
||||
ON bookingdestinations (bookingid, seq)`); res.Error != nil {
|
||||
utils.Error("❌ Failed to create bookingdestinations (bookingid, seq) unique index", "error", res.Error)
|
||||
} else {
|
||||
utils.Info("✅ bookingdestinations (bookingid, seq) unique index ready")
|
||||
}
|
||||
|
||||
// The timeline is read as "every event for this booking, oldest first" on
|
||||
// every tracking poll, which is the hottest customer read there is.
|
||||
if res := db.Exec(`CREATE INDEX IF NOT EXISTS idx_bookingstageevents_booking_time
|
||||
ON bookingstageevents (bookingid, occurredat)`); res.Error != nil {
|
||||
utils.Error("❌ Failed to create bookingstageevents (bookingid, occurredat) index", "error", res.Error)
|
||||
} else {
|
||||
utils.Info("✅ bookingstageevents (bookingid, occurredat) index ready")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user