updates on the ai agents and time series prediction and updates on the api to
This commit is contained in:
@@ -14,11 +14,59 @@ type Tenant struct {
|
||||
// parcel; not for a food order, where it just slows every drop down.
|
||||
// Defaults off: turning it on platform-wide would block deliveries for
|
||||
// clients whose customer app has no way to show the code yet.
|
||||
Requiredeliveryotp bool `json:"requiredeliveryotp" gorm:"column:requiredeliveryotp;default:false"`
|
||||
Requiredeliveryotp bool `json:"requiredeliveryotp" gorm:"column:requiredeliveryotp;default:false"`
|
||||
// Deliverycategory is WHAT this client ships, from the same vocabulary
|
||||
// pricing uses (constants.DeliveryCategories) — a tenant whose category is
|
||||
// not a pricing category cannot be priced, so the two are one list.
|
||||
//
|
||||
// It decides whether reverse logistics applies: a returned meal is waste,
|
||||
// not inventory, so Food clients get no RTO path. See
|
||||
// constants.ReverseLogisticsAllowed for the reasoning.
|
||||
//
|
||||
// Empty on every tenant onboarded before this field existed, and empty
|
||||
// must keep behaving as it always did — which is why
|
||||
// ReverseLogisticsAllowed treats an unknown category as returnable rather
|
||||
// than defaulting the new flag to off.
|
||||
Deliverycategory string `json:"deliverycategory" gorm:"column:deliverycategory;size:32"`
|
||||
// Reverselogisticsenabled is the OPERATIONAL consequence, stored rather
|
||||
// than derived on every read.
|
||||
//
|
||||
// Two reasons it is its own column. First, an operator may need to turn
|
||||
// returns off for a non-Food client (a clearance line that is final sale)
|
||||
// or on for a Food client (a caterer who takes back equipment), and a
|
||||
// derived value cannot be overridden. Second, deriving it would mean that
|
||||
// editing a client's category silently changes whether live parcels can be
|
||||
// returned — a stored flag makes that an explicit second decision.
|
||||
// A POINTER, deliberately, and this is load-bearing.
|
||||
//
|
||||
// GORM omits a zero-value field from an INSERT when the tag declares a
|
||||
// default — so a plain `bool` set to false was silently dropped and the
|
||||
// column default (true) applied, creating Food clients with reverse
|
||||
// logistics ENABLED: the exact case this feature exists to prevent,
|
||||
// failing silently. A test caught it.
|
||||
//
|
||||
// Dropping the default instead is worse: ADD COLUMN ... NOT NULL with no
|
||||
// default fails outright on a populated tenants table.
|
||||
//
|
||||
// A pointer gives both. nil means "not stated" and the column default
|
||||
// (true) applies — which is what every row predating this field wants. A
|
||||
// non-nil false is written as false, because GORM never omits a non-nil
|
||||
// pointer. Read it through ReturnsEnabled(), never directly.
|
||||
Reverselogisticsenabled *bool `json:"reverselogisticsenabled" gorm:"column:reverselogisticsenabled;default:true"`
|
||||
Createdat time.Time `json:"createdat" gorm:"column:createdat;default:CURRENT_TIMESTAMP"`
|
||||
Updatedat time.Time `json:"updatedat" gorm:"column:updatedat;default:CURRENT_TIMESTAMP"`
|
||||
}
|
||||
|
||||
// ReturnsEnabled is the one way to read Reverselogisticsenabled.
|
||||
//
|
||||
// nil means the client predates the field, and those clients were all using
|
||||
// returns — so nil is TRUE. Reading the pointer directly invites a nil deref
|
||||
// or, worse, treating "not stated" as "disabled" and silently withdrawing a
|
||||
// capability a client is already using.
|
||||
func (t Tenant) ReturnsEnabled() bool {
|
||||
return t.Reverselogisticsenabled == nil || *t.Reverselogisticsenabled
|
||||
}
|
||||
|
||||
func (Tenant) TableName() string {
|
||||
return "tenants"
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user