Initial commit: JDE Scoping Tool migration project

Set up repository with legacy .NET Framework 4.8 source (OLD/),
new .NET 10 Blazor solution (NEW/), OpenSpec specifications,
documentation, and project configuration.
This commit is contained in:
Joseph Doherty
2026-01-02 07:43:29 -05:00
commit 26ff8d9b4f
1761 changed files with 596509 additions and 0 deletions
+404
View File
@@ -0,0 +1,404 @@
# SQL Views and Types Specification
## Purpose
This specification defines the SQL views that unify current and historical data across partitioned tables, the table-valued parameter (TVP) types used for efficient bulk filtering in search queries, and an aggregation view for work order scrap totals. These database objects provide the foundation for search query execution and data synchronization status tracking.
## Source Reference
| Legacy File | Purpose |
|-------------|---------|
| OLD/Database/Views/LastDataUpdates.sql | Aggregates latest successful sync timestamps per table/type |
| OLD/Database/Views/WorkOrderTotalScrap.sql | Aggregates scrap quantities per work order |
| OLD/Database/Views/WorkOrder.sql | Union of current and historical work orders |
| OLD/Database/Views/WorkOrderTime.sql | Union of current and historical work order time entries |
| OLD/Database/Views/WorkOrderStep.sql | Union of current and historical work order steps with function code join |
| OLD/Database/Views/WorkOrderComponent.sql | Union of current and historical work order components |
| OLD/Database/Views/LotUsage.sql | Union of current and historical lot usage records |
| OLD/Database/Types/WorkOrderFilterParameter.sql | TVP for filtering by work order numbers |
| OLD/Database/Types/ItemNumberFilterParameter.sql | TVP for filtering by item numbers |
| OLD/Database/Types/ProfitCenterFilterParameter.sql | TVP for filtering by profit center codes |
| OLD/Database/Types/WorkCenterFilterParameter.sql | TVP for filtering by work center codes |
| OLD/Database/Types/OperatorFilterParameter.sql | TVP for filtering by operator user names |
| OLD/Database/Types/ComponentLotFilterParameter.sql | TVP for filtering by component lot/item combinations |
| OLD/Database/Types/ItemOperationMISFilterParameter.sql | TVP for filtering by item/operation/MIS combinations |
## Requirements
### Requirement: LastDataUpdates aggregation view
The system SHALL provide a LastDataUpdates view that aggregates the most recent successful data synchronization timestamps per table and update type.
#### Columns
| Column | Type | Description |
|--------|------|-------------|
| TableName | VARCHAR(50) | Name of the synchronized table |
| MassUpdateDT | DATETIME | Timestamp of last successful mass update (UpdateType=3), defaults to 1970-01-01 |
| DailyUpdateDT | DATETIME | Timestamp of last successful daily update (UpdateType=2), falls back to MassUpdateDT |
| HourlyUpdateDT | DATETIME | Timestamp of last successful hourly update (UpdateType=1), falls back to DailyUpdateDT then MassUpdateDT |
#### Implementation Details
- Uses a CTE with ROW_NUMBER() partitioned by TableName and UpdateType, ordered by StartDT DESC
- Filters to WasSuccessful = 1 records only
- Uses PIVOT to transform UpdateType values (1=Hourly, 2=Daily, 3=Mass) into columns
- Uses COALESCE cascading to provide fallback timestamps when specific update types have not occurred
#### Scenario: Query data freshness status
- **WHEN** an administrator queries the LastDataUpdates view
- **THEN** results show the most recent successful sync timestamp for each table at each update frequency level
#### Scenario: Check if hourly sync is needed
- **WHEN** the data sync service checks HourlyUpdateDT for a table
- **THEN** it receives the most recent of hourly/daily/mass update timestamps to determine staleness
### Requirement: WorkOrderTotalScrap aggregation view
The system SHALL provide a WorkOrderTotalScrap view that calculates the total scrapped quantity per work order from work order steps.
#### Columns
| Column | Type | Description |
|--------|------|-------------|
| WorkOrderNumber | BIGINT | Work order identifier |
| TotalScrappedQuantity | DECIMAL(18,2) | Sum of scrapped quantities, defaults to 0 |
#### Implementation Details
- Aggregates from the WorkOrderStep view (which unions _Curr and _Hist tables)
- Filters to whole-number step numbers only (StepNumber = ROUND(StepNumber, 0))
- Groups by WorkOrderNumber
- Uses COALESCE to return 0 when no scrap exists
#### Scenario: Calculate work order scrap total
- **WHEN** a query joins to WorkOrderTotalScrap for a work order
- **THEN** it receives the sum of all scrapped quantities from that work order's steps
### Requirement: WorkOrder union view
The system SHALL provide a WorkOrder view that unions WorkOrder_Curr and WorkOrder_Hist tables to present all work orders as a single queryable source.
#### Columns
| Column | Type | Source |
|--------|------|--------|
| WorkOrderNumber | BIGINT | Primary key |
| BranchCode | VARCHAR(12) | Branch/plant code |
| LotNumber | VARCHAR(30) | Associated lot number |
| ItemNumber | VARCHAR(25) | Item being produced |
| ShortItemNumber | BIGINT | Numeric item identifier |
| ParentWorkOrderNumber | VARCHAR(8) | Parent work order for split orders |
| OrderQuantity | DECIMAL(15,2) | Ordered quantity |
| HeldQuantity | DECIMAL(15,2) | Quantity on hold |
| ShippedQuantity | DECIMAL(15,2) | Quantity shipped |
| StatusCode | VARCHAR(10) | Work order status |
| StatusCodeUpdateDT | DATETIME | Status last changed |
| IssueDate | DATETIME | Issue date |
| StartDate | DATETIME | Scheduled start date |
| RoutingType | VARCHAR(3) | Routing type code |
| LastUpdateDT | DATETIME | Record last updated |
#### Implementation Details
- Uses UNION ALL to combine WorkOrder_Hist and WorkOrder_Curr
- Selects all columns via wildcard (SELECT hist.*, SELECT curr.*)
- No deduplication logic - assumes _Curr and _Hist are mutually exclusive
#### Scenario: Query all work orders
- **WHEN** a query selects from the WorkOrder view
- **THEN** results include both current and historical work order records
#### Scenario: Search by work order number
- **WHEN** a search filter specifies work order numbers
- **THEN** the query joins WorkOrder view to the filter TVP to match both current and historical records
### Requirement: WorkOrderTime union view
The system SHALL provide a WorkOrderTime view that unions WorkOrderTime_Curr and WorkOrderTime_Hist tables.
#### Columns
| Column | Type | Description |
|--------|------|-------------|
| UniqueID | BIGINT | Primary key |
| WorkOrderNumber | BIGINT | Associated work order |
| StepNumber | DECIMAL(7,2) | Step sequence number |
| WorkCenterCode | VARCHAR(12) | Work center code |
| BranchCode | VARCHAR(12) | Branch/plant code |
| AddressNumber | BIGINT | Operator address number (links to JdeUser) |
| GlDate | DATETIME | General ledger date |
| LastUpdateDT | DATETIME | Record last updated |
#### Implementation Details
- Uses UNION ALL with explicit column list
- AddressNumber column enables join to JdeUser table in search queries (join not in view itself)
#### Scenario: Query operator time entries
- **WHEN** a search filters by operator
- **THEN** search queries join WorkOrderTime view to JdeUser via AddressNumber to match operator time entries
### Requirement: WorkOrderStep union view with function code join
The system SHALL provide a WorkOrderStep view that unions WorkOrderStep_Curr and WorkOrderStep_Hist tables and enriches with function code descriptions.
#### Columns
| Column | Type | Description |
|--------|------|-------------|
| WorkOrderNumber | BIGINT | Associated work order |
| WorkCenterCode | VARCHAR(12) | Work center code |
| StepNumber | DECIMAL(7,2) | Step sequence number |
| StepTypeCode | VARCHAR(2) | Step type code |
| BranchCode | VARCHAR(12) | Branch/plant code |
| StepDescription | VARCHAR(30) | Step description |
| StartDT | DATETIME | Step start timestamp |
| EndDT | DATETIME | Step end timestamp |
| FunctionCode | VARCHAR(15) | Function/operation code |
| FunctionOperationDescription | VARCHAR(MAX) | Description from FunctionCode table |
| ScrappedQuantity | DECIMAL(18,2) | Quantity scrapped at this step |
| LastUpdateDT | DATETIME | Record last updated |
#### Implementation Details
- Uses UNION ALL of _Curr and _Hist in a subquery
- LEFT OUTER JOINs to FunctionCode table on FunctionCode = Code
- Adds FunctionOperationDescription from joined FunctionCode.Description
#### Scenario: Query work order steps with descriptions
- **WHEN** a query selects from WorkOrderStep view
- **THEN** results include enriched function operation descriptions from the FunctionCode reference table
### Requirement: WorkOrderComponent union view
The system SHALL provide a WorkOrderComponent view that unions WorkOrderComponent_Curr and WorkOrderComponent_Hist tables.
#### Columns
| Column | Type | Description |
|--------|------|-------------|
| UniqueID | BIGINT | Primary key |
| WorkOrderNumber | BIGINT | Parent work order |
| LotNumber | VARCHAR(30) | Component lot number |
| BranchCode | VARCHAR(12) | Branch/plant code |
| ShortItemNumber | BIGINT | Component item identifier |
| Quantity | DECIMAL(15,2) | Quantity used |
| LastUpdateDT | DATETIME | Record last updated |
#### Implementation Details
- Uses UNION ALL with wildcard column selection
- Used to trace component lot consumption in work orders
#### Scenario: Trace component lots
- **WHEN** a search filters by component lot numbers
- **THEN** WorkOrderComponent view is queried to find work orders that consumed those lots
### Requirement: LotUsage union view
The system SHALL provide a LotUsage view that unions LotUsage_Curr and LotUsage_Hist tables.
#### Columns
| Column | Type | Description |
|--------|------|-------------|
| UniqueID | BIGINT | Primary key |
| WorkOrderNumber | BIGINT | Associated work order |
| LotNumber | VARCHAR(30) | Lot number used |
| BranchCode | VARCHAR(12) | Branch/plant code |
| ShortItemNumber | BIGINT | Item identifier |
| Quantity | DECIMAL(15,2) | Quantity used |
| LastUpdateDT | DATETIME | Record last updated |
#### Implementation Details
- Uses UNION ALL with wildcard column selection
- Used alongside WorkOrderComponent for complete lot traceability
#### Scenario: Trace lot usage downstream
- **WHEN** a search filters by component lot numbers
- **THEN** LotUsage view is queried alongside WorkOrderComponent to find downstream work orders
### Requirement: WorkOrderFilterParameter TVP type
The system SHALL provide a table-valued parameter type for bulk filtering by work order numbers.
#### Schema
| Column | Type | Nullable |
|--------|------|----------|
| WorkOrderNumber | BIGINT | NULL |
#### Usage Pattern
The application creates a DataTable with WorkOrderNumber column, populates it from search criteria, and passes it as a TVP to search queries:
```csharp
DataTable dataTable = new DataTable();
dataTable.Columns.Add("WorkOrderNumber", typeof(long));
foreach (var entry in model.WorkOrderFilter)
{
dataTable.Rows.Add(entry.WorkOrderNumber);
}
return dataTable.AsTableValuedParameter("WorkOrderFilterParameter");
```
#### Scenario: Filter by specific work orders
- **WHEN** a user specifies work order numbers in search criteria
- **THEN** the system passes a WorkOrderFilterParameter TVP to the query for efficient bulk matching
### Requirement: ItemNumberFilterParameter TVP type
The system SHALL provide a table-valued parameter type for bulk filtering by item numbers.
#### Schema
| Column | Type | Nullable |
|--------|------|----------|
| ItemNumber | VARCHAR(25) | NULL |
#### Usage Pattern
Populated from search criteria item number list and joined to WorkOrder.ItemNumber in search queries.
#### Scenario: Filter by item numbers
- **WHEN** a user specifies item numbers in search criteria
- **THEN** the system passes an ItemNumberFilterParameter TVP for efficient bulk item matching
### Requirement: ProfitCenterFilterParameter TVP type
The system SHALL provide a table-valued parameter type for bulk filtering by profit center codes.
#### Schema
| Column | Type | Nullable |
|--------|------|----------|
| Code | VARCHAR(12) | NULL |
#### Usage Pattern
Profit center codes are expanded to work center codes via OrgHierarchy table join, then used to filter WorkOrderStep/WorkOrderTime records.
#### Scenario: Filter by profit centers
- **WHEN** a user specifies profit centers in search criteria
- **THEN** the system passes a ProfitCenterFilterParameter TVP and expands to work centers via OrgHierarchy
### Requirement: WorkCenterFilterParameter TVP type
The system SHALL provide a table-valued parameter type for bulk filtering by work center codes.
#### Schema
| Column | Type | Nullable |
|--------|------|----------|
| Code | VARCHAR(12) | NULL |
#### Usage Pattern
Joined directly to WorkOrderStep.WorkCenterCode or WorkOrderTime.WorkCenterCode to filter by manufacturing work centers.
#### Scenario: Filter by work centers
- **WHEN** a user specifies work centers in search criteria
- **THEN** the system passes a WorkCenterFilterParameter TVP for direct work center matching
### Requirement: OperatorFilterParameter TVP type
The system SHALL provide a table-valued parameter type for bulk filtering by operator user names.
#### Schema
| Column | Type | Nullable |
|--------|------|----------|
| UserName | VARCHAR(10) | NULL |
#### Usage Pattern
User names are resolved to AddressNumber via JdeUser table join, then matched to WorkOrderTime.AddressNumber to find work orders touched by specific operators.
#### Scenario: Filter by operators
- **WHEN** a user specifies operator IDs in search criteria
- **THEN** the system passes an OperatorFilterParameter TVP and resolves to address numbers via JdeUser
### Requirement: ComponentLotFilterParameter TVP type
The system SHALL provide a table-valued parameter type for bulk filtering by component lot and item number combinations.
#### Schema
| Column | Type | Nullable |
|--------|------|----------|
| ComponentLotNumber | VARCHAR(30) | NULL |
| ItemNumber | VARCHAR(128) | NULL |
#### Usage Pattern
Used to find downstream work orders that consumed specific component lots. The lot/item combination is matched against Lot table, then traced through WorkOrderComponent and LotUsage views.
#### Scenario: Trace component lots to downstream products
- **WHEN** a user specifies component lot numbers in search criteria
- **THEN** the system passes a ComponentLotFilterParameter TVP to trace lot usage through manufacturing
### Requirement: ItemOperationMisFilterParameter TVP type
The system SHALL provide a table-valued parameter type for bulk filtering by item/operation/MIS number/revision combinations.
#### Schema
| Column | Type | Nullable |
|--------|------|----------|
| ItemNumber | VARCHAR(32) | NULL |
| OperationNumber | VARCHAR(32) | NULL |
| MisNumber | VARCHAR(32) | NULL |
| MisRevision | VARCHAR(32) | NULL |
#### Usage Pattern
Used for MIS (Manufacturing Information System) data extraction. The four-part key identifies specific MIS records to match against work order routing and MIS data.
#### Scenario: Filter by MIS specifications
- **WHEN** a user specifies item/operation/MIS criteria
- **THEN** the system passes an ItemOperationMISFilterParameter TVP for MIS data matching and extraction
## Migration Notes
| Legacy Pattern | New Pattern | Rationale |
|----------------|-------------|-----------|
| SELECT * in union views | Explicit column lists | Ensures schema changes are caught at compile time and improves maintainability |
| VARCHAR types in TVPs | Consider NVARCHAR for some columns | Evaluate if Unicode support is needed for international data |
| Multiple TVP types with single-column schemas | Consider consolidation | ProfitCenterFilterParameter and WorkCenterFilterParameter have identical schemas |
| Dapper AsTableValuedParameter | Continue using Dapper or switch to EF Core | TVP support in .NET 10 works well with both Dapper and raw ADO.NET |
## Open Questions
1. Should the union views use UNION (with deduplication) instead of UNION ALL? The current implementation assumes _Curr and _Hist tables are mutually exclusive, but this should be verified during data sync analysis.
2. The ComponentLotFilterParameter uses VARCHAR(128) for ItemNumber while other TVPs and tables use VARCHAR(25). Should this be standardized?
3. Should LastDataUpdates view be replaced with a more flexible query or stored procedure that can report on any update type combination?
## Codex Review Findings
### Issues Fixed
1. ~~**TVP nullability incorrect**~~: Fixed - all TVP columns now show NULL
2. ~~**WorkOrderTime join logic misstated**~~: Fixed - clarified join happens in search queries, not in view
3. ~~**TVP name case mismatch**~~: Fixed - renamed to `ItemOperationMisFilterParameter`
### Remaining Notes
- **WorkOrderTotalScrap datatype**: Spec lists `DECIMAL(18,2)` but SUM without casting returns higher precision (typically `DECIMAL(28,2)`) - acceptable for documentation purposes