The ingest only ever wrote. A bill that reached pos_orders was safe and completely unreachable — no screen in the product could show it, and the only way to see a day's counter takings was to query the database by hand. Three endpoints: a paged bill list, one bill with its lines, and a summary split the three ways somebody actually asks for — by tender for reconciling a drawer, by day for a chart, by till for an outlet running several counters. locationid is required on all of them and is the authorisation boundary, so a caller cannot page through another shop's takings by omitting a parameter. Fetching a bill under the wrong outlet returns 404 even when the reference is a real one. Dates match businessdate rather than arrival, because a till that was offline overnight uploads yesterday's bills this morning and they belong to yesterday. The list is ordered by billedat for the same reason — sorting by arrival would interleave a recovered backlog through today. Unlike the ingest handlers these answer in the usual envelope: they are read by the web app, not by a terminal, and nothing about them is bound to the till's contract. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
38 lines
1.4 KiB
Go
38 lines
1.4 KiB
Go
package routes
|
|
|
|
import (
|
|
"nearle/facade"
|
|
|
|
"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")
|
|
|
|
pos.Post("/orders", f.PosController.IngestOrders)
|
|
pos.Post("/customers", f.PosController.IngestCustomers)
|
|
pos.Get("/catalogue", f.PosController.Catalogue)
|
|
|
|
// 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)
|
|
}
|