Scan-to-order: label from the customer's camera to "buy it here"
POST /v1/mob/scan/lookup label + customer → catalogue match, sizes, and
every registered store that sells it with live
stock, in-stock first / nearest first, one
recommended
POST /v1/mob/scan/confirm chosen store + size + qty → re-read the ledger;
ok, or the next-nearest store with enough of the
same product
GET /v1/mob/scan/stores registered stores nearest first
Recognition is pgvector cosine search over every brand_* table (each
with its own index, merged) plus a word match that settles near-ties
and works alone when no model is configured. The embedder is chosen by
EMBEDDING_PROVIDER (OpenAI-compatible or Gemini) and must be the model
that indexed the catalogue: verified 2026-09-15 as all-MiniLM-L6-v2 over
search_query, served by the cluster's Ollama as `all-minilm`; the first
search refuses a width mismatch by name.
Customer, stores and catalogue are read concurrently under a 5 s cap; a
slow model degrades to a text answer. Vectors and ranked hits are cached
in Redis and in-process; live stock never is. Availability uses the same
rules as the customer catalogue (approve, publishedat, ledger balance,
outlet price else retail). No stock reservation: confirm re-reads.
scratch/cataloguedims reports the catalogue's embedding width and fill.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -21,4 +21,5 @@ func RegisterRoutes(app *fiber.App, f *facade.Facade) {
|
||||
RegisterCatalogueRoutes(api, f)
|
||||
RegisterPosRoutes(api, f)
|
||||
RegisterUploadRoutes(api, f)
|
||||
RegisterScanRoutes(api, f)
|
||||
}
|
||||
|
||||
17
routes/scanroutes.go
Normal file
17
routes/scanroutes.go
Normal file
@@ -0,0 +1,17 @@
|
||||
package routes
|
||||
|
||||
import (
|
||||
"nearle/facade"
|
||||
|
||||
"github.com/gofiber/fiber/v2"
|
||||
)
|
||||
|
||||
// Scan-to-order, customer app only. See controllers/scanController.go for
|
||||
// the three calls and services/scanService.go for the pipeline behind them.
|
||||
func RegisterScanRoutes(api fiber.Router, f *facade.Facade) {
|
||||
scan := api.Group("/v1/mob/scan")
|
||||
|
||||
scan.Post("/lookup", f.ScanController.Lookup)
|
||||
scan.Post("/confirm", f.ScanController.Confirm)
|
||||
scan.Get("/stores", f.ScanController.Stores)
|
||||
}
|
||||
Reference in New Issue
Block a user