Materials
+ New material| Name | Variant code / SKU | Category | Default supplier | Default purchase price | Default sales price | |
|---|---|---|---|---|---|---|
| — | MYR | MYR |
Project Gaia — static mockup in Filament v3 table idiom. No backend. Sample data: Katana tenant snapshot 2026-04-12.
Switch factory
CYTO-11 — Balakong Jaya CTSB CYTO-29 CTSB CYTOWELL-54 — Taming Jaya PIC/S CTWSB CYTOCNGZ-602 — Guangzhou CTCNGZOnly factories you are granted appear here (Filament tenant menu).
| Name | Variant code / SKU | Category | Default supplier | Default purchase price | Default sales price | |
|---|---|---|---|---|---|---|
| — | MYR | MYR |
Project Gaia — static mockup in Filament v3 table idiom. No backend. Sample data: Katana tenant snapshot 2026-04-12.
Turning OFF is blocked once stock movements exist — GMP traceability.
They disappear from pickers and new documents but keep full history and batch traceability. Items still holding stock remain visible in Stock until zeroed out.
Exports run async with a completion notification — same pipeline as the “Import done.” toast in the Katana capture.
Only items with zero stock and no stock movements can be deleted — anything with ledger history is skipped (archive instead; movement history is immutable under GMP). This cannot be undone.
| Field | Filament component | Type | Source | FK target |
|---|---|---|---|---|
| Name | TextColumn::searchable(isIndividual)->url()->sortable() | string (material / variant) | derived display: '{name} / {variant code | supplier tag}' — keep name and variant code as distinct stored fields | variants.id |
| Variant code / SKU | TextColumn::searchable(isIndividual) | string, nullable | stored per variant, optional (empty on "BBeast Men's Candy Sachet"); can differ from Name suffix (Belgian Dark Cocoa → CBADCP22PLARO91B) | — |
| Category | TextColumn::badge() + SelectFilter | string lookup | stored: items.category_id — free-form tag shared across items (13+ values observed) | categories.id |
| Default supplier | TextColumn::placeholder('—') | string, nullable | stored FK — unpopulated across the snapshot despite supplier names embedded in Name strings | suppliers.id |
| Default purchase price | TextColumn::money('MYR') | money MYR | stored default unit cost; defaults to 0 MYR when unset (every visible row 0) | — |
| Default sales price | TextColumn::money('MYR')->placeholder('') | money MYR, nullable | stored, optional — populated only on materials also sold directly (2 of 18 sample rows) | — |
| Active / Archive tabs | Tabs (lifecycle filter); Archive view not captured | bool flag | stored: items.archived_at | — |
| Bulk actions | BulkAction: Bulk edit / Archive / Delete (+ Print, Export header actions) | action | Katana toolbar icon cluster (print, edit, export/archive, trash) | — |
BulkAction::make('bulkEdit')->form(...) (category / purchase price / batch tracking); ->archive() sets items.archived_at; ExportAction runs via the Filament export job (async notification, same pipeline as the import toast); DeleteBulkAction is policy-guarded — deletable only when no stock_movements rows reference the variant, so items with ledger history are skipped (archive instead — GMP immutability). Toolbar Export CSV icon runs the same export over the filtered set when nothing is selected.