status updated
This commit is contained in:
@@ -12,10 +12,17 @@ import (
|
||||
|
||||
type DeliverySlotController struct {
|
||||
service services.DeliverySlotService
|
||||
// Asked whether the shop is trading at all. Held here rather than inside
|
||||
// the slot service, which answers one question — is this window still
|
||||
// running — and should not also have to know about shop closures.
|
||||
tenants services.TenantService
|
||||
}
|
||||
|
||||
func NewDeliverySlotController(service services.DeliverySlotService) *DeliverySlotController {
|
||||
return &DeliverySlotController{service: service}
|
||||
func NewDeliverySlotController(
|
||||
service services.DeliverySlotService,
|
||||
tenants services.TenantService,
|
||||
) *DeliverySlotController {
|
||||
return &DeliverySlotController{service: service, tenants: tenants}
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -128,6 +135,28 @@ func (ctl *DeliverySlotController) AvailableDeliverySlots(c *fiber.Ctx) error {
|
||||
})
|
||||
}
|
||||
|
||||
/*
|
||||
A shut shop offers nothing.
|
||||
|
||||
Without this, a branch closed for the day still hands the app tomorrow
|
||||
morning — and the shopper picks it, reaches checkout, and is refused by
|
||||
the closed-shop guard in order creation with no warning anything was
|
||||
wrong. The empty list is already the app's "no windows here" path, so
|
||||
this needs nothing new on their side.
|
||||
|
||||
The reason rides along so the app can say WHY rather than just showing
|
||||
nothing, on an endpoint it is already calling.
|
||||
*/
|
||||
if reason := ctl.tenants.StoreClosedReason(tenantID, locationID); reason != "" {
|
||||
return c.Status(http.StatusOK).JSON(fiber.Map{
|
||||
"code": http.StatusOK,
|
||||
"message": "Success",
|
||||
"status": true,
|
||||
"details": []models.AvailableDeliverySlot{},
|
||||
"closedreason": reason,
|
||||
})
|
||||
}
|
||||
|
||||
slots, err := ctl.service.Available(tenantID, locationID)
|
||||
if err != nil {
|
||||
return c.Status(http.StatusInternalServerError).JSON(fiber.Map{
|
||||
|
||||
@@ -20,15 +20,21 @@ type OrderController struct {
|
||||
// than reimplemented, so the app's list and this check can never disagree
|
||||
// about where a window ends.
|
||||
deliverySlotService services.DeliverySlotService
|
||||
// Asked whether the shop is trading. Same reasoning: the customer-facing
|
||||
// store list and this check run the same rule, so a shop shown as open is
|
||||
// never refused here.
|
||||
tenantService services.TenantService
|
||||
}
|
||||
|
||||
func NewOrderController(
|
||||
orderService services.OrderService,
|
||||
deliverySlotService services.DeliverySlotService,
|
||||
tenantService services.TenantService,
|
||||
) *OrderController {
|
||||
return &OrderController{
|
||||
orderService: orderService,
|
||||
deliverySlotService: deliverySlotService,
|
||||
tenantService: tenantService,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -358,6 +364,24 @@ func (ctl *OrderController) CreateOrderv3(c *fiber.Ctx) error {
|
||||
data.Deliverytime = time.Now().Format("2006-01-02 15:04:05")
|
||||
}
|
||||
|
||||
/*
|
||||
Is the shop even trading?
|
||||
|
||||
Checked HERE and not only in the app, because /v1/mob/* carries no
|
||||
session: anything arriving is a claim. The ordinary case is innocent and
|
||||
still has to be caught — a shopper with the app open when the shopkeeper
|
||||
closes, or a stale screen from this morning.
|
||||
|
||||
409 with the shop's own reason, written to be shown as-is.
|
||||
*/
|
||||
if reason := ctl.tenantService.StoreClosedReason(data.Tenantid, data.Locationid); reason != "" {
|
||||
return c.Status(http.StatusConflict).JSON(fiber.Map{
|
||||
"code": http.StatusConflict,
|
||||
"message": reason,
|
||||
"status": false,
|
||||
})
|
||||
}
|
||||
|
||||
// The chosen delivery window, re-decided here.
|
||||
//
|
||||
// The app sends back what /v1/mob/deliveryslots/available handed it, but
|
||||
|
||||
@@ -871,3 +871,53 @@ func (ctl *TenantController) ResendInvite(c *fiber.Ctx) error {
|
||||
"code": http.StatusOK, "status": true, "message": "Invitation sent.",
|
||||
})
|
||||
}
|
||||
|
||||
/*
|
||||
PUT /v1/web/tenants/storeopen
|
||||
|
||||
Open or close a branch for the day.
|
||||
|
||||
── Why this is on the guarded group ────────────────────────────────────────
|
||||
|
||||
Closing a shop stops it taking money. On /v1/mob/* — which carries no session
|
||||
at all — anyone who could guess a locationid could shut any shop on the
|
||||
platform. WebAuth checks the tenant scope, so a business can only reach its
|
||||
own branches.
|
||||
|
||||
A business objection — a date in the past, a branch that is not yours — is 409
|
||||
and not 500: the request was well formed, and the message is written to be
|
||||
shown to the person who typed it.
|
||||
*/
|
||||
func (ctl *TenantController) SetStoreOpen(c *fiber.Ctx) error {
|
||||
var req struct {
|
||||
Tenantid int `json:"tenantid"`
|
||||
Locationid int `json:"locationid"`
|
||||
// A POINTER, so "not sent" and "sent as false" stay different answers.
|
||||
// A plain bool would read a missing field as "close this shop".
|
||||
Isopen *bool `json:"isopen"`
|
||||
Closeduntil string `json:"closeduntil"`
|
||||
}
|
||||
|
||||
if err := c.BodyParser(&req); err != nil {
|
||||
return c.Status(http.StatusBadRequest).JSON(fiber.Map{
|
||||
"code": http.StatusBadRequest, "message": "Invalid request body", "status": false,
|
||||
})
|
||||
}
|
||||
if req.Isopen == nil {
|
||||
return c.Status(http.StatusBadRequest).JSON(fiber.Map{
|
||||
"code": http.StatusBadRequest, "message": "isopen is required", "status": false,
|
||||
})
|
||||
}
|
||||
|
||||
if err := ctl.tenantService.SetStoreOpen(
|
||||
req.Tenantid, req.Locationid, *req.Isopen, req.Closeduntil,
|
||||
); err != nil {
|
||||
return c.Status(http.StatusConflict).JSON(fiber.Map{
|
||||
"code": http.StatusConflict, "message": err.Error(), "status": false,
|
||||
})
|
||||
}
|
||||
|
||||
return c.Status(http.StatusOK).JSON(fiber.Map{
|
||||
"code": http.StatusOK, "message": "Successfully Updated", "status": true,
|
||||
})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user