status updated
This commit is contained in:
89
models/storeopen.go
Normal file
89
models/storeopen.go
Normal file
@@ -0,0 +1,89 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
/*
|
||||
Is a branch taking orders right now?
|
||||
|
||||
Two things have to be true: the branch exists as far as the platform is
|
||||
concerned, and the shop has not closed itself for the day. They are different
|
||||
questions with different owners — Nearle decommissions a branch, a shopkeeper
|
||||
closes for an afternoon — and this is the only place they are answered
|
||||
together.
|
||||
|
||||
── Reopening is worked out, not scheduled ──────────────────────────────────
|
||||
|
||||
A shop that said "back on Monday" is open on Monday because this function says
|
||||
so, not because a job ran. Nothing has to fire, nothing can be missed, and a
|
||||
server that was down over the weekend still gets it right. The alternative — a
|
||||
nightly task flipping the flag — fails silently exactly once and leaves a shop
|
||||
shut with nobody watching.
|
||||
|
||||
── Why the date means the day it REOPENS ───────────────────────────────────
|
||||
|
||||
"Closed until the 12th" reads, in English, as open on the 12th. So the date
|
||||
names the first day back, and a shop closing for today alone sets tomorrow.
|
||||
The console says "Reopens on" rather than "Closed until" so nobody has to
|
||||
work that out.
|
||||
*/
|
||||
func StoreIsOpen(status string, isOpen bool, closedUntil string, now time.Time) bool {
|
||||
// Decommissioned beats everything. A branch Nearle has switched off does
|
||||
// not come back because a date passed.
|
||||
if !strings.EqualFold(strings.TrimSpace(status), "active") {
|
||||
return false
|
||||
}
|
||||
|
||||
if isOpen {
|
||||
return true
|
||||
}
|
||||
|
||||
// Closed, with a date to come back on.
|
||||
reopen, ok := parseStoreDate(closedUntil)
|
||||
if !ok {
|
||||
// Closed with no end in sight — a power cut nobody can put a date on.
|
||||
// Stays closed until a person says otherwise, which is the safe way
|
||||
// round: a shop wrongly shown open takes orders it cannot fill.
|
||||
return false
|
||||
}
|
||||
|
||||
today := now.Truncate(24 * time.Hour)
|
||||
return !today.Before(reopen.Truncate(24 * time.Hour))
|
||||
}
|
||||
|
||||
/*
|
||||
Why a shopper cannot order, in words fit to show them.
|
||||
|
||||
Empty when the branch is open. Returned straight to the app, so it says what a
|
||||
person needs to know and not what the database holds.
|
||||
*/
|
||||
func StoreClosedReason(status string, isOpen bool, closedUntil string, now time.Time) string {
|
||||
if StoreIsOpen(status, isOpen, closedUntil, now) {
|
||||
return ""
|
||||
}
|
||||
if !strings.EqualFold(strings.TrimSpace(status), "active") {
|
||||
return "This store is not currently available"
|
||||
}
|
||||
if reopen, ok := parseStoreDate(closedUntil); ok {
|
||||
return "This store is closed today and reopens on " + reopen.Format("2 Jan")
|
||||
}
|
||||
return "This store is closed today"
|
||||
}
|
||||
|
||||
// Accepts a bare date or a timestamp, because the column is a DATE but GORM
|
||||
// and the console have both been known to hand over a full RFC3339 string.
|
||||
// Anything unreadable is "no date", never today.
|
||||
func parseStoreDate(value string) (time.Time, bool) {
|
||||
trimmed := strings.TrimSpace(value)
|
||||
if trimmed == "" {
|
||||
return time.Time{}, false
|
||||
}
|
||||
if len(trimmed) >= 10 {
|
||||
if parsed, err := time.Parse("2006-01-02", trimmed[:10]); err == nil {
|
||||
return parsed, true
|
||||
}
|
||||
}
|
||||
return time.Time{}, false
|
||||
}
|
||||
Reference in New Issue
Block a user