3.1 Region Resolution
Input: facility.country, facility.city, optional postalCode.
Rule: Map to Region via precedence: explicit country rule → sub‑region (e.g., GCC vs Non‑GCC) → default fallback.
Examples: AE/SA/QA/OM/BH/KW → GCC, GB → UK, US → USA, DE/FR/… → Europe, SG → SE Asia. If a tenant has multiple facilities in different regions, compute per‑facility line items using each facility’s region.
3.2 Price Catalog (Super Admin)
Entities:
PriceList: { priceListId, name, region, currency, taxPolicyId, effectiveFrom, effectiveTo?, isActive }
SKU: { sku, family, label, unit, meta } (families: device, gateway, connectivity, software, license, installation, delivery, certification)
PriceItem: { priceListId, sku, unitPrice, minQty?, maxQty?, tiering?, discountPct?, taxClass, notes }
TaxPolicy: { taxPolicyId, name, region, taxClasses:[{taxClass, ratePct, inclusive:boolean}] }
CRUD & Versioning:
- Create/Update PriceList per region; multiple active lists allowed if effective ranges don’t overlap.
- Price changes do not retro‑edit existing BoQs; BoQs store a snapshot { priceListId, version }.
- Audit trail: who/when/what changed; export/import CSV.
Taxes:
- Support inclusive (VAT‑inclusive prices) vs exclusive (VAT added at calc time).
- TaxClass per SKU (e.g., hardware_standard=5%, software=0%, delivery=5%, certification=0%).
- Multi‑tax support (VAT + ecoFee) via array if required.
3.3 BoQ Computation
Inputs from intake: facility count, floors, area/floor, freezers, fridges, pools, waterTanks, targetLevel, facility type & location.
Formula Families (configurable Rules):
Min devices per area, Cold Storage, Pools → Sigfox, Water Quality, Gateways (LoRa), etc. Admin‑editable without code.
Pricing per Facility Region: per facility resolve region → select active PriceList → compute quantities by family → price line items → apply tax policy. Delivery per device, connectivity per gateway/year, software/licenses per device/pool, installation per facility, certification by type/target.
Discounts: Annual Plan Discount (per region) on recurring totals; optional per‑SKU discount at PriceItem.
3.4 BoQ Output & Persistence
Header: boqId, tenantId, version, createdAt, validUntil(+30 days), priceListId(s), currency per region.
Customer: billTo/shipTo from intake (editable after login before checkout).
Items: [ { sku, label, productCode?, region, facilityId?, qty, unitPrice, discountPct, taxPct, taxAmount, subtotal, type: 'otc'|'annual_recurring' } ].
Totals: { otcTotal, recurringAnnualTotal, recurringMonthlyEquiv, taxTotal, grandTotal }.
Metadata: counts (devices/gateways), targetLevel, facility types, terms, notes.
Visibility: anonymous teaser vs logged‑in full priced + PDF.
3.5 BoQ Lifecycle
States: draft_teaser → priced_active → priced_expired → ordered → paid_otc → cancelled
ValidUntil: createdAt + 30 days (cron → priced_expired)
Redo: recompute with new boqId; keep history; one active BoQ per facility set.
3.6 Checkout Split & Orders
OTC now: hardware, installation, delivery (and setup fees). Recurring later: certification (monthly/annual with discount). Save payment method via SetupIntent. Order links { orderId, boqId, otcAmount, plan, facilities[] }.
3.7 Multi‑Facility & Multi‑Region Rules
Group lines per facility & region; summarize per tenant. PDF sections per facility with region badge; taxes per region. Currency: prefer native; optionally display tenant currency using FX snapshot at BoQ creation.