TotalApp Docs

Harvest & Supply Inventory

Agro-input staging, growing-crop biological asset tracking (IAS 41), silo & storage management, and material consumption analytics — the four ledgers that turn field spend into capitalized harvest value.

What this group does

Four screens, one service file (src/services/harvestSupplyInventoryService.ts), covering the full input-to-output supply chain: chemicals/fertilizers/seeds are staged and deducted as they're used; growing crops are tracked as biological assets that accumulate capitalized costs (IAS 41-style) until harvest; harvested volume lands in silo/storage as intake lots; and every dollar spent along the way is reconciled through one shared material consumption ledger.

Agro-Input Staging
Growing Crop Tracking (WIP)
Silo & Storage Management
Agro-Material Consumption

Under the hood — where the silo registry actually lives

The silo registry (SiloRecord) originally lived as a minimal stand-in inside agroTechExecutionService.ts, used by Season & Harvest Scheduling for storage reservation before this screen existed. When Silo & Storage Management shipped, ownership of that store moved into harvestSupplyInventoryService.ts — and agroTechExecutionService.ts now re-exports fetchSiloRegistry, saveSilo, reserveStorageCapacity, and the SiloRecord type from here, so existing callers (Season & Harvest Scheduling, Farm-to-Fork Traceability) needed no changes. If you're tracing where a silo write actually lands, always look in this file, even when the calling code imports from agroTechExecutionService.ts.

1. Agro-Input Staging

Purpose: Track on-hand stock of fertilizers, pesticides, seeds/seedlings, and soil conditioners staged for field use — expiration, hazard level, reorder threshold.

Key features

  • CodesSTG-2026-XXXX staging lot id (generateStagingLotId) and SKU-2026-XXXX SKU id (generateSkuId), tracked separately since one SKU can have multiple staging lots (different expiration dates).
  • Categoriesfertilizers, pesticides, seeds_seedlings, soil_conditioners (AgroInputCategory).
  • Expiration countdown metercomputeDaysToExpiration() returns days remaining (negative once expired).
  • Derived statuscomputeDerivedStatus() always overrides stored status: expired_quarantined if days-to-expire ≤ 0, else low_stock_alert if quantity ≤ reorder threshold, else staged_ready (AgroInputStagingStatus).
  • MSDS hazard levelsnone, irritant, toxic, highly_toxic_corrosive (MsdsHazardLevel).

Integration triggers

Action / HookWhat it does
deductStagingStockDeducts quantityOnHand across the SKU's staging lots (earliest-expiring first), recomputing each lot's derived status. Called from Field & Greenhouse Orders on order completion and from Agro-Chemical Analytics on chemical application.
reconcileWithChemicalAnalyticsPushes the staging lot's active-ingredient profile onto a matching Agro-Chemical Analytics record (matched by sourceTestId/recordCode/id), and marks syncedToChemicalAnalytics: true. Real write against qualityCropHealthService.ts.
triggerPurchaseOrderReorderFlips reorderTriggered: true on a low-stock record. A local flag only — no Purchase/Procurement screen exists yet in Agriculture to route the actual PO to.

2. Growing Crop Tracking (WIP)

Purpose: Track each active planting as a biological asset (IAS 41-style) — accumulating capitalized costs by category as the crop moves through growth stages toward harvest.

Key features

  • Batch codesWIP-2026-XXXX (generateWipBatchId).
  • Cost capitalizationCapitalizedCostEntry[] tagged by category labor, irrigation, fertilizer, land_usage, each entry timestamped with an optional note.
  • GDD maturity gaugecomputeMaturityPercent() expresses accumulated Growing Degree Days as a percentage of the crop's target GDD, capped at 100.
  • Growth stagesgermination → vegetative → flowering → fruiting → harvest_ready (GrowthStage).
  • Statusactive_wip, storm_damage_flag, harvest_in_progress (GrowingCropWIPStatus).

Integration triggers

Action / HookWhat it does
capitalizeWIPToHarvestOn harvest completion, calls logInboundStorageBatch() (re-exported from this same file via agroTechExecutionService.ts) to create an unverified intake lot in the silo registry, then sets capitalizedToHarvest: true and status harvest_in_progress on the WIP record.
syncAccumulatedCostsReads unreconciled Agro-Material Consumption records for the WIP's location, sums their totalCost, adds it to accumulatedInputCosts, and marks each consumption record wipCostsReconciled: true with a linkedWipId back-reference. Real, local — this service owns both the WIP store and the consumption ledger.

3. Silo & Storage Management

Purpose: Manage bulk silo/warehouse storage capacity — fill level, grain condition, aeration, quarantine status — and link stored lots back to traceability.

Key features

  • Silo codesSILO-2026-XXXX (generateSiloCode).
  • Fill capacity gaugecomputeFillPercent() expresses reserved tonnage as a percentage of total capacity, capped at 100.
  • Grain condition readings — moisture %, internal temperature (°C).
  • Aeration fan statusactive, idle, maintenance_required (AerationFanStatus).
  • Quarantine statusclear, mold_risk_warning, sealed (SiloQuarantineStatus).
  • Storage conditionambient, cold_storage, controlled_atmosphere, dry_depot (SiloCondition).

Integration triggers

Action / HookWhat it does
reserveStorageCapacityIncrements a silo's reservedTons by the expected harvest volume. Called by Season & Harvest Scheduling during harvest planning, via the re-export in agroTechExecutionService.ts.
linkSiloLotToTraceabilityPushes a batch storage record into Farm-to-Fork Traceability, setting storageSiloId/storageSiloCode/storageOriginVerified: true on the matched trace record, and siloLotTraceabilityLinked: true on the silo. Real write against qualityCropHealthService.ts.
triggerAerationMaintenanceDispatches an "Aeration Motor Fault / Overheating" work order via createMaintenanceWorkOrder() (re-exported from agroTechExecutionService.ts, wrapping the domain-agnostic maintenanceWorkOrderService.ts), then sets the silo's aerationMaintenanceTriggered: true and aerationFanStatus: maintenance_required.

4. Agro-Material Consumption

Purpose: The shared consumption ledger every other screen in this add-on posts into — the single source of truth for "what did we actually spend, on what, and where."

Key features

  • Consumption IDsAMC-2026-XXXX (generateConsumptionId).
  • Source categorieschemicals, fertilizers, water_utilities, power_electricity, fuel (MaterialSourceCategory).
  • Seasonal budget burn gaugecomputeBudgetBurnPercent() compares actual cost total against (budgeted cost/ha × hectares), can exceed 100 if over budget.
  • Reconciliation modal — a record carries optional linkedWorkOrderId, linkedResourceCounterId, and linkedWipId back-references, plus a manuallyAdjusted flag and free-text reconciliationNote.
  • Every record is written by another screen — this ledger has no independent "create" flow of its own in the documented pipeline; it is populated entirely by syncOrderMaterialsToConsumption (Field & Greenhouse Orders) and postResourceToMaterialConsumption (Resource Counters).

Integration triggers

Action / HookWhat it does
syncOrderMaterialsToConsumption (source: Field & Greenhouse Orders)On order completion, deducts each material from Agro-Input Staging and writes a matching consumption record here.
postResourceToMaterialConsumption (source: Resource Counters)Posts a utility counter's net usage and cost as a consumption record (resource type mapped to source category).
syncAccumulatedCosts (source: Growing Crop Tracking WIP, reads this ledger)Reads unreconciled records for a WIP's location and folds their cost into the WIP's accumulatedInputCosts, marking them wipCostsReconciled: true.

End-to-end data flow

Source screen / hookWritesTarget screen / store
Field & Greenhouse Orders · syncOrderMaterialsToConsumptionDeducts stock; creates consumption recordAgro-Input Staging + Agro-Material Consumption
Agro-Input Staging · deductStagingStockReduces quantityOnHand per lot, recomputes statusown store (called from multiple sources)
Agro-Input Staging · reconcileWithChemicalAnalyticsSyncs active ingredient onto matched recordAgro-Chemical Analytics
Agro-Input Staging · triggerPurchaseOrderReorderSets reorderTriggered = trueown record (local flag only)
Season & Harvest Scheduling · syncScheduleToWIPCreates GrowingCropWIPRecordGrowing Crop Tracking WIP
Growing Crop Tracking WIP · capitalizeWIPToHarvestCreates INTAKE-<batchCode> silo lotSilo & Storage Management registry
Growing Crop Tracking WIP · syncAccumulatedCostsSums unreconciled consumption cost into accumulatedInputCostsAgro-Material Consumption (read + reconcile)
Season & Harvest Scheduling · reserveStorageCapacity (re-exported)Increments silo reservedTonsSilo & Storage Management registry
Silo & Storage Management · linkSiloLotToTraceabilityLinks storage silo to a lot; sets storageOriginVerifiedFarm-to-Fork Traceability
Silo & Storage Management · triggerAerationMaintenanceDispatches aeration fault work ordermaintenanceWorkOrderService (domain-agnostic)
Resource Counters · postResourceToMaterialConsumptionCreates consumption recordAgro-Material Consumption

Frequently Asked Questions

Why does agroTechExecutionService.ts still export SiloRecord and silo functions?
For backward compatibility. The silo registry moved to harvestSupplyInventoryService.ts when Silo & Storage Management shipped, but agroTechExecutionService.ts re-exports fetchSiloRegistry, saveSilo, reserveStorageCapacity, and the SiloRecord/SiloCondition types so that Season & Harvest Scheduling and other pre-existing callers needed zero import changes when ownership moved.
Can Agro-Material Consumption records be created directly on that screen?
The documented pipeline populates this ledger entirely from Field & Greenhouse Orders (materials used) and Resource Counters (utility usage) — both write into it as an integration side-effect. The screen exists to view, filter, and reconcile those records (including a manuallyAdjusted flag for hand corrections), not as the primary entry point for new consumption.
What happens to a WIP batch's costs once it's harvested?
capitalizeWIPToHarvest creates an unverified intake lot in the silo registry and flips the WIP's status to harvest_in_progress with capitalizedToHarvest: true — the accumulated capitalized costs stay on the WIP record as the batch's final cost basis; they aren't separately transferred elsewhere by this hook.
How does a low-stock staging item get reordered?
triggerPurchaseOrderReorder only sets a local reorderTriggered flag on the record today — there is no Purchase/Procurement screen wired up in this add-on yet to receive an actual purchase order, so the flag is currently just a visual badge in the staging ledger.
Does an expired staging lot get auto-deducted from stock?
No — computeDerivedStatus() only recomputes the display status to expired_quarantined when days-to-expire ≤ 0; it does not zero out or remove the quantity. Actual stock deduction only happens via deductStagingStock, triggered by real consumption events.
Does the aeration maintenance trigger require Agro-Equipment Maintenance to exist?
No — triggerAerationMaintenance routes through the domain-agnostic maintenanceWorkOrderService.ts (also used by Manufacturing's Maintenance Operations group), which already exists independently of whether Agriculture ships its own dedicated maintenance screens. See Agro-Equipment Maintenance for that group's roadmap status.