package routes import ( "nearle/facade" "nearle/middleware" "github.com/gofiber/fiber/v2" ) // Routes for the Nearle POS terminal. // // The paths are fixed by the till, which appends `/orders`, `/customers` and // `/catalogue` to whatever base URL a shop enters in Settings. Set that base to // this group — `https://your-host/live/api/v1/pos` — and the three line up. // // Kept in their own group rather than folded into the order routes because a // terminal authenticates as a device, not as a signed-in user, and because // these answer with a bare ack rather than the web app's response envelope. func RegisterPosRoutes(api fiber.Router, f *facade.Facade) { pos := api.Group("/v1/pos") // Sign-in, and the only route on this group that runs before the guard — // it is where a session comes from. A till posts the same `app_users` // credentials the web console takes, and gets back a token plus the outlet // that account is entitled to. The store id it will bill under is decided // here, from the user's record, instead of being typed into Settings and // taken on trust. pos.Post("/login", f.PosController.Login) // Everything past this point carries the session. // // The guard verifies the token and refuses a request naming an outlet the // token's tenant does not own. Until `POS_AUTH_REQUIRED=true` is set it // lets an unauthenticated request through, so the terminals already // trading do not stop the day this deploys — see middleware.PosAuth. pos.Use(middleware.PosAuth(f.PosService())) pos.Get("/session", f.PosController.Session) // Who may ring a bill here. Deliberately takes no location parameter — the // answer carries PINs, so the outlet comes from the caller's own token. pos.Get("/staff", f.PosController.Staff) // Signing on by PIN, once a supervisor has opened the terminal with a real // password. Sits behind the guard on purpose — see PinLogin. pos.Post("/login/pin", f.PosController.PinLogin) // The shop's own counter staff. A supervisor creates their cashiers; the // outlet is always the caller's own, read from their token. pos.Get("/users", f.PosController.ListPosUsers) pos.Post("/users", f.PosController.CreatePosUser) pos.Put("/users", f.PosController.UpdatePosUser) pos.Delete("/users", f.PosController.DeletePosUser) pos.Post("/orders", f.PosController.IngestOrders) pos.Post("/customers", f.PosController.IngestCustomers) pos.Get("/catalogue", f.PosController.Catalogue) // The 30-second heartbeat, for tills on the HTTP route. The broker carries // the same payload for tills on MQTT; both land in the same Redis record, // so the fleet board cannot tell them apart and does not need to. pos.Post("/health", f.PosController.IngestHealth) // Counter sales, read back out. The ingest above only ever writes; without // these a committed bill is unreachable from every screen in the product. pos.Get("/sales", f.PosController.GetSales) pos.Get("/sales/detail", f.PosController.GetSaleDetail) pos.Get("/sales/summary", f.PosController.GetSalesSummary) // Terminal presence, read from Redis. What the rider app's POS board and a // support call both hit — the tills themselves publish health over the // broker rather than posting it here. pos.Get("/health/terminal", f.PosController.TerminalHealth) pos.Get("/health/location", f.PosController.LocationHealth) }