ShopFloor - Stations
Station Catalog
Section titled “Station Catalog”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.
1. How stations work
Section titled “1. How stations work”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.
2. The StationTypeEnum
Section titled “2. The StationTypeEnum”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 value | StationTypeID | Display name |
|---|---|---|
Undefined | 0 | Undefined |
Debox | 10 | Debox |
Dock | 12 | Dock |
ImageDownload | 13 | Image Download |
Grading | 14 | Grading |
Cleaning | 15 | Cleaning |
Palletized | 16 | Palletized |
FinishedGood | 17 | FG |
RepairCenter | 19 | Repair Center |
FG_OutOfRoute | 20 | FG_OutOfRoute |
SalesInventory | 21 | Sales Inventory |
Shipped | 22 | Picking/Shipping |
Sold | 23 | Sold/Fulfilled |
Quarantine | 29 | Quarantine |
Scrap | 32 | Scrap/Recycled |
RTV | 34 | RTV |
Absent | 35 | Absent |
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:
StationTypeEnumis partial. Several stations referenced in code (Triage, Kitting, Packing, BER, Harvesting, etc.) have no enum entry, forcing hardcodedStationTypeID == 17-style comparisons or service-name lookups. Either complete the enum or document why specific types are excluded.
3. Catalog — all stations
Section titled “3. Catalog — all stations”Columns:
- Phase —
StationCategory(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.
Receiving (Category 7)
Section titled “Receiving (Category 7)”| Station | Enum ID | Phase | Owning service | Inputs | Writes | Next station |
|---|---|---|---|---|---|---|
| Dock | 12 | Receiving | DockStationControllerService, DockAndTriageControllerService | Serial number + inbound pallet ID; matched against PrealertBol | Creates or resets WorkTracking (ArrivedSKU, LabelSKU, InboundPalletIdentifier, ReceivedDate, WorkOrderID, BOMHeaderID). Auto-grades IMC/AS-IS/FLIP types (lines 91–169). | Debox or Triage (project-dependent) |
| Debox | 10 | Receiving | (none direct — uses general scan service) | Serial scan | Updates StationID, LastScanDate | Sorting or Triage |
| Sorting | — (no enum) | Receiving | SortingStationControllerService | Serial scan + destination type | Routes by type (normal / AS-IS / IMC / FLIP) | Cleaning, Triage, or AS-IS lane |
WIP (Category 8) — main flow
Section titled “WIP (Category 8) — main flow”| Station | Enum ID | Phase | Owning service | Inputs | Writes | Next station |
|---|---|---|---|---|---|---|
| Triage | — (no enum) | WIP | TriageEvaluationService, DockAndTriageControllerService | Cosmetic + Functional questionnaire submissions | TriageEvaluationSubmission (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 Download | 13 | WIP | PromoteImageDownloadUnitControllerService | Serial scan | Updates StationID. Unit physically leaves shop floor for Windows Test System. | (off-floor) → MoveFromWindowsTestSystem |
| MoveFromWindowsTestSystem | — (no enum) | WIP | MoveFromWindowsTestSystemControllerService | Returning serial; optionally error code/type | Brings unit back into shop-floor flow; logs UnitNotes with errors if any | Cleaning or Repair Center |
| PromoteImageDownloadUnit | — | WIP | PromoteImageDownloadUnitControllerService | Serial scan | Updates StationID. ⚠️ Naming overlap with Image Download — function unclear, may be re-imaging path. | Next route step |
| Cleaning | 15 | WIP | CleaningStationControllerService | Serial scan | Verifies WindowsTestResultsUpload exists before allowing advance | Grading |
| Grading | 14 | WIP | GradingStationControllerservice (sic — typo’d service) | QR scan encoding SKU + grade | Sets WorkTracking.GradingID (and optional SubGradingID) | Kitting |
| PrinterCleaning | — | WIP | PrinterCleaningControllerService | (maintenance) | Maintenance station — clean print heads, etc. ⚠️ Not part of unit flow. | n/a |
| PrinterTesting | — | WIP | PrinterTestingControllerService | Test print scan | Records PrinterTest results | n/a |
Pre-FGI (Category 9)
Section titled “Pre-FGI (Category 9)”| Station | Enum ID | Phase | Owning service | Inputs | Writes | Next station |
|---|---|---|---|---|---|---|
| Kitting | — | Pre-FGI | KittingStationControllerService | Accessory barcode scans against unit’s KittingBOM | One KittingLog row per scanned KeypartsNumberID (with IsException flag for missing items) | Packing |
| Packing | — | Pre-FGI | PackingStationControllerService | Serial scan | Validates GradingID is set (when Project.GradingValidation=true); may create BoxPallet for multi-box shipments (SF-220) | QA or Pallet |
| QA | — | Pre-FGI | QAStationControllerService | Serial scan | Final inspection. ⚠️ Exact validation rules per project not fully traced. | Pallet |
FGI (Category 10)
Section titled “FGI (Category 10)”| Station | Enum ID | Phase | Owning service | Inputs | Writes | Next station |
|---|---|---|---|---|---|---|
| Pallet Station / Palletized | 16 | FGI | PalletStationControllerService, PalletServiceFactory, BasePalletService | Serial scan + outbound pallet ID | Sets WorkTracking.OutboundPalletID; auto-generates pallet identifier from PalletPrefix | Finished Good |
| Finished Good (FG) | 17 | FGI | FinishGoodStationControllerService | Pallet close action | OutboundPallets.IsOpen=false, CloseDate set; unit is now FGI | Sales Inventory |
| FG_OutOfRoute | 20 | FGI | (ad-hoc) | — | ⚠️ Used when a unit reaches FG outside its assigned Route. Confirm semantics. | n/a |
| BoxPallet | — | FGI | BoxPalletControllerService | Serial scan + box label | Sub-pallet assignment for multi-box shipments (SF-220) | n/a |
Post-FGI (Category 11)
Section titled “Post-FGI (Category 11)”| Station | Enum ID | Phase | Owning service | Inputs | Writes | Next station |
|---|---|---|---|---|---|---|
| Sales Inventory | 21 | Post-FGI | (driven by sales-import jobs) | Sales-import match | Unit visible to sales. SentToSalesDate set. | Picking/Shipping |
| Picking/Shipping | 22 | Post-FGI | (sales-import job updates) | Sales-import shipped status | WorkTracking.UnitShippedDate set | Sold |
| Sold/Fulfilled | 23 | Post-FGI | (sales-import job updates) | Sales-import sold status | WorkTracking.UnitSoldDate set; SoldFulfilledOrScrapedLog row | Terminal |
| As-Is Shipments | — | Post-FGI | AsIsShipmentsControllerService | Special AS-IS path | Per AsIsShipmentsRoutes configuration; ships without refurbishment | Terminal (AS-IS) |
| Internal Transfer | — | Post-FGI | InternalTransferStationControllerService | Serial + destination | InternalTransfer + InternalTransferPallet + InternalTransferSerial rows; unit moves between facilities | Reappears at destination Dock |
Outside-Process (Category 12)
Section titled “Outside-Process (Category 12)”| Station | Enum ID | Phase | Owning service | Inputs | Writes | Next station |
|---|---|---|---|---|---|---|
| Repair Center | 19 | Outside-Process | RepairCenterStationControllerService | Serial scan + error/repair data | RepairCenter, RepairCenterError, RCImages, RCNotes, RCReplacementParts. After 3 failed attempts on same error → BER. | Back into route (⚠️ exact entry unclear) or BER |
| BER | — | Outside-Process | BERPalletStationControllerService | Triggered by Repair Center auto-promotion | WorkTracking.GradingID = "TYPE BER", LabelSKU marked, StationID = BER station | Harvesting or Scrap |
| Harvesting | — | Outside-Process | HarvestingControllerService | BER unit + list of extracted parts | HarvestingEvent, Part rows (Source=“Harvesting”), InventoryTransaction IN | Terminal for donor; parts enter inventory |
| Recovery | — | Outside-Process | RecoveryControllerService | ⚠️ Distinction from Harvesting unclear | RecoveryEvent (ties to WarehouseID) | ⚠️ Unclear |
| Quarantine | 29 | Outside-Process | QuarantineControllerService | RTV flag from Triage, suspect SKU, etc. | Quarantine row + UnitNotes narrative | Can be released back to route |
| StandByPallet | — | Outside-Process | StandByPalletStationControllerService | Serial scan | Per-ProductionFlow buffer pallet (StandByPallets.isPallet distinguishes real pallet vs holding area) | Released back into route |
| RTV | 34 | Outside-Process | (no dedicated service — set via Quarantine path) | RTV-flagged option in Triage | Effectively Quarantine subtype with vendor-return outcome | Terminal (RTV) |
| Scrap/Recycled | 32 | Outside-Process | (terminal — SoldFulfilledOrScrapedLog) | Disposition decision | SoldFulfilledOrScrapedLog row | Terminal |
| Absent | 35 | Outside-Process | (status flag) | Missing-unit reconciliation | ⚠️ Semantics unclear — may mean “expected but never arrived.” | n/a |
RMA processing stations
Section titled “RMA processing stations”RMA receipt isn’t a separate station — RMA’d units re-enter at Dock. These services orchestrate the RMA creation itself:
| Service | Purpose |
|---|---|
RMAControllerService | In-system RMA: creates RmaHeader + RmaItemsRelation, resets WorkTracking to Dock. |
RmaForOutOfSystemUnitsControllerService | Out-of-system RMA: stages RmaNotInsystemPreAlert, validates, then materializes new WorkOrder (IsRMA=true) + new WorkTracking rows. |
RmaTypesControllerService | CRUD 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:
| Service | What it really is |
|---|---|
BinLocationControllerService | Inventory bin location management. |
LiveInventoryControllerService | Real-time inventory view. |
BinLocationHistory / KeypartLocationHistory | Audit logs for part/bin moves. |
KeypartsInventoryControllerService, KeypartLocationControllerService | Keypart inventory + locations CRUD. |
PurchaseOrderControllerService, PurchasingControllerService | Procurement workflow. |
ConsumptionRequestControllerService, ConsumptionRequestItemControllerService | Part consumption requests (⚠️ write-down to inventory is incomplete — see refactor findings). |
ProductionFlowControllerService, ProjectsControllerService, RouteControllerService, StationControllerService, StationTypeControllerService, StationCategoryControllerService | Admin CRUD for the route/station model. |
4. Special routing considerations
Section titled “4. Special routing considerations”Strict scan order
Section titled “Strict scan order”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.
Branches off the route
Section titled “Branches off the route”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).
Post-branch re-entry
Section titled “Post-branch re-entry”⚠️ 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 field | Set by |
|---|---|
ArrivedSKU, LabelSKU, InboundPalletIdentifier, WorkOrderID, BOMHeaderID | Dock |
ReceivedDate | Dock |
StationID, LastScanDate | Every scan-based station |
GradingID, SubGradingID | Dock (auto for IMC/AS-IS/FLIP), Grading station (manual) |
SystemInformationBlob, IsSystemInformationBlobSynced | Windows Test System upload |
WindowsTestResultBlob | Windows Test System upload |
ErrorFlag | Repair Center on repair completion |
OutboundPalletID | Pallet Station |
BoxPalletID | Packing (when BoxPallet created) |
SentToSalesDate | Sales Inventory transition |
UnitShippedDate | Sales-import job (Picking/Shipping) |
UnitSoldDate | Sales-import job (Sold/Fulfilled) |
InTransit | Internal Transfer |
AcquisitionCost | WorkOrderAcquisitionCostJob reconciliation |
UnitSalesPrice | Sales-import job |
6. Cross-references
Section titled “6. Cross-references”- For how the dispatcher decides what’s next → 13-workflow-engine.md
- For what a unit’s journey actually looks like → 02-unit-flow.md
- For the entities each station mutates → 11-data-model.md
- For background jobs that update station state externally (sales import) → 14-jobs-and-integrations.md