all the refactor
This commit is contained in:
@@ -0,0 +1,97 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
messages "git.k6n.net/mats/go-cart-actor/proto/cart"
|
||||
"git.k6n.net/mats/platform/catalog"
|
||||
)
|
||||
|
||||
// taxClassToBp maps the canonical TaxClass string identifiers published on
|
||||
// catalog.Projection to basis-points-of-a-percent (rate × 100) — the single
|
||||
// platform-wide rate scale used by AddItem.Tax (int32 basis points), the
|
||||
// mutation registry, and the tax.Provider Compute formula.
|
||||
//
|
||||
// Values reflect the standard tariff names used by the Nordic configuration.
|
||||
// Per-country / per-tenant numeric resolution (e.g. Finland 25.5%, Ireland
|
||||
// 13.5%) is delegated to platform/tax and is a follow-up: this static map
|
||||
// gets the common case right (2500 / 1200 / 600 / 0) and lets the cache path
|
||||
// ship while the platform/tax lookup is wired into the cart pool server.
|
||||
var taxClassToBp = map[string]int{
|
||||
"standard": 2500,
|
||||
"reduced": 1200, // common reduced rate (e.g. SE/NO food)
|
||||
"lowered": 600, // super-reduced
|
||||
"zero": 0, // zero-rated (export, healthcare, ...)
|
||||
"exempt": 0, // similarly untaxed, separate nominal class
|
||||
}
|
||||
|
||||
// resolveTaxBp returns the basis-point rate for a TaxClass string, falling
|
||||
// back to platform "standard" (25%) when the class is unrecognised. The
|
||||
// default matches the grain's existing behaviour (AddItem falls back to 2500
|
||||
// when m.Tax == 0 — see pkg/cart/mutation_add_item.go).
|
||||
func resolveTaxBp(class string) int {
|
||||
if bp, ok := taxClassToBp[class]; ok {
|
||||
return bp
|
||||
}
|
||||
return 2500
|
||||
}
|
||||
|
||||
// ApplyProjectionOverlay overlays the cache's authoritative catalog facts onto
|
||||
// an AddItem message that was just produced by a PRODUCT_BASE_URL HTTP fetch.
|
||||
//
|
||||
// Authoritative-from-cache fields (these WIN over the HTTP-fetched value when
|
||||
// both are present, because the bus is the live stream):
|
||||
//
|
||||
// Price (bus has post-class-overrides; product service has static)
|
||||
// Tax (TaxClass → bp via resolveTaxBp; only when TaxClass is set —
|
||||
// an empty TaxClass means the producer didn't classify,
|
||||
// so we leave the HTTP-fetched rate intact rather than
|
||||
// quietly swapping in a default 2500 and miscategorising)
|
||||
// Title (canonical, post-trim)
|
||||
// Image (canonical)
|
||||
// InventoryTracked (only flips to true; false is the zero value in proto
|
||||
// and may be unset on the wire, so we don't second-guess)
|
||||
// DropShip (only flips to true; same reasoning)
|
||||
//
|
||||
// The HTTP-fetched values remain authoritative for fields the cache does not
|
||||
// carry: SellerId / SellerName (marketplace split), Stock (per docs/inventory-
|
||||
// shape.md stock is queried synchronously from inventory, not cached),
|
||||
// OrgPrice / Discount (not yet on the projection schema), the dynamic
|
||||
// ExtraJson product data (configurator options — width/height used by
|
||||
// accessory child-pricing), and the catalog uint32 ItemId (the product
|
||||
// service's integer id which messages.AddItem.ItemId dedupes on — Projection
|
||||
// only carries the opaque string ID, so a cache-only build path is blocked
|
||||
// and the HTTP fetch is preserved).
|
||||
//
|
||||
// Tombstoned SKUs (catalog.projection_published with deleted=true) → the
|
||||
// caller checks idx.IsDeleted(sku) before this helper and short-circuits.
|
||||
func ApplyProjectionOverlay(msg *messages.AddItem, p catalog.Projection) {
|
||||
if msg == nil {
|
||||
return
|
||||
}
|
||||
// Price: positive bus values override HTTP. A zero PriceIncVat is treated
|
||||
// as "no value" rather than "free".
|
||||
if p.PriceIncVat.Int64() > 0 {
|
||||
msg.Price = p.PriceIncVat.Int64()
|
||||
}
|
||||
// Tax: only override when the bus has classified the SKU. An empty TaxClass
|
||||
// means the producer had nothing to say about VAT; the HTTP rate is more
|
||||
// trustworthy in that case than a guessed 2500.
|
||||
if p.TaxClass != "" {
|
||||
msg.Tax = int32(resolveTaxBp(p.TaxClass))
|
||||
}
|
||||
// Display fields: only override if non-empty so the HTTP-fanned value
|
||||
// remains in place when the cache hasn't populated them yet.
|
||||
if p.Title != "" {
|
||||
msg.Name = p.Title
|
||||
}
|
||||
if p.Image != "" {
|
||||
msg.Image = p.Image
|
||||
}
|
||||
// Flags: only flip to true (positive boolean signals). A false is the
|
||||
// proto-zero value and not worth overriding.
|
||||
if p.InventoryTracked {
|
||||
msg.InventoryTracked = true
|
||||
}
|
||||
if p.DropShip {
|
||||
msg.DropShip = true
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user