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
← Products / 2024-04

Yes Global AlphaMax V+ / 2024-04

Finished good End Product Sellable Active Quotable — view quotes →
Print spec
SKU
2024-04
Item type
Finished good
Category group
Finished Goods
Category
End Product
Origin country
Malaysia (made in-house)
UoM
pcs
Default location
CTSB — 11, Balakong Jaya
Safety stock
0 pcs
Barcode
Default sales price
55.00 MYR
Current avg. cost
4.63 MYR
Created
2024-04-02
Open MO
YGMSB-260401 / 1 1,197 pcs
Recipe / BOM — version 3 Frozen on 1 open MO
Quantities per 1 pcs (one 12 g sachet — formula weight 11,988 mg)
Certifications GMP ✓ Halal (JAKIM) ✓ MeSTI ✓ ISO 22000 HACCP Kosher NPRA Registered
Product claims Sugar-Free Non-GMO Vegetarian Vegan Gluten-Free Allergen-Free

Certifications & claims cascade BOM → MO → BMR → batch → delivery docs; everything filterable by either.

# Ingredient Supplier Origin Qty per unit UoM Avail. Avg. cost Line cost Notes
1 Taurine / Nexus Wise Nexus Wise China 1,000 mg In stock 0.00004 MYR 0.040 MYR active
2 Altilix (Artichoke Extract) / ITS Nutriscience ITS Nutriscience Italy 300 mg In stock 0.0018 MYR 0.540 MYR branded active
3 Affron / NaVi-CN-HN-ZLKJ NaVi-CN China 28 mg In stock 0.00011 MYR 0.003 MYR 28 mg clinical dose
4 Ascorbic Acid / ITS-Luwei ITS Nutriscience China 500 mg In stock 0.00002 MYR 0.010 MYR vitamin C
5 Sub-assembly (in-house) Malaysia 1,800 mg Expected 0.00019 MYR 0.336 MYR made in-house — nested MO
5.1 Angelica Sinensis Extract / CK-4548 NaVi-CN China 900 mg In stock 0.00024 MYR 0.216 MYR premix line
5.2 Agaricus Mushroom Extract / NaVi-CN-XAFDSWKJ NaVi-CN China 600 mg In stock 0.00004 MYR 0.024 MYR premix line
5.3 Agarwood Extract / A&T Ingredients A&T Ingredients Indonesia 300 mg In stock 0.00032 MYR 0.096 MYR premix line
6 Apple Juice Powder / Nexus Wise-DSB Delmar Nexus Wise China 4,000 mg In stock 0.0001 MYR 0.400 MYR carrier / base
7 Apple Powder / ITS-Italy-Iprona-IPOFL-70020018 Iprona Italy 1,500 mg In stock 0.00014 MYR 0.210 MYR
8 Apple Fiber / ITS-Sanacel ITS Nutriscience China 2,500 mg In stock 0.00002 MYR 0.050 MYR soluble fiber
9 Apple Flavor / CK-1647 CK Ingredients Malaysia 300 mg Expected 0.00013 MYR 0.039 MYR scrap 2%
10 Acesulfame Potassium (ACK) / Nexus Wise Nexus Wise China 60 mg In stock 0.00014 MYR 0.008 MYR sweetener
1.64 MYR Materials cost total
+ 2.99 MYR Operations cost (see Operations tab)
= 4.63 MYR Rolled-up unit cost — matches current avg. cost
Per 1 pcs — one 12 g sachet; carton / box packaging is consumed at the Cartoning operation. Sub-assembly lines explode into nested MOs at planning time (multi-level BOM).
Triple approval — release gate 3 / 3 approved

R&D approved ✓

Jason Teh 2026-03-20

“Formula confirmed correct”

ENG approved ✓

Sarah Tan 2026-03-21

“Machine specs confirmed correct”

QA approved ✓

Farah Hussin 2026-03-22

“Food safety reviewed. No new allergens.”

Approved artwork: AMX_label_v3_approved.pdf
BOM cannot go Active without all three approvals; each approval auto-records who + when; unchecking requires Cancel.
Recipe documents — versioned with v3 stability studies, approved artwork, regulatory letters
Type Document Issued Status File / link
Stability study 24-month stability report 2026-02-11 Valid AMX_stability_24mo.pdf
Artwork Label artwork v2 Approved 2026-03-22 Valid R&D design track →
NPRA letter Variant notification Submitted 2026-06-24 Valid JC-26-014 →
Recipe docs ride the recipe VERSION — a new version starts its own register (frozen history, same doctrine as the BOM).
Production operations — routing Operation names as used on the Tasks board (Make → Tasks)
# Operation Type Resource Time per unit Cost rate Cost per unit Instructions & precautions
Line Setup & Cleaning (changeover) Setup Mixing Room 3.0 s 60.00 MYR/h 0.05 MYR
Full washdown per SOP-CL-04. Line clearance sign-off required before start.

Work instruction

Prepare Ingredients & Mixing Process Mixing Room 36.0 s 60.00 MYR/h 0.60 MYR
Speed 120 RPM, 25°C. ALLERGEN: contains milk derivative — full changeover if previous batch allergen-free.

Work instruction

Charge powders into the Ribbon Blender in order of ascending bulk density — carriers and fibre first, actives next, flavour and sweetener premixes last. Dry-mix 10 minutes before adding the flavour premix, then blend a further 15 minutes at the set RPM. Scrape blender walls and paddle at the 12-minute mark to break up any caking near the taurine charge. Pull a top/middle/bottom sample for the in-process blend-uniformity check before releasing to Sachet Packing. Stop and cool the load if bowl temperature exceeds the set point.

Machine settings

Mixer RPM 120 Temp 45°C Mix time 25 min Mesh 80

Attachments

RichEditor + FileUpload — versioned with the recipe; open MOs keep their frozen copy.
Sachet Packing Process Sachet Line 1 63.0 s 48.00 MYR/h 0.84 MYR
H-seal 165°C, V-seal 170°C. Check seal integrity every 30 min. Air bubble test mandatory.

Work instruction

Load the roll-stock onto Sachet Line 1 and verify the film registration mark against the photocell before running. Set H-seal to 165°C and V-seal to 170°C; run a 20-sachet warm-up strip and check peel strength before committing to the batch. Verify fill weight against the 12 g target every 30 minutes on the check-weigher lane and log it on the BMR. Perform the mandatory air-bubble seal test at shift start and after every changeover. Reject and quarantine any sachet with a visible seal gap, wrinkle, or short fill — do not rework into the good-pack stream.

Machine settings

H-seal 165°C V-seal 170°C Line speed 45/min Fill weight 12 g

Attachments

RichEditor + FileUpload — versioned with the recipe; open MOs keep their frozen copy.
Print Expiry Date on Box/Pouch/Sachet Process Inkjet Coder 12.0 s 30.00 MYR/h 0.10 MYR
Format EXP DD/MM/YYYY + batch no. Verify first print against BMR.

Work instruction

Pack into End Product Process Packing Line 54.0 s 40.00 MYR/h 0.60 MYR
30 sachets per box; insert leaflet before closing.

Work instruction

Shrink Wrap Process Packing Line 27.0 s 40.00 MYR/h 0.30 MYR
Tunnel 160°C; check film tension and corner seal.

Work instruction

Cartoning Process Packing Line 45.0 s 40.00 MYR/h 0.50 MYR
12 boxes per carton; apply shipping mark + carton label.

Work instruction

Set the cartoning machine for 30 sachets per box and 12 boxes per carton per the packing spec. Insert the patient information leaflet before the box is folded and glued — verify leaflet presence on the first 5 units after every changeover. Apply the shipping mark and carton label with the batch number and expiry carried from the upstream coder. Spot-check carton weight against expected tare + fill weight every 60 minutes to catch missing boxes. Stack cartons on pallets per the loading pattern in SOP-CTN-007 to keep corner-crush risk low.

Machine settings

Boxes/carton 12 Carton speed 20/min Tape width 48mm

Attachments

RichEditor + FileUpload — versioned with the recipe; open MOs keep their frozen copy.
2.99 MYR
Total operations cost per unit — feeds the Recipe tab roll-up (1.64 + 2.99 = 4.63 MYR)
Per-op optional fields: min operator skill (Trainee / Competent / Expert), changeover time, units/hr, alt machine — used by the capacity calc and pre-flight checks; only name + machine are mandatory. Click the row number to expand the detailed work instruction, machine settings and SOP attachments (D45) — frozen onto the MO at creation and printed on the job traveler.
Variants — packaging generations
Variant code SKU Sales price Avg. cost In stock Status
2026-01 just added 2026-01 55.00 MYR 0 MYR 0 pcs Draft
2023-01 2023-01 48.00 MYR 4.12 MYR 0 pcs Archived
2024-01 2024-01 52.00 MYR 4.41 MYR 0 pcs Archived
2024-04 (this card) 2024-04 55.00 MYR 4.63 MYR 0 pcs Active
Variant code = packaging / formulation generation (tenant convention: YYYY-NN, plus suffixes like -Hologram on other products). Each variant carries its own SKU, recipe version, price and stock. 2024-04 expects 1,197 pcs from MO YGMSB-260401 / 1.
General information
NameYes Global AlphaMax V+
TypeProduct (producible & sellable — materials are the Buy side)
Item typeFinished good (raw_material | packaging | finished_good | consumable)
Category groupFinished Goods → category tree parent
CategoryEnd Product
Origin countryMalaysia (NPRA — made in-house; BOM lines inherit each ingredient's own origin)
Default supplier(made in-house)
Default sales price55.00 MYR
Default UoMpcs
Purchase UoM + conversioncarton · 1 carton = 30 pcs (outsourced runs only)
Default purchase price165.00 MYR per carton (purchase UoM — outsourced runs only)
Lead time14 days — feeds Plan / Replenishment expected-arrival math
Reorder point0 pcs (per location, drives Planning)
Storage bins CTSB — 11, Balakong Jaya: — (FG, no bin in snapshot) CTWSB — 54, Jalan Taming 8: CTCNGZ — Guangzhou 3PL:
Batch tracking ON expiry required at receipt
Additional info RichEditor — informational only, prints nowhere

Label artwork v3 (hologram sticker top-right) approved 2026-03-22 — see attachment on the Recipe tab. Export cartons need the EN/MY bilingual label.

Registration: food supplement under MeSTI — no MAL (NPRA) number required; re-check classification if the affron claim wording changes.

Stock by location — 2024-04 Open in Inventory →
Location In stock Committed Expected Safety stock Calculated
CTSB — 11, Balakong Jaya default 0 pcs 0 pcs 1,197 pcs 0 pcs 1,197 pcs
CTWSB — 54, Jalan Taming 8, Taman Taming Jaya 0 pcs 0 pcs 0 pcs 0 pcs 0 pcs
CTCNGZ — Guangzhou 3PL 0 pcs 0 pcs 0 pcs 0 pcs 0 pcs
Same netting engine as the Inventory screen: calculated = in_stock + expected − committed − safety_stock. Expected here = MO YGMSB-260401 / 1 output (1,197 pcs, work in progress).
GMP documents — item-level register

Raw materials use this same tab — per-LOT CoAs stay on the batch (batch-stock); this register is for the ITEM-level papers (spec, halal, allergen, test methods).

Type Document Issued Expires Status By File
Halal cert Halal certificate — JAKIM-2024-0117 2024-08-30 2026-08-30 Expiring · 52d Farah Hussin JAKIM-2024-0117.pdf
Spec sheet Item specification — v3 2026-03-22 no expiry Valid Jason Teh AMX_spec_v3.pdf
Allergen statement Allergen statement 2026-01-15 no expiry Valid Farah Hussin AMX_allergen_statement_2026-01.pdf
Micro test Microbiological test — last FG lot AMX-2604-01 2026-04-18 no expiry Valid Farah Hussin AMX-2604-01_micro.pdf
gmp_documents (D48): polymorphic register (documentable morph — items & recipes in v1) · doc_type enum · file via media morph, private OBS bucket, signed URL only · issued_at · expires_at nullable · note · uploaded_by. Status is DERIVED, never stored: no expiry or >60 days out → Valid (green); ≤ 60 days → Expiring (amber); past → Expired (red) — same rule feeds the QA dashboard "docs expiring" tile and notifications.

Project Gaia — static mockup in Filament v3 table idiom. No backend. Sample data: Katana tenant snapshot 2026-04-12. This card was never captured from Katana: product, MO link, ingredient names, avg. costs and availability are real snapshot values; recipe quantities, operation times/rates and variant history are illustrative and consistent with the 4.63 MYR FG cost magnitude.

Archive Yes Global AlphaMax V+ / 2024-04?

Archiving hides the variant from Items, Inventory and order pickers. Stock history, batches and the movement ledger are kept — archive is reversible.

1 open MO references this variant — YGMSB-260401 / 1 · 1,197 pcs, Work in progress. Archiving is blocked until it completes or is cancelled.

Yes Global AlphaMax V+

New variant

Not saved

Tenant convention YYYY-NN; suffixes like -Hologram allowed (cf. JuicyPop 2023-01-Hologram).

Defaults to the variant code.

MYR
MYR per carton

Purchase UoM: 1 carton = 30 pcs — outsourced runs only.

The copied recipe lands as v1 Draft on the new variant and must pass the R&D / ENG / QA release gate before it can go Active (GMP). Stock, batches and avg. cost start at zero.

Recipe / BOM

Version history — Yes Global AlphaMax V+ / 2024-04

v3 Active Frozen on 1 open MO Effective 2026-03-22
Unit cost 4.63MYR · materials 1.64 + operations 2.99
R&D Jason Teh 2026-03-20 ENG Sarah Tan 2026-03-21 QA Farah Hussin 2026-03-22

Change note: Affron dose confirmed 28 mg; artwork v3 hologram.

Frozen copy on YGMSB-260401 / 1 →
v2 Superseded Effective 2025-06-10
Unit cost 4.41MYR
R&D Jason Teh 2025-06-05 ENG Sarah Tan 2025-06-08 QA Farah Hussin 2025-06-09

Change note: Sweetener swapped to Acesulfame Potassium (ACK); scrap 2% on Apple Flavor.

v1 Archived Effective 2024-04-02
Unit cost 4.12MYR

Note: Initial release with variant 2024-04.

Versions are immutable once superseded. Each MO carries its own frozen snapshot (mo_ingredients / mo_operations) — editing the recipe never mutates open MOs. New versions require the triple approval gate before going Active.

Item detail — field manifest

Filament v3: Resource view page. Header = Infolist + header Actions (Make primary, Print spec, Archive danger). Tabs = Tabs component; Recipe = Repeater on the edit form (read view shown); Operations & Variants = RelationManagers; Stock = derived per-location Infolist table.

FieldFilament componentTypeSourceFK target
Name / variant codeTextEntry (Infolist header)stringstored: items.name + variants.codevariants.id
SKUTextEntry / TextInputstring, nullablestored: variants.sku
Item typeTextEntry::badge()enum, mandatorystored: items.item_type — raw_material | packaging | finished_good | consumable (this card = finished_good); master classification axis, rendered as the gray Type badge in the header
Category groupTextEntry / Select (parent of Category)FK, admin-lockedstored: items.category_group_id — admin-locked parent (5 ingredient groups + a finished-goods group); category_groups.id → categories treecategory_groups.id
CategoryTextEntry::badge() + Select (grouped by category group)FK, admin-lockedstored: items.category_id — admin-locked child of a category group (~22 clean values; ingredient tree). Finished goods keep the End Product categorycategories.id
Origin countrySelect (country list)enum / FK, admin-lockedstored: items.origin_country — authoritative country of origin (NPRA); made-in-house FGs = Malaysia. Every recipe/BOM line inherits its ingredient material's origin_country from here (see Recipe line · origin country)countries.id
Customer-suppliedToggle / badgeboolstored: items.customer_supplied — customer-paid packaging carried at RM0 cost (packaging items only; teal badge)
Type / Sellable / ActiveTextEntry::badge(), Toggleenum + boolstored: items.type (product|material|service), items.is_sellable, variants.status — kit/bundle deliberately NOT in the enum: v1 out of scope (no tenant usage in either snapshot); revisit only if retail bundles appear
Default supplierSelect::relationship()FK, nullablestored: items.default_supplier_id (null — made in-house)suppliers.id
UoM / purchase UoM + conversionSelect (admin-locked units list) ×2 + disabled TextInput conversion displayFK ×2 + decimalstored: variants.uom_id, items.purchase_uom_id → units table (staff pick, never type); unit↔unit factors (kg→mg, L→ml) hard-coded — items.purchase_uom_factor only for pack units (1 carton = 30 pcs), which are item dataunits.id
Default purchase priceTextInput::numeric()->suffix('MYR')money, nullablestored: items.default_purchase_price — per purchase UoM; prefills PO lines (supply-details tab stays consolidated into General, this carries its dropped field)
Lead timeTextInput::numeric()->suffix('days')int, nullablestored: items.lead_time_days — feeds Plan / Replenishment expected-arrival math (order-by date = need date − lead time)
Default cost (service)TextInput::numeric()->suffix('MYR')money, nullablestored: variants.default_cost — used when items.type = service: services have no stock movements so no derived avg. cost; feeds SO line margin and outsourced-operation costing
Additional infoRichEditortext, nullablestored: items.additional_info — free-form label/registration remarks, informational only (same gap flagged in product, service and MO captures of the item card)
Batch trackingToggle (disabled once movements exist)boolstored: items.is_batch_tracked — ON forces batch + expiry at every receipt/consumptionbatches
Safety stock / reorder pointTextInput::numeric per locationqtystored: variant_location.safety_stocklocations.id
Storage binSelect per locationFK, nullablestored: variant_location.bin_idstorage_bins.id
Default sales priceTextInput::numeric()->suffix('MYR')moneystored: variants.default_sales_price
Current avg. costTextEntry (read-only)decimal(20,10)derived: moving average per location (inventory engine)
Recipe (header)— table recipesrowstored: recipes.variant_id, recipes.version, recipes.status (draft|active|frozen)variants.id
Recipe · version historyRead-only slide-over (recipes rows per variant, newest first)int + enum + datetime + FKstored: recipes.version (int), recipes.status (draft|active|superseded|archived), recipes.effective_at, recipes.superseded_by_id (self-FK) — immutable once superseded; each MO freezes its own snapshot (mo_ingredients / mo_operations), so editing never mutates open MOs; new versions gated behind the R&D/ENG/QA triple approval before status → activerecipes.id
Recipe line · ingredientRepeater → Select::relationship('ingredientVariant')FKstored: recipe_lines.ingredient_variant_id — when target variant is itself producible ⇒ sub-assemblyvariants.id
Recipe line · qty per unitTextInput::numericdecimal(20,10)stored: recipe_lines.qty_per_unit, in ingredient UoM (mg)
Recipe line · scrap %TextInput::numeric()->suffix('%')decimal, nullablestored: recipe_lines.scrap_pct (inflates MO ingredient requirement)
Recipe line · Avail. badgeTextEntry::badge()->color(fn)derivedderived: ingredient location stock ≥ requirement → In stock (green), else open PO/MO → Expected (amber)stock_movements
Recipe line · line costTextEntry (computed)moneyderived: qty_per_unit × ingredient moving-avg cost
Operation · name / typeOperationsRelationManager, reorderable()string + enumstored: operations.name, operations.type (process|setup)recipes.id
Operation · resourceSelect::relationship('resource')FKstored: operations.resource_id (Tasks board groups by this)resources.id
Operation · time / rate / costTextInput::numeric ×2 + computed TextEntrydecimalstored: operations.time_per_unit, operations.cost_rate; derived: cost = time × rate
Recipe · certificationsCheckboxList (multiselect)json arraystored: recipes.certifications (GMP, Halal JAKIM, MeSTI, ISO 22000, HACCP, Kosher, NPRA Registered) — cascades BOM → MO → BMR → batch → delivery docs; filterable everywhere
Recipe · product claimsCheckboxList (multiselect)json arraystored: recipes.product_claims (Sugar-Free, Non-GMO, Vegetarian, Vegan, Gluten-Free, Allergen-Free) — same cascade rule as certifications
Recipe · triple approvalToggle ×3 + auto TextEntry (who/when)bool + FK + date ×3stored: recipes.rnd_approved / _by / _at, eng_approved / _by / _at, qa_approved / _by / _at — gate: recipe cannot go Active until all three; each auto-records user + timestamp; unchecking requires Cancel actionusers.id
Recipe line · supplierSelect::relationship('supplier')FK, nullablestored: recipe_lines.supplier_id — auto-fetched from the ingredient item's default supplier, editable per linesuppliers.id
Recipe line · origin countryTextEntry (read-only, inherited)enum / FKderived: inherits the ingredient material's items.origin_country (authoritative NPRA country of origin — China / Italy / Indonesia / Malaysia in the lines above); snapshotted onto recipe_lines / mo_ingredients at BOM freeze for the batch dossier, editable only as a per-line overridecountries.id
Operation · instructionsTextareatext, nullablestored: operations.instructions — free text incl. allergen / seal-check precautions; surfaced on the Tasks board and printed into the BMR
Operation · work instructionRichEditor (expandable row, per-op)longtext, nullablestored: recipe_operations.work_instruction — the detailed setup/procedure/quality-check text for the step (D45), distinct from the short Instructions & precautions column above; ops without one show a “+ Add instruction” ghost
Operation · machine settingsKeyValue (chip row render)json, nullablestored: recipe_operations.machine_settings — structured key→value pairs the floor dials in, e.g. {"mixer_rpm":120,"temp_c":45,"mix_time_min":25,"mesh":"80"}
Operation · SOP attachmentsFileUpload (chips + dashed attach ghost)media, nullablestored: media morph, collection sop — SOP PDFs, correct-setup reference photos; versioned with the recipemedia.id
Operation · instruction snapshot rule— (engine behaviour, no field)rulework_instruction + machine_settings + sop media are copied onto mo_operations at MO creation (BOM freeze, same rule as mo_ingredients/mo_operations elsewhere on this page) — editing the recipe's instruction never mutates an open MO; the frozen copy is what prints on the job traveler / BMRmo_operations
Operation · optional fieldsSelect + TextInput::numeric ×2 + Selectenum + decimal ×2 + FKstored: operations.min_skill (trainee|competent|expert), operations.changeover_time, operations.units_per_hour, operations.alt_machine_id — used by capacity calc and pre-flight checks; only name + machine are mandatoryresources.id
BOM · R&D requestTextEntry::url() (Link)FK, nullablestored: recipes.rnd_request_id — links the BOM back to the originating R&D requestrnd_requests.id
Variants tableVariantsRelationManagerrowsstored: variants (code, sku, price, status) + derived stock/avg costitems.id
New variant · codeVariantsRelationManager CreateAction → TextInputstringstored: variants.code — unique per item (YYYY-NN + optional suffix); a fresh generation of the same productitems.id
New variant · statusSelectenumstored: variants.status gains draft (draft|active|archived) — Active disabled until the copied recipe clears triple approval
New variant · copy recipe / routingSelect (source variant) + CheckboxFK + boolaction: clones the source recipe into a new recipes row (version 1, status draft, rnd/eng/qa approvals null) + recipe_lines / operations copiesrecipes.id
Stock by locationInfolist table (read-only)derivedderived: same ledger as Inventory screen, filtered to this variantstock_movements
Documents tab — registerGmpDocumentsRelationManagerrowsstored: gmp_documents (D48) — polymorphic documentable morph, this card scoped to documentable_type=items; columns doc_type (spec_sheet | coa | halal_cert | msds | allergen_statement | moisture_test | micro_test | heavy_metals | stability_study | artwork | npra_letter | other), issued_at, expires_at nullable, note, uploaded_byitems.id
Document · fileFileUpload (chip + dashed upload ghost)media, nullablestored: media morph — private Huawei OBS bucket, NEVER the ECS disk; signed URLs only (SECURITY §6, D49)media.id
Document · statusTextEntry::badge() (derived, not stored)derivedderived: expires_at null or > 60 days away → Valid (green); ≤ 60 days away → Expiring · Nd (amber, e.g. halal_cert above); in the past → Expired (red) — the same rule drives the QA dashboard "docs expiring" tile and notifications
Recipe documents cardGmpDocumentsRelationManager (documentable=recipes)rowsstored: gmp_documents where documentable_type=recipes, documentable_id=recipes.id — versioned WITH the recipe; a new recipe version starts its own register (frozen history, same doctrine as the BOM). Batches keep their existing per-lot CoA media (batch-stock.html) and suppliers keep their existing docs-via-media — neither migrates into gmp_documentsrecipes.id
BarcodeTextInput (empty across snapshot)string, nullablestored: variants.barcode

Engine notes

  • Rolled-up unit cost = Σ(line qty × ingredient moving-avg) + Σ(operation time × cost rate) — recomputed when an MO completes (actual consumption at actual costs), NOT when the recipe is edited.
  • Sub-assembly = a recipe line whose ingredient variant is itself producible (has its own recipe) ⇒ multi-level BOM; planning explodes it into a nested MO (Vit-Min Premix here).
  • Recipe versions freeze against open MOs: each MO carries its own snapshot (mo_ingredients / mo_operations copied at MO creation), so editing this recipe never mutates YGMSB-260401 / 1.
  • Work instructions ride the same freeze: recipe_operations.work_instruction, machine_settings and any sop media are copied onto mo_operations at MO creation and print on the job traveler / BMR — the paper the floor executes from stays official.
  • Avail. badge per line reuses the inventory netting engine at the default location: enough in stock → green; shortfall covered by open PO/MO → amber Expected.
  • is_batch_tracked = true forces batch + expiry entry at receipt (PO receive or MO completion) and batch pick at every consumption — GMP traceability chain.
  • qty_per_unit is stored in the ingredient's UoM (mg for materials, pcs for sub-assemblies/products); the FG unit here is 1 pcs = one 12 g sachet.
  • Item classification is four fields: item_type (enum) · category_group_idcategory_id (admin-locked tree) · customer_supplied (packaging only) · origin_country. The Origin column on each recipe/BOM line is not typed here — it inherits the ingredient material's origin_country (China, Italy, Indonesia, Malaysia above), frozen onto the MO snapshot for NPRA batch traceability.
  • Units rule: quantities are stored in the item's base unit (mass → mg, volume → ml, count → pcs); display auto-scales (1,250,000 mg shows as 1.25 kg). Unit pickers are locked to the admin units table and unit↔unit factors are hard-coded (1 kg = 1,000 g = 1,000,000 mg; 1 L = 1,000 ml) — staff never type units; only per-item pack conversions (1 carton = 30 pcs) are data.
  • BOM cost = Σ(RM qty × valuation rate) + operation costs — the true manufacture cost the owner sees on the SO.
  • Service-type items collapse to a thin card — name, category, UoM, sell-only toggle, price / SKU / default cost, notes — with no Recipe / Operations / Variants / Stock tabs: services never touch the stock ledger, so variants.default_cost stands in for the missing moving-average.
  • Make actions create draft mos + mo_ingredients/mo_operations snapshots; nothing reserves stock until Commit ingredients on the MO card.
  • New variant = a fresh packaging/formulation generation of the same product: variants.code unique per item, stock/batches/avg. cost start at zero. Copy recipe/routing clones the source into recipes as version 1, status draft, approvals null — it must clear the R&D/ENG/QA triple-approval gate before variants.status can go active.
  • Archive = variants.status → archived; Filament Action::requiresConfirmation, ->disabled(fn: open MOs/SOs exist) with the blocking documents listed in the modal.
  • GMP document register (D48): one polymorphic gmp_documents table serves both the Documents tab (documentable=item) and the Recipe documents card (documentable=recipe, versioned with it); raw-material per-LOT CoAs stay where they already lived, on the batch (batch-stock.html) — not migrated here. Status is always computed at read time from expires_at, never stored, so it can't drift out of sync with today's date.