A till holds every bill in its own SQLite database and keeps it for seven days after we acknowledge it, marking one synced only when its id comes back in an ack. Everything here follows from that. Silence is not acceptance, so a failing ingest publishes nothing at all and the terminal simply sends again. A duplicate is a success, because at-least-once delivery means a lost ack legitimately re-delivers bills we already hold, and calling those failures would strand a day of takings on the till. Deduplication is a unique index on the terminal's UUID plus an advisory lock held for the transaction. Bills land in pos_orders / pos_order_items rather than orders: a counter bill carries a cashier, a terminal, a rounding adjustment, promos, loyalty movement and a payment split that orders has nowhere to put, and forcing one into the other loses whatever does not fit. Stock is *not* split — a counter sale writes the same productstocks rows an app order does, through helpers extracted from createOrderTx so the rule that prevents overselling has one implementation rather than two. GetRevenueSummary and GetSalesSummary were extended to union the new table in; any new report has to remember the same. Terminal health goes to Redis under a 90-second TTL, sharing the instance the express backend uses. A heartbeat is a fact with an expiry date: a till that loses power stops refreshing and ages off the board by itself, where a Postgres row would need ~288k writes a day and a reaper. Proven end to end against the live estate before commit: a bill over HTTP and one over the real Mosquitto broker, the same bill three times producing one row and one stock movement, and a heartbeat arriving on the health endpoint. All probe data was removed afterwards. Four things that only surfaced against real data. An unset jsonb column failed the very first bill. Product SKUs are unusable as barcodes — 6,245 products share 93 SKUs and "1" covers 5,794 of them — against the till's unique index, so barcodes fall back to the product id. A taxpercent of -1 exists and would have put negative GST in a filed slab. And a product with id 0 exists, which can never be billed and is now skipped. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
109 lines
4.9 KiB
Modula-2
109 lines
4.9 KiB
Modula-2
module nearle
|
|
|
|
go 1.24
|
|
|
|
require (
|
|
firebase.google.com/go v3.13.0+incompatible
|
|
github.com/aws/aws-sdk-go-v2 v1.42.1
|
|
github.com/aws/aws-sdk-go-v2/config v1.32.30
|
|
github.com/aws/aws-sdk-go-v2/credentials v1.19.29
|
|
github.com/aws/aws-sdk-go-v2/service/s3 v1.105.1
|
|
github.com/eclipse/paho.mqtt.golang v1.5.0
|
|
github.com/gofiber/fiber v1.14.6
|
|
github.com/joho/godotenv v1.5.1
|
|
github.com/redis/go-redis/v9 v9.18.0
|
|
golang.org/x/oauth2 v0.12.0
|
|
google.golang.org/api v0.143.0
|
|
gorm.io/driver/postgres v1.6.0
|
|
gorm.io/gorm v1.25.10
|
|
)
|
|
|
|
require (
|
|
cloud.google.com/go v0.110.7 // indirect
|
|
cloud.google.com/go/compute v1.23.0 // indirect
|
|
cloud.google.com/go/compute/metadata v0.2.3 // indirect
|
|
cloud.google.com/go/firestore v1.13.0 // indirect
|
|
cloud.google.com/go/iam v1.1.1 // indirect
|
|
cloud.google.com/go/longrunning v0.5.1 // indirect
|
|
cloud.google.com/go/storage v1.30.1 // indirect
|
|
github.com/andybalholm/brotli v1.0.6 // indirect
|
|
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.14 // indirect
|
|
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.30 // indirect
|
|
github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.30 // indirect
|
|
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.30 // indirect
|
|
github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.31 // indirect
|
|
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.13 // indirect
|
|
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.9.23 // indirect
|
|
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.30 // indirect
|
|
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.31 // indirect
|
|
github.com/aws/aws-sdk-go-v2/service/signin v1.4.1 // indirect
|
|
github.com/aws/aws-sdk-go-v2/service/sso v1.32.1 // indirect
|
|
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.37.1 // indirect
|
|
github.com/aws/aws-sdk-go-v2/service/sts v1.44.1 // indirect
|
|
github.com/aws/smithy-go v1.27.3 // indirect
|
|
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
|
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
|
|
github.com/fsnotify/fsnotify v1.7.0 // indirect
|
|
github.com/gofiber/utils v0.0.10 // indirect
|
|
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
|
|
github.com/golang/protobuf v1.5.3 // indirect
|
|
github.com/google/go-cmp v0.6.0 // indirect
|
|
github.com/google/s2a-go v0.1.7 // indirect
|
|
github.com/google/uuid v1.4.0 // indirect
|
|
github.com/googleapis/enterprise-certificate-proxy v0.3.1 // indirect
|
|
github.com/googleapis/gax-go/v2 v2.12.0 // indirect
|
|
github.com/gorilla/schema v1.1.0 // indirect
|
|
github.com/gorilla/websocket v1.5.3 // indirect
|
|
github.com/hashicorp/hcl v1.0.0 // indirect
|
|
github.com/jackc/pgpassfile v1.0.0 // indirect
|
|
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // indirect
|
|
github.com/jackc/pgx/v5 v5.6.0 // indirect
|
|
github.com/jackc/puddle/v2 v2.2.2 // indirect
|
|
github.com/jinzhu/inflection v1.0.0 // indirect
|
|
github.com/jinzhu/now v1.1.5 // indirect
|
|
github.com/klauspost/compress v1.19.0 // indirect
|
|
github.com/magiconair/properties v1.8.7 // indirect
|
|
github.com/mattn/go-colorable v0.1.13 // indirect
|
|
github.com/mattn/go-isatty v0.0.20 // indirect
|
|
github.com/mattn/go-runewidth v0.0.15 // indirect
|
|
github.com/mitchellh/mapstructure v1.5.0 // indirect
|
|
github.com/rivo/uniseg v0.4.4 // indirect
|
|
github.com/rogpeppe/go-internal v1.11.0 // indirect
|
|
github.com/sagikazarmark/locafero v0.3.0 // indirect
|
|
github.com/sagikazarmark/slog-shim v0.1.0 // indirect
|
|
github.com/sourcegraph/conc v0.3.0 // indirect
|
|
github.com/spf13/afero v1.10.0 // indirect
|
|
github.com/spf13/cast v1.5.1 // indirect
|
|
github.com/spf13/pflag v1.0.5 // indirect
|
|
github.com/subosito/gotenv v1.6.0 // indirect
|
|
github.com/valyala/bytebufferpool v1.0.0 // indirect
|
|
github.com/valyala/fasthttp v1.50.0 // indirect
|
|
github.com/valyala/tcplisten v1.0.0 // indirect
|
|
go.opencensus.io v0.24.0 // indirect
|
|
go.uber.org/atomic v1.11.0 // indirect
|
|
go.uber.org/multierr v1.11.0 // indirect
|
|
golang.org/x/crypto v0.31.0 // indirect
|
|
golang.org/x/exp v0.0.0-20231006140011-7918f672742d // indirect
|
|
golang.org/x/net v0.33.0 // indirect
|
|
golang.org/x/sync v0.10.0 // indirect
|
|
golang.org/x/time v0.3.0 // indirect
|
|
golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect
|
|
google.golang.org/appengine v1.6.7 // indirect
|
|
google.golang.org/genproto v0.0.0-20230913181813-007df8e322eb // indirect
|
|
google.golang.org/genproto/googleapis/api v0.0.0-20230913181813-007df8e322eb // indirect
|
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20230920204549-e6e6cdab5c13 // indirect
|
|
google.golang.org/grpc v1.58.2 // indirect
|
|
google.golang.org/protobuf v1.31.0 // indirect
|
|
gopkg.in/ini.v1 v1.67.0 // indirect
|
|
)
|
|
|
|
require (
|
|
github.com/gofiber/fiber/v2 v2.50.0
|
|
github.com/jinzhu/copier v0.4.0
|
|
github.com/pelletier/go-toml/v2 v2.1.0 // indirect
|
|
github.com/spf13/viper v1.17.0
|
|
golang.org/x/sys v0.28.0 // indirect
|
|
golang.org/x/text v0.21.0 // indirect
|
|
gopkg.in/yaml.v3 v3.0.1 // indirect
|
|
)
|