G Gaia

Switch factory

CYTO-11 — Balakong Jaya CTSB CYTO-29 CTSB CYTOWELL-54 — Taming Jaya PIC/S CTWSB CYTOCNGZ-602 — Guangzhou CTCNGZ

Only factories you are granted appear here (Filament tenant menu).

Leo Lim

leo@navi.my · Owner / Admin

Profile settings Change password

Theme

Sign out
RetailSellR&DMakeBuyStockPlanItemsGMPAdminInsights

Retail customers

One customers table, two views: every customer row carries a channel flag (oem / retail / both). This screen shows retail + both; Sell → Customers shows oem + both. Same data underneath — a kedai that grows into an OEM buyer just flips to both and keeps its whole history.
6 customers in the retail view
Name Phone Area Channel Usual products Orders First order Last order Status
OEM customers (Roy KL Trading, Yes Global, Al Insan Sempurna, …) live in Sell → Customers — same customers table underneath, different view scope: that screen filters channel ∈ {oem, both}, this one channel ∈ {retail, both}. Herbs & Health PJ appears in both views.

Project Gaia — static mockup in Filament v3 idiom. No backend. Retail module; customer data shared with OEM underneath (channel-flagged), screens separated.

Retail customers — field manifest

FieldFilament componentTypeSourceFK target
Name / Phone / AreaTextColumnstoredstored: customers — ONE table shared with OEM (Sell → Customers reads the same rows). No retail_customers table existscustomers
ChannelBadge + SelectFilterenum oem / retail / bothstored: customers.channel. THIS resource scopes channel ∈ {retail, both}; Sell → Customers scopes channel ∈ {oem, both}. channel=both also flips e-invoicing to per-sale B2B
Usual productsTextColumn, derivedderivedmost-frequent variants from this customer's sale-line history (shared engine with the CRM book)retail_sale_lines
Orders / First / Last orderTextColumn, derivedaggregatecount / min(date) / max(date) over retail_sales for the customerretail_sales
StatusBadge, derivedflagActive, or DUE TO REORDER when now > last_order + 1.5× cadence — same derived rule as Retail CRM, no status field stored
+ Customer (slide-over)CreateAction slideOver()formcreates: customers (display_name, phone, area, channel enum oem/retail/both, terms, b2b_einvoice, notes) — same table Sell → Customers writes; creation here defaults channel=retail. No price fields: price memory builds from confirmed sales, floor lives in variant_pricescustomers

Engine notes

  • Shared-data doctrine: ONE customers table (channel enum oem / retail / both) and ONE variant_prices table — data shared, views scoped. What separates Retail from Sell: screens, numbering series (RS- vs SO-), CRM shape (book vs pipeline), e-invoicing path (consolidated vs per-order).
  • Promoting a retail customer to OEM = set channel to both. History, price memory and cadence carry over — nothing is copied or re-entered.
  • Walk-in is a pseudo-customer (null FK on the sale): counted in sales, excluded from the book, no price memory kept.

Customer

Not saved

The one required field.

ONE customers table shared with OEM. both = also visible in Sell → Customers and gets a per-sale B2B e-invoice instead of joining the monthly consolidation. A kedai that grows into OEM just flips to both and keeps its history.

Routes e-invoicing per sale via QBO. Auto-on (and locked) when channel = both.

No price fields here — price memory builds itself from confirmed sales; the floor lives in variant_prices (owner-edited in Sell → Price lists).