Skip to content

ShopFloor - Stations

Every station type the system knows about, what it does, what writes to it, and where it sits in the lifecycle.

Read 02-unit-flow.md first for the narrative of how a unit moves through these. This doc is the reference table you skim when you need a specific station.


A StationType is the role (Dock, Triage, Grading, …). A Station is a physical workstation (a scanner + screen) — multiple Stations of the same StationType exist across the facility. A Station belongs to a ProductionFlow (an instance of a Route).

Movement happens when an operator scans a serial number at a Station. The scan dispatcher (ScanUnitControllerService.UpdateWorkTrackingSN) confirms the unit’s next allowed StationType matches the scanned station, then updates WorkTracking.StationID.

See 13-workflow-engine.md for dispatcher mechanics.


CTLShopFloor.Core.Domain/Enums/StationTypeEnum.cs is the canonical list of station-type IDs used in code. Note: many additional station types exist as rows in the StationType database table without enum entries — that’s intentional (the enum holds only the ones business logic explicitly tests for).

Enum valueStationTypeIDDisplay name
Undefined0Undefined
Debox10Debox
Dock12Dock
ImageDownload13Image Download
Grading14Grading
Cleaning15Cleaning
Palletized16Palletized
FinishedGood17FG
RepairCenter19Repair Center
FG_OutOfRoute20FG_OutOfRoute
SalesInventory21Sales Inventory
Shipped22Picking/Shipping
Sold23Sold/Fulfilled
Quarantine29Quarantine
Scrap32Scrap/Recycled
RTV34RTV
Absent35Absent

Triage, Sorting, Kitting, Packing, QA, BER, Harvesting, Recovery, As-Is Shipments, MoveFromWindowsTestSystem, PromoteImageDownloadUnit, StandByPallet, InternalTransfer, and Pallet stations all have controller-services but no enum entry — they’re addressed by name lookup or by service. ⚠️ This is a refactor-finding-worthy inconsistency.

🔧 Refactor finding: StationTypeEnum is partial. Several stations referenced in code (Triage, Kitting, Packing, BER, Harvesting, etc.) have no enum entry, forcing hardcoded StationTypeID == 17-style comparisons or service-name lookups. Either complete the enum or document why specific types are excluded.


Columns:

  • PhaseStationCategory (StationCategoryEnum): Forecast (6), Receiving (7), WIP (8), Pre-FGI (9), FGI (10), Post-FGI (11), Outside-Process (12). ⚠️ Phase assignments below are inferred from controller-service responsibilities — confirm against actual DB rows for your tenant.
  • Owning service — primary controller-service implementing the station’s behavior.
  • Writes — what entities/fields get mutated.
StationEnum IDPhaseOwning serviceInputsWritesNext station
Dock12ReceivingDockStationControllerService, DockAndTriageControllerServiceSerial number + inbound pallet ID; matched against PrealertBolCreates or resets WorkTracking (ArrivedSKU, LabelSKU, InboundPalletIdentifier, ReceivedDate, WorkOrderID, BOMHeaderID). Auto-grades IMC/AS-IS/FLIP types (lines 91–169).Debox or Triage (project-dependent)
Debox10Receiving(none direct — uses general scan service)Serial scanUpdates StationID, LastScanDateSorting or Triage
Sorting— (no enum)ReceivingSortingStationControllerServiceSerial scan + destination typeRoutes by type (normal / AS-IS / IMC / FLIP)Cleaning, Triage, or AS-IS lane
StationEnum IDPhaseOwning serviceInputsWritesNext station
Triage— (no enum)WIPTriageEvaluationService, DockAndTriageControllerServiceCosmetic + Functional questionnaire submissionsTriageEvaluationSubmission (score, grade, JSON, needRepair/needPaint/needRelam flags); TriageErrorRecords; routes to next station based on tenant rules. See 02-unit-flow.md §4.Image Download, Repair Center, Quarantine, or held
Image Download13WIPPromoteImageDownloadUnitControllerServiceSerial scanUpdates StationID. Unit physically leaves shop floor for Windows Test System.(off-floor) → MoveFromWindowsTestSystem
MoveFromWindowsTestSystem— (no enum)WIPMoveFromWindowsTestSystemControllerServiceReturning serial; optionally error code/typeBrings unit back into shop-floor flow; logs UnitNotes with errors if anyCleaning or Repair Center
PromoteImageDownloadUnitWIPPromoteImageDownloadUnitControllerServiceSerial scanUpdates StationID. ⚠️ Naming overlap with Image Download — function unclear, may be re-imaging path.Next route step
Cleaning15WIPCleaningStationControllerServiceSerial scanVerifies WindowsTestResultsUpload exists before allowing advanceGrading
Grading14WIPGradingStationControllerservice (sic — typo’d service)QR scan encoding SKU + gradeSets WorkTracking.GradingID (and optional SubGradingID)Kitting
PrinterCleaningWIPPrinterCleaningControllerService(maintenance)Maintenance station — clean print heads, etc. ⚠️ Not part of unit flow.n/a
PrinterTestingWIPPrinterTestingControllerServiceTest print scanRecords PrinterTest resultsn/a
StationEnum IDPhaseOwning serviceInputsWritesNext station
KittingPre-FGIKittingStationControllerServiceAccessory barcode scans against unit’s KittingBOMOne KittingLog row per scanned KeypartsNumberID (with IsException flag for missing items)Packing
PackingPre-FGIPackingStationControllerServiceSerial scanValidates GradingID is set (when Project.GradingValidation=true); may create BoxPallet for multi-box shipments (SF-220)QA or Pallet
QAPre-FGIQAStationControllerServiceSerial scanFinal inspection. ⚠️ Exact validation rules per project not fully traced.Pallet
StationEnum IDPhaseOwning serviceInputsWritesNext station
Pallet Station / Palletized16FGIPalletStationControllerService, PalletServiceFactory, BasePalletServiceSerial scan + outbound pallet IDSets WorkTracking.OutboundPalletID; auto-generates pallet identifier from PalletPrefixFinished Good
Finished Good (FG)17FGIFinishGoodStationControllerServicePallet close actionOutboundPallets.IsOpen=false, CloseDate set; unit is now FGISales Inventory
FG_OutOfRoute20FGI(ad-hoc)⚠️ Used when a unit reaches FG outside its assigned Route. Confirm semantics.n/a
BoxPalletFGIBoxPalletControllerServiceSerial scan + box labelSub-pallet assignment for multi-box shipments (SF-220)n/a
StationEnum IDPhaseOwning serviceInputsWritesNext station
Sales Inventory21Post-FGI(driven by sales-import jobs)Sales-import matchUnit visible to sales. SentToSalesDate set.Picking/Shipping
Picking/Shipping22Post-FGI(sales-import job updates)Sales-import shipped statusWorkTracking.UnitShippedDate setSold
Sold/Fulfilled23Post-FGI(sales-import job updates)Sales-import sold statusWorkTracking.UnitSoldDate set; SoldFulfilledOrScrapedLog rowTerminal
As-Is ShipmentsPost-FGIAsIsShipmentsControllerServiceSpecial AS-IS pathPer AsIsShipmentsRoutes configuration; ships without refurbishmentTerminal (AS-IS)
Internal TransferPost-FGIInternalTransferStationControllerServiceSerial + destinationInternalTransfer + InternalTransferPallet + InternalTransferSerial rows; unit moves between facilitiesReappears at destination Dock
StationEnum IDPhaseOwning serviceInputsWritesNext station
Repair Center19Outside-ProcessRepairCenterStationControllerServiceSerial scan + error/repair dataRepairCenter, RepairCenterError, RCImages, RCNotes, RCReplacementParts. After 3 failed attempts on same error → BER.Back into route (⚠️ exact entry unclear) or BER
BEROutside-ProcessBERPalletStationControllerServiceTriggered by Repair Center auto-promotionWorkTracking.GradingID = "TYPE BER", LabelSKU marked, StationID = BER stationHarvesting or Scrap
HarvestingOutside-ProcessHarvestingControllerServiceBER unit + list of extracted partsHarvestingEvent, Part rows (Source=“Harvesting”), InventoryTransaction INTerminal for donor; parts enter inventory
RecoveryOutside-ProcessRecoveryControllerService⚠️ Distinction from Harvesting unclearRecoveryEvent (ties to WarehouseID)⚠️ Unclear
Quarantine29Outside-ProcessQuarantineControllerServiceRTV flag from Triage, suspect SKU, etc.Quarantine row + UnitNotes narrativeCan be released back to route
StandByPalletOutside-ProcessStandByPalletStationControllerServiceSerial scanPer-ProductionFlow buffer pallet (StandByPallets.isPallet distinguishes real pallet vs holding area)Released back into route
RTV34Outside-Process(no dedicated service — set via Quarantine path)RTV-flagged option in TriageEffectively Quarantine subtype with vendor-return outcomeTerminal (RTV)
Scrap/Recycled32Outside-Process(terminal — SoldFulfilledOrScrapedLog)Disposition decisionSoldFulfilledOrScrapedLog rowTerminal
Absent35Outside-Process(status flag)Missing-unit reconciliation⚠️ Semantics unclear — may mean “expected but never arrived.”n/a

RMA receipt isn’t a separate station — RMA’d units re-enter at Dock. These services orchestrate the RMA creation itself:

ServicePurpose
RMAControllerServiceIn-system RMA: creates RmaHeader + RmaItemsRelation, resets WorkTracking to Dock.
RmaForOutOfSystemUnitsControllerServiceOut-of-system RMA: stages RmaNotInsystemPreAlert, validates, then materializes new WorkOrder (IsRMA=true) + new WorkTracking rows.
RmaTypesControllerServiceCRUD for RmaTypes lookup.

See 02-unit-flow.md §5.

Administrative / Inventory / Reporting (not unit-flow stations)

Section titled “Administrative / Inventory / Reporting (not unit-flow stations)”

These controller-services don’t sit in the unit flow but are listed because they’re commonly confused with stations:

ServiceWhat it really is
BinLocationControllerServiceInventory bin location management.
LiveInventoryControllerServiceReal-time inventory view.
BinLocationHistory / KeypartLocationHistoryAudit logs for part/bin moves.
KeypartsInventoryControllerService, KeypartLocationControllerServiceKeypart inventory + locations CRUD.
PurchaseOrderControllerService, PurchasingControllerServiceProcurement workflow.
ConsumptionRequestControllerService, ConsumptionRequestItemControllerServicePart consumption requests (⚠️ write-down to inventory is incomplete — see refactor findings).
ProductionFlowControllerService, ProjectsControllerService, RouteControllerService, StationControllerService, StationTypeControllerService, StationCategoryControllerServiceAdmin CRUD for the route/station model.

The dispatcher enforces RouteFlow.ScanOrder strictly — no skipping. To “skip” a station for a particular product, the station must be absent from that Route’s RouteFlow.

Repair Center, BER, Harvesting, Quarantine, StandByPallet, and Recovery are not in any RouteFlow. They’re entered by explicit WorkTracking.StationID reassignment from within a service (e.g., TriageEvaluationService.ProcessItemToStation, RepairCenterStationControllerService.sendToBER).

⚠️ Genuinely unclear how a unit returns from Repair Center / Quarantine / StandByPallet back to the main route. See 02-unit-flow.md §6.2.


5. Per-station data writes — quick reference

Section titled “5. Per-station data writes — quick reference”

When debugging “why is this unit’s record in state X?”, check what station could have written to the field.

WorkTracking fieldSet by
ArrivedSKU, LabelSKU, InboundPalletIdentifier, WorkOrderID, BOMHeaderIDDock
ReceivedDateDock
StationID, LastScanDateEvery scan-based station
GradingID, SubGradingIDDock (auto for IMC/AS-IS/FLIP), Grading station (manual)
SystemInformationBlob, IsSystemInformationBlobSyncedWindows Test System upload
WindowsTestResultBlobWindows Test System upload
ErrorFlagRepair Center on repair completion
OutboundPalletIDPallet Station
BoxPalletIDPacking (when BoxPallet created)
SentToSalesDateSales Inventory transition
UnitShippedDateSales-import job (Picking/Shipping)
UnitSoldDateSales-import job (Sold/Fulfilled)
InTransitInternal Transfer
AcquisitionCostWorkOrderAcquisitionCostJob reconciliation
UnitSalesPriceSales-import job