# Tasks: Implement Search Processing ## Phase 1: Project Setup - [x] 001: Create JdeScoping.SearchProcessing project - Location: `NEW/src/JdeScoping.SearchProcessing/JdeScoping.SearchProcessing.csproj` - Dependencies: SqlKata, SqlKata.Execution, Dapper, Microsoft.Data.SqlClient - Validation: `dotnet build` succeeds - [x] 002: Add project reference to JdeScoping.Host - Location: `NEW/src/JdeScoping.Host/JdeScoping.Host.csproj` - Validation: Solution builds with new reference - [x] 003: Create SearchProcessingOptions configuration class - Location: `NEW/src/JdeScoping.SearchProcessing/Configuration/SearchProcessingConfiguration.cs` - Properties: QueryTimeoutSeconds, MaxTraversalIterations, EnableDebugSql, DebugSqlPath - Validation: Options bind from appsettings.json ## Phase 2: Output Attributes - [x] 004: Create OutputColumnAttribute - Location: `NEW/src/JdeScoping.SearchProcessing/Attributes/OutputColumnAttribute.cs` - Properties: Order, HeaderText, Format, AutoWidth, Width, WrapText - Constants: DATE_FORMAT, TIMESTAMP_FORMAT, WRAPPED_COLUMN_WIDTH - Validation: Attribute compiles and is applicable to properties - [x] 005: Create OutputTableAttribute - Location: `NEW/src/JdeScoping.SearchProcessing/Attributes/OutputTableAttribute.cs` - Properties: TabName, TableName, ShowHeader - Validation: Attribute compiles and is applicable to classes/records ## Phase 3: Filter Entry Records - [x] 006: Create WorkOrderFilterEntry record - Location: `NEW/src/JdeScoping.SearchProcessing/Models/FilterEntries/WorkOrderFilterEntry.cs` - Properties: WorkOrderNumber (long), ItemNumber (string) - Include OutputTable and OutputColumn attributes - Validation: Record compiles with proper attributes - [x] 007: Create ItemNumberFilterEntry record - Location: `NEW/src/JdeScoping.SearchProcessing/Models/FilterEntries/ItemNumberFilterEntry.cs` - Properties: ItemNumber, ItemDescription - Validation: Record compiles with proper attributes - [x] 008: Create ProfitCenterFilterEntry record - Location: `NEW/src/JdeScoping.SearchProcessing/Models/FilterEntries/ProfitCenterFilterEntry.cs` - Properties: Code, Description - Validation: Record compiles with proper attributes - [x] 009: Create WorkCenterFilterEntry record - Location: `NEW/src/JdeScoping.SearchProcessing/Models/FilterEntries/WorkCenterFilterEntry.cs` - Properties: Code, Description - Validation: Record compiles with proper attributes - [x] 010: Create OperatorFilterEntry record - Location: `NEW/src/JdeScoping.SearchProcessing/Models/FilterEntries/OperatorFilterEntry.cs` - Properties: AddressNumber (long), UserID, FullName - Validation: Record compiles with proper attributes - [x] 011: Create ComponentLotFilterEntry record - Location: `NEW/src/JdeScoping.SearchProcessing/Models/FilterEntries/ComponentLotFilterEntry.cs` - Properties: LotNumber, ItemNumber - Validation: Record compiles with proper attributes - [x] 012: Create ItemOperationMisFilterEntry record - Location: `NEW/src/JdeScoping.SearchProcessing/Models/FilterEntries/ItemOperationMisFilterEntry.cs` - Properties: ItemNumber, OperationNumber, MisNumber, MisRevision - Validation: Record compiles with proper attributes ## Phase 4: Result Records - [x] 013: Create SearchResult record - Location: `NEW/src/JdeScoping.SearchProcessing/Models/Results/SearchResult.cs` - Source: `OLD/WorkerService/Models/Reporting/SearchResult.cs` - Include all OutputColumn attributes matching legacy - Include computed InclusionReason property - Validation: All 18 output columns present with correct attributes - [x] 014: Create MisSearchResult record - Location: `NEW/src/JdeScoping.SearchProcessing/Models/Results/MisSearchResult.cs` - Source: `OLD/WorkerService/Models/Reporting/MisSearchResult.cs` - Validation: All MIS-related columns present - [x] 015: Create MisNonMatchSearchResult record - Location: `NEW/src/JdeScoping.SearchProcessing/Models/Results/MisNonMatchSearchResult.cs` - Source: `OLD/WorkerService/Models/Reporting/MisNonMatchSearchResult.cs` - Include: WasJobStepAdded, MatchedJobStepNumber columns - Validation: All non-match columns present ## Phase 5: SearchModel and Extensions - [x] 016: Create SearchModel class - Location: `NEW/src/JdeScoping.SearchProcessing/Models/SearchModel.cs` - Source: `OLD/WorkerService/Models/Reporting/SearchModel.cs` - Include all filter collections and computed *Enabled properties - Include Results, MisResults, MisNonMatchResults collections - Validation: All filter enabled properties work correctly - [x] 017: Create SearchQueryResult record - Location: `NEW/src/JdeScoping.SearchProcessing/Models/SearchQueryResult.cs` - Properties: Sql, Parameters, TempTableSetupSql - Validation: Record compiles - [x] 018: Create TableValuedParameterExtensions - Location: `NEW/src/JdeScoping.SearchProcessing/Extensions/TableValuedParameterExtensions.cs` - Methods: Create*FilterParameter for all 7 filter types - Source: `OLD/WorkerService/Helpers/SearchModelHelpers.cs` - Validation: All TVP methods compile and match legacy schema - [x] 019: Create SearchModelExtensions - Location: `NEW/src/JdeScoping.SearchProcessing/Extensions/SearchModelExtensions.cs` - Methods: ShouldSearchSteps, ToSearchModel (from Search entity) - Source: `OLD/WorkerService/Helpers/SearchModelHelpers.cs` - Validation: ShouldSearchSteps logic matches legacy ## Phase 6: Query Builder Interfaces - [x] 020: Create IFilterHandler interface - Location: `NEW/src/JdeScoping.SearchProcessing/Interfaces/IFilterHandler.cs` - Methods: IsEnabled, Apply, Priority property - Validation: Interface compiles - [x] 021: Create FilterResult record - Location: `NEW/src/JdeScoping.SearchProcessing/Models/FilterResult.cs` - Properties: SetupSql (IReadOnlyList), Parameters (IDictionary) - Validation: Record compiles - [x] 022: Create ISearchQueryBuilder interface - Location: `NEW/src/JdeScoping.SearchProcessing/Interfaces/ISearchQueryBuilder.cs` - Methods: BuildSearchQuery, BuildMisQuery, BuildMisNonMatchQuery - Validation: Interface compiles ## Phase 7: Filter Handlers - [x] 023: Create FilterHandlerBase abstract class - Location: `NEW/src/JdeScoping.SearchProcessing/FilterHandlers/FilterHandlerBase.cs` - Common functionality for all handlers - Validation: Abstract class compiles - [x] 024: Create WorkOrderFilterHandler - Location: `NEW/src/JdeScoping.SearchProcessing/FilterHandlers/WorkOrderFilterHandler.cs` - Source: QueryTemplate.tt lines 26-96 - Generates: MERGE #Temp_WO with ManuallySpecified flag, split order detection - Validation: Unit test verifies SQL structure - [x] 025: Create ItemNumberFilterHandler - Location: `NEW/src/JdeScoping.SearchProcessing/FilterHandlers/ItemNumberFilterHandler.cs` - Source: QueryTemplate.tt lines 48-64 - Generates: #P_ItemNumbers temp table - Validation: Unit test verifies SQL structure - [x] 026: Create ProfitCenterFilterHandler - Location: `NEW/src/JdeScoping.SearchProcessing/FilterHandlers/ProfitCenterFilterHandler.cs` - Source: QueryTemplate.tt lines 65-89 - Generates: #P_WorkCenters temp table via OrgHierarchy join - Validation: Unit test verifies SQL structure - [x] 027: Create WorkCenterFilterHandler - Location: `NEW/src/JdeScoping.SearchProcessing/FilterHandlers/WorkCenterFilterHandler.cs` - Source: QueryTemplate.tt lines 90-102 - Generates: MERGE into #P_WorkCenters - Validation: Unit test verifies SQL structure - [x] 028: Create OperatorFilterHandler - Location: `NEW/src/JdeScoping.SearchProcessing/FilterHandlers/OperatorFilterHandler.cs` - Source: QueryTemplate.tt lines 147-172 - Generates: #P_OperatorIDs temp table with JdeUser lookup - Validation: Unit test verifies SQL structure - [x] 029: Create ComponentLotFilterHandler - Location: `NEW/src/JdeScoping.SearchProcessing/FilterHandlers/ComponentLotFilterHandler.cs` - Source: QueryTemplate.tt lines 103-146 - Generates: WorkOrderComponent/LotUsage joins, CARDEX flag - Validation: Unit test verifies SQL structure - [x] 030: Create ItemOperationMisFilterHandler - Location: `NEW/src/JdeScoping.SearchProcessing/FilterHandlers/ItemOperationMisFilterHandler.cs` - Source: QueryTemplate.tt lines 173-198 - Generates: #P_PartOperations temp table - Validation: Unit test verifies SQL structure - [x] 031: Create TimespanFilterHandler - Location: `NEW/src/JdeScoping.SearchProcessing/FilterHandlers/TimespanFilterHandler.cs` - Source: QueryTemplate.tt lines 254-258 - Generates: WHERE clause with @p_MinimumDT/@p_MaximumDT - Business rule: Requires BOTH min and max for combined condition - Validation: Unit test verifies SQL structure ## Phase 8: Query Builder Implementation - [x] 032: Create SqlKataSearchQueryBuilder - Location: `NEW/src/JdeScoping.SearchProcessing/QueryBuilders/SqlKataSearchQueryBuilder.cs` - Orchestrates filter handlers - Builds #Temp_WO setup, downstream traversal call, final SELECT - Source: QueryTemplate.tt full template - Validation: Generated SQL matches legacy structure - [x] 033: Create MisQueryBuilder - Location: `NEW/src/JdeScoping.SearchProcessing/QueryBuilders/MisQueryBuilder.cs` - Builds MIS extraction queries (MIS_CTE, #TempMisData) - Source: QueryTemplate.tt lines 353-482 - Note: MIS extraction does NOT join #Temp_WO - Validation: Generated SQL matches legacy structure ## Phase 9: Services - [x] 034: Create ISearchProcessor interface - Note: Existing interface at `NEW/src/JdeScoping.Core/Interfaces/ISearchProcessor.cs` - Methods: ExecuteSearchAsync (IAsyncEnumerable), ExecuteSearchToModelAsync - Validation: Interface compiles - [x] 035: Create IWorkOrderTraversalService interface - Location: `NEW/src/JdeScoping.SearchProcessing/Interfaces/IWorkOrderTraversalService.cs` - Method: TraverseDownstreamAsync - Validation: Interface compiles - [x] 036: Create WorkOrderTraversalService - Location: `NEW/src/JdeScoping.SearchProcessing/Services/WorkOrderTraversalService.cs` - Calls dbo.TraverseWorkOrders stored procedure - Executes WHILE loop logic for downstream work orders - Source: QueryTemplate.tt lines 285-349 - Validation: Service compiles, stored procedure exists - [x] 037: Create SearchProcessor service - Location: `NEW/src/JdeScoping.SearchProcessing/Services/SearchProcessor.cs` - Constructor: IDbConnectionFactory, ISearchQueryBuilder, IWorkOrderTraversalService, ILotFinderRepository, ILogger - Implements full search flow: 1. Enrich filter entries via repository lookups 2. Build query via SqlKata 3. Execute temp table setup 4. Call downstream traversal 5. Execute result query 6. Optionally extract MIS data - Validation: Service compiles, all dependencies injected ## Phase 10: Service Registration - [x] 038: Create ServiceCollectionExtensions - Location: `NEW/src/JdeScoping.SearchProcessing/ServiceCollectionExtensions.cs` - Method: AddSearchProcessing(IServiceCollection, IConfiguration) - Registers: Options, SqlServerCompiler (singleton), filter handlers (scoped), services (scoped) - Validation: Services resolve correctly at runtime - [x] 039: Register search processing in Program.cs - Location: `NEW/src/JdeScoping.Host/Program.cs` - Note: Updated to use SearchProcessing module's AddSearchProcessing; renamed Core's method to AddSearchProcessingOptions - Validation: Application starts without DI errors ## Phase 11: Unit Tests - [x] 040: Create test project - Location: `NEW/tests/JdeScoping.SearchProcessing.Tests/JdeScoping.SearchProcessing.Tests.csproj` - Dependencies: xUnit, Shouldly, NSubstitute - Validation: Test project builds - [x] 041: Write WorkOrderFilterHandler tests - Location: `NEW/tests/JdeScoping.SearchProcessing.Tests/FilterHandlers/WorkOrderFilterHandlerTests.cs` - Test: IsEnabled returns correct value - Test: Generated SQL contains MERGE and ManuallySpecified - Validation: All tests pass (7 tests) - [x] 042: Write ComponentLotFilterHandler tests - Location: `NEW/tests/JdeScoping.SearchProcessing.Tests/FilterHandlers/ComponentLotFilterHandlerTests.cs` - Test: IsEnabled returns correct value - Test: Generated SQL contains WorkOrderComponent join - Test: CARDEX flag is set (not PartsList) - Validation: All tests pass (9 tests) - [x] 043: Write SqlKataSearchQueryBuilder tests - Location: `NEW/tests/JdeScoping.SearchProcessing.Tests/QueryBuilders/SqlKataSearchQueryBuilderTests.cs` - Test: Empty filters produces minimal query - Test: Single filter produces correct structure - Test: Multiple filters combine correctly - Validation: All tests pass (10 tests) - [x] 044: Write TableValuedParameterExtensions tests - Location: `NEW/tests/JdeScoping.SearchProcessing.Tests/Extensions/TableValuedParameterExtensionsTests.cs` - Test: Each Create*Parameter method produces correct DataTable schema - Test: Empty collections produce empty DataTables - Validation: All tests pass (17 tests) - [x] 045: Write SearchResult tests - Location: `NEW/tests/JdeScoping.SearchProcessing.Tests/Models/SearchResultTests.cs` - Test: InclusionReason returns correct values for all flag combinations - Test: ManuallySpecified takes priority over Flagged - Test: Unknown returned when no flags set - Validation: All tests pass (21 tests) ## Phase 12: Verification - [x] 046: Run full test suite - Command: `dotnet test NEW/tests/JdeScoping.SearchProcessing.Tests/` - Validation: All 64 tests pass - [x] 047: Verify solution builds - Command: `dotnet build NEW/JdeScoping.sln` - Validation: No errors or warnings - [x] 048: Run OpenSpec validation - Command: `openspec validate implement-search-processing --strict` - Validation: No validation errors - "Change 'implement-search-processing' is valid" - [x] 049: Codex MCP review of query builder output - SqlKataSearchQueryBuilder generates SQL matching legacy QueryTemplate.tt structure - Key features verified: #Temp_WO creation, MERGE statements, filter handler priority ordering - Validation: SQL structure matches legacy implementation