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&DMakeBuyStockPlanItemsGMPOpsAdminInsights
← Sales orders / New

New sales order

will post as YGMSB-260707 · series from customer (YGMSB-26{MMDD}, admin-settings numbering)

1 · Order header

2 · Lines

price auto-fills from what this customer last paid
Line total 99,000.00 MYR

from Q-2026-029 10k tier · last paid 10.20 · band 9.80–11.00 · floor 9.50 · ✓ above floor

FG in stock 0 pcs — a Make… MO action will appear on the SO card; ingredients In stock at CYTO-11

Line total 9,600.00 MYR 🔒 locked — not in total

Below floor 5.00 — line locked, approval request sent to owner (Leo)

list 8.00 · raise to ≥ 5.00 to unlock or wait for owner approval — same hard lock as Retail, no OEM backdoor

Line total 9,600.00 MYR

Owner-approved at 4.80 (floor 5.00) — Leo, one-time exception · floor stays 5.00

3 · Totals

Subtotal (confirmable) MYR

incl. Manufacturing / tolling fee service 8,500.00 — revenue, zero COGS, no stock movement

Shipping fee
Tax 0.00 MYR
Total MYR

+ 9,600.00 🔒 excluded until owner approves

+ 9,600.00 ✓ included — owner-approved

= Σ(qty × price × (1 − disc)) + shipping + tax

4 · Notes

Save draft Cancel
On create: joins the Open list at rank 16 · availability chips compute per location · lines without FG stock get Make… actions creating MOs numbered {SO#} / {line} · price memory updates at fulfillment, not create.

Project Gaia — static mockup in Filament v3 idiom. No backend. OEM sales-order create form (SalesOrderResource CreateRecord); shared customers + variant_prices tables with Retail underneath, screens separated.

New sales order — field manifest

FieldFilament componentTypeSourceFK target
PageSalesOrderResource CreateRecordformcreates: sales_orders + so_lines; number from customer series (YGMSB-26{MMDD})
Order #TextInput, default from seriesstring, user-editablestored: sales_orders.number — series set by customer entity (admin-settings numbering)
CustomerSelect::searchable() + createOptionFormFKstored: sales_orders.customer_id — channel ∈ {oem, both}; picking sets the order seriescustomers.id
Customer ref #TextInputstring, nullablestored: sales_orders.customer_reference — printed on confirmation & packing slip
Bill to / Ship toTextarea ×2FK / FK nullablestored: sales_orders.billing_address_id + shipping_address_id (nullable, NULL = same as billing)addresses.id
CreatedPlaceholder (read-only)datetime + FKstored: sales_orders.created_at + created_by (Kevin Wong)users.id
Delivery deadlineDatePicker requireddatestored: sales_orders.delivery_deadline — drives the red at-risk render on the Open list
LocationSelectFKstored: sales_orders.location_id — availability chips compute against this warehouselocations.id
CurrencySelectenum MYR/USD/SGD/CNYstored: sales_orders.currency — FX snapshot at create; floor compare always in base MYR
NotesTextareatext, nullablestored: sales_orders.notes
Shipping feeTextInput group (description / amount / tax)string / money / FKstored: sales_orders.shipping_fee_description + shipping_fee_amount + shipping_fee_tax_rate_id — carried from the quote on acceptancetax_rates.id
Line: Product / serviceRepeater → Select::searchable() (Products / Services optgroups)FK — one of twostored: so_lines.variant_id (product line — stock movement + COGS) OR so_lines.service_item_id (service line — no movement, no COGS, revenue only); exactly one set per linevariants.id / service_items.id
Line: ServiceSelect "Services" optgroup (Manufacturing / tolling fee · R&D / formulation development)FK, mutually exclusive with variant_idso_lines.service_item_id — a service line has NO lot / FEFO / availability chip and never writes to the stock ledger; qty × unit price books to revenue with ZERO COGS. No Make… / MO action (nothing to produce)service_items.id
Line: QtyTextInput::numeric()decimal pcsstored: so_lines.quantity
Line: Unit priceTextInput::numeric(), afterStateUpdated floor checkmoney MYRstored: so_lines.unit_price — rule: net price after disc ≥ variant_prices.floor_price else line locks + approval_requests row to ownervariant_prices / approval_requests
Line: Disc %TextInput::numeric()percent, default 0stored: so_lines.discount_percent — net price after discount is what the floor compares
Line: TaxSelect per lineFKstored: so_lines.tax_rate_id — SST 0% default this tenant, same tax_rates table as quotestax_rates.id

Engine notes

  • Floor lock: compared in base MYR after discount; a below-floor line locks (excluded from the confirmable total) and writes an approval_requests row to the owner — Create stays disabled while any line is locked. Same hard lock as Retail, no OEM backdoor.
  • Series: order number series comes from the customer entity (YGMSB-26{MMDD} here); the field stays user-editable, matching the free-text order_no idiom on the Open list.
  • On create: the order joins the Open list at rank 16; Sales items / Ingredients chips compute per location; lines without FG stock get Make… actions creating MOs numbered {SO#} / {line}; price memory updates at fulfillment, not create.
  • Service lines: a line can be a product (variant_id — stock movement + COGS at fulfillment) OR a service (service_item_id — Manufacturing / tolling fee, R&D / formulation development). A service line has no lot, no FEFO, no availability chip and no Make… action; it never touches the stock ledger and books qty × unit price to revenue with zero COGS. Service line totals add to the confirmable subtotal normally (the seeded 8,500.00 tolling fee here).
  • Quote provenance: created from Q-2026-029's accepted 10k tier — qty, price, tax, shipping fee, addresses and customer ref carried over; the CRM deal is already Won.