delivery slot api creation
This commit is contained in:
111
models/deliveryslot.go
Normal file
111
models/deliveryslot.go
Normal file
@@ -0,0 +1,111 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"slices"
|
||||
"time"
|
||||
)
|
||||
|
||||
/*
|
||||
When a shop delivers.
|
||||
|
||||
A branch offers at most three windows a day — morning, afternoon, evening — and
|
||||
the shopper picks one at checkout. The window is a PREFERENCE, not a promise:
|
||||
every order is accepted, there is no capacity limit, and a slot never fills up.
|
||||
It tells the shop when to group a drop, and it tells the shopper roughly when to
|
||||
expect one.
|
||||
|
||||
── Per branch, not per tenant ──────────────────────────────────────────────
|
||||
|
||||
Timings belong to a shop floor, not a company. A tenant with an outlet in a
|
||||
market and another in an office park will run different hours, and discovering
|
||||
that after the fact would mean migrating live rows. `locationid` is on the table
|
||||
from the start for that reason, and onboarding simply fills it with the primary
|
||||
branch it just created.
|
||||
|
||||
── A branch with no slots is not broken ────────────────────────────────────
|
||||
|
||||
Every tenant trading today has no slots at all, and must keep taking orders.
|
||||
Absence means "order without a slot", exactly as before — never "this shop is
|
||||
closed". The whole rollout rests on that, so nothing here may treat an empty
|
||||
list as an error.
|
||||
*/
|
||||
type DeliverySlots struct {
|
||||
Slotid int `json:"deliveryslotid" gorm:"primaryKey;autoIncrement;column:slotid"`
|
||||
Tenantid int `json:"tenantid" gorm:"column:tenantid;index"`
|
||||
Locationid int `json:"locationid" gorm:"column:locationid;index"`
|
||||
|
||||
// Which of the three this is. Fixed rather than free-form: the app shows
|
||||
// them in a known order and may want an icon per slot, and a shop inventing
|
||||
// a fourth would have nowhere to appear.
|
||||
Slotkey string `json:"slotkey" gorm:"column:slotkey"`
|
||||
|
||||
// What the shopper reads. Separate from `slotkey` so a shop can say
|
||||
// "Before work" without breaking the app's ordering.
|
||||
Name string `json:"name" gorm:"column:name"`
|
||||
|
||||
// "HH:MM", 24-hour, in the shop's local time.
|
||||
//
|
||||
// Stored as text, not as a timestamp, because this is a time of DAY that
|
||||
// recurs — it has no date until an order attaches one. A timestamp column
|
||||
// would invite a timezone conversion on every read, which is the one thing
|
||||
// this must not do: the shopkeeper typed 08:00 meaning eight in the morning
|
||||
// where they are standing.
|
||||
Starttime string `json:"starttime" gorm:"column:starttime"`
|
||||
|
||||
// Also the CUT-OFF. There is deliberately no separate cutoff column: a slot
|
||||
// accepts orders right up to the moment it ends, and then stops being
|
||||
// offered. Morning 08:00–10:00 takes an order at 09:59 and not at 10:01.
|
||||
Endtime string `json:"endtime" gorm:"column:endtime"`
|
||||
|
||||
// "active" or "inactive". A shop that stops doing evenings turns the slot
|
||||
// off rather than deleting it, so orders already placed against it still
|
||||
// resolve to something with a name.
|
||||
Status string `json:"status" gorm:"column:status"`
|
||||
|
||||
Created time.Time `json:"created" gorm:"column:created;autoCreateTime"`
|
||||
Updated time.Time `json:"updated" gorm:"column:updated;autoUpdateTime"`
|
||||
}
|
||||
|
||||
func (DeliverySlots) TableName() string {
|
||||
return "deliveryslots"
|
||||
}
|
||||
|
||||
// The three keys, in the order a shopper reads them.
|
||||
const (
|
||||
SlotMorning = "morning"
|
||||
SlotAfternoon = "afternoon"
|
||||
SlotEvening = "evening"
|
||||
)
|
||||
|
||||
// SlotKeys is the whole set, in display order. Used to validate input and to
|
||||
// seed a new branch.
|
||||
var SlotKeys = []string{SlotMorning, SlotAfternoon, SlotEvening}
|
||||
|
||||
// IsSlotKey reports whether a key is one of the three.
|
||||
func IsSlotKey(key string) bool {
|
||||
return slices.Contains(SlotKeys, key)
|
||||
}
|
||||
|
||||
/*
|
||||
A slot offered to a shopper, with the day it falls on.
|
||||
|
||||
`DeliverySlots` describes a window that recurs; this is one concrete occurrence
|
||||
of it. The app needs the date because "evening" alone cannot distinguish tonight
|
||||
from tomorrow night, and once today's last window closes the next thing on offer
|
||||
is tomorrow morning.
|
||||
|
||||
The app does NO time arithmetic. It renders what this list contains, and the
|
||||
list already excludes anything that has closed.
|
||||
*/
|
||||
type AvailableDeliverySlot struct {
|
||||
Slotid int `json:"deliveryslotid"`
|
||||
Slotkey string `json:"slotkey"`
|
||||
Name string `json:"name"`
|
||||
Starttime string `json:"starttime"`
|
||||
Endtime string `json:"endtime"`
|
||||
// "YYYY-MM-DD", the day this window falls on.
|
||||
Slotdate string `json:"slotdate"`
|
||||
// True when `Slotdate` is not today. Saves the app comparing dates to
|
||||
// decide whether to write "Tomorrow" beside the name.
|
||||
IsTomorrow bool `json:"istomorrow"`
|
||||
}
|
||||
@@ -233,19 +233,30 @@ type Ordermonths struct {
|
||||
}
|
||||
|
||||
type Orders struct {
|
||||
Orderheaderid int `json:"orderheaderid" gorm:"Primary_Key"`
|
||||
Tenantid int `json:"tenantid"`
|
||||
Locationid int `json:"locationid"`
|
||||
Applocationid int `json:"applocationid"`
|
||||
Moduleid int `json:"moduleid"`
|
||||
Partnerid int `json:"partnerid"`
|
||||
Configid int `json:"configid"`
|
||||
Categoryid int `json:"categoryid"`
|
||||
Subcategoryid int `json:"subcategoryid"`
|
||||
Orderid string `json:"orderid"`
|
||||
Orderdate string `json:"orderdate,omitempty"`
|
||||
Deliverytime string `json:"deliverytime"`
|
||||
Deliverytype string `json:"deliverytype"`
|
||||
Orderheaderid int `json:"orderheaderid" gorm:"Primary_Key"`
|
||||
Tenantid int `json:"tenantid"`
|
||||
Locationid int `json:"locationid"`
|
||||
Applocationid int `json:"applocationid"`
|
||||
Moduleid int `json:"moduleid"`
|
||||
Partnerid int `json:"partnerid"`
|
||||
Configid int `json:"configid"`
|
||||
Categoryid int `json:"categoryid"`
|
||||
Subcategoryid int `json:"subcategoryid"`
|
||||
Orderid string `json:"orderid"`
|
||||
Orderdate string `json:"orderdate,omitempty"`
|
||||
Deliverytime string `json:"deliverytime"`
|
||||
Deliverytype string `json:"deliverytype"`
|
||||
// The window the shopper chose, and the day it falls on.
|
||||
//
|
||||
// Both stay zero for every order placed without one — which is every order
|
||||
// before this shipped, and every order from a branch that has set no
|
||||
// windows. Nothing downstream may require them.
|
||||
//
|
||||
// Distinct from `Deliverytime` above, which is a TIMESTAMP of what happened
|
||||
// and is defaulted to now() a few lines into CreateOrderv3. These two say
|
||||
// what was asked for; that one says what occurred.
|
||||
Deliveryslotid int `json:"deliveryslotid" gorm:"column:deliveryslotid"`
|
||||
Deliveryslotdate string `json:"deliveryslotdate" gorm:"column:deliveryslotdate"`
|
||||
Orderstatus string `json:"orderstatus"`
|
||||
Pending string `json:"pending"`
|
||||
Processing string `json:"processing"`
|
||||
|
||||
Reference in New Issue
Block a user