Files
Joseph Doherty 26ff8d9b4f 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.
2026-01-02 07:43:29 -05:00

9.0 KiB

Search Processing Specification Delta

Purpose

This document captures ADDED and MODIFIED requirements for the search processing subsystem specific to the .NET 10 migration. It supplements the base specification at openspec/specs/search-processing/spec.md.

ADDED Requirements

Requirement: SqlKata Query Builder Integration

The system SHALL use SqlKata fluent query builder instead of T4 text templates for dynamic SQL generation.

Inputs

  • SearchModel containing filter criteria and enriched filter entries
  • SqlServerCompiler for T-SQL generation

Outputs

  • SearchQueryResult record containing:
    • Sql: Parameterized T-SQL query string
    • Parameters: Dictionary of named parameter values
    • TempTableSetupSql: List of temp table creation/population statements

Business Rules

  • SqlKata SqlServerCompiler SHALL be registered as a singleton (thread-safe)
  • All queries SHALL use named parameters (not positional)
  • Parameter names SHALL match legacy convention (@p_* prefix)
  • Generated SQL SHALL produce equivalent results to legacy QueryTemplate.tt

Scenario: Build query with SqlKata

  • WHEN ISearchQueryBuilder.BuildSearchQuery(model) is called
  • THEN SqlKata generates parameterized SQL with named bindings
  • AND the SearchQueryResult.Sql is executable via Dapper
  • AND SearchQueryResult.Parameters contains all TVP parameters

Requirement: Filter Handler Pattern

The system SHALL use a composable filter handler pattern for modular query building.

Inputs

  • SearchModel with active filter criteria
  • SqlServerCompiler for SQL compilation

Outputs

  • FilterResult record containing:
    • SetupSql: List of temp table setup statements
    • Parameters: Dictionary of parameters for this filter

Business Rules

  • Each filter type SHALL have a dedicated IFilterHandler implementation
  • Filter handlers SHALL be registered in dependency injection container
  • Handlers SHALL execute in priority order (lower priority = earlier execution)
  • Handler priorities SHALL ensure dependent temp tables exist before use:
    • WorkOrder: 10
    • ItemNumber: 20
    • ComponentLot: 30
    • ProfitCenter: 40
    • WorkCenter: 50
    • Operator: 60
    • ItemOperationMis: 70
    • Timespan: 80

Scenario: Execute filter handlers in order

  • WHEN search criteria includes work orders, items, and operators
  • THEN WorkOrderFilterHandler executes first (priority 10)
  • AND ItemNumberFilterHandler executes second (priority 20)
  • AND OperatorFilterHandler executes later (priority 60)

Requirement: IAsyncEnumerable Result Streaming

The system SHALL support streaming large result sets using IAsyncEnumerable<T>.

Inputs

  • SearchModel with executed query
  • CancellationToken for cooperative cancellation

Outputs

  • IAsyncEnumerable<SearchResult> streaming results one at a time

Business Rules

  • Streaming SHALL use Dapper's QueryUnbufferedAsync method
  • Cancellation SHALL be supported via [EnumeratorCancellation] attribute
  • Memory allocation SHALL remain constant regardless of result set size
  • Consumer MAY materialize results using ToListAsync() when needed

Scenario: Stream large result set

  • WHEN search returns 10,000 work orders
  • THEN results stream via IAsyncEnumerable<SearchResult>
  • AND memory usage remains constant during enumeration
  • AND await foreach consumes results incrementally

Requirement: Async-First Design

The system SHALL use async methods throughout the search processing pipeline.

Business Rules

  • All repository methods SHALL accept CancellationToken parameter
  • All database operations SHALL use async Dapper methods (QueryAsync, ExecuteAsync)
  • Long-running operations SHALL respect cancellation tokens
  • ISearchProcessor.ExecuteSearchAsync SHALL be the primary entry point
  • WHEN a search is in progress and cancellation is requested
  • THEN the operation throws OperationCanceledException
  • AND database connections are properly disposed

Requirement: Configuration via IOptions Pattern

The system SHALL use IOptions<SearchProcessingOptions> for configuration.

Inputs

  • appsettings.json section: SearchProcessing

Outputs

  • Strongly-typed SearchProcessingOptions injected via DI

Configuration Properties

Property Type Default Description
QueryTimeoutSeconds int 600 SQL query timeout
MaxTraversalIterations int 20 Downstream traversal limit
EnableDebugSql bool false Write SQL to debug files
DebugSqlPath string? null Path for debug SQL files

Scenario: Configure query timeout

  • WHEN SearchProcessingOptions.QueryTimeoutSeconds is set to 900
  • THEN Dapper queries use commandTimeout: 900

Requirement: Service Registration Extension

The system SHALL provide an AddSearchProcessing extension method for DI registration.

Service Lifetimes

Service Lifetime Rationale
SqlServerCompiler Singleton Thread-safe, stateless
IFilterHandler implementations Scoped Per-request state
ISearchQueryBuilder Scoped Uses scoped handlers
ISearchProcessor Scoped Uses scoped repositories
IWorkOrderTraversalService Scoped Uses connection factory

Scenario: Register search processing services

  • WHEN services.AddSearchProcessing(configuration) is called
  • THEN all search processing services are registered
  • AND ISearchProcessor can be resolved from service provider

MODIFIED Requirements

Requirement: Work Order Traversal

The system SHALL execute downstream work order traversal via stored procedure dbo.TraverseWorkOrders instead of inline WHILE loop in generated SQL.

Inputs

  • Active database connection with #Temp_WO temporary table populated
  • Maximum iteration count (default 20)

Outputs

  • Updated #Temp_WO table with downstream work orders flagged

Business Rules

  • IWorkOrderTraversalService.TraverseDownstreamAsync SHALL call stored procedure
  • Stored procedure SHALL contain iterative WHILE loop logic
  • Single stored procedure call SHALL replace 20 inline iterations
  • Transaction scope SHALL be maintained within stored procedure

Scenario: Execute downstream traversal via stored procedure

  • WHEN initial work orders are flagged in #Temp_WO
  • THEN dbo.TraverseWorkOrders stored procedure is called
  • AND downstream work orders are added with PartsList and CARDEX flags
  • AND split orders are detected and flagged

Requirement: Filter Entry Types

The system SHALL use C# record types for filter entry DTOs to provide immutability and value semantics.

Inputs

  • Raw filter values from SearchCriteria
  • Reference data lookups from ILotFinderRepository

Outputs

  • Immutable record instances with output attributes for Excel export

Business Rules

  • All filter entry types SHALL be declared as C# records
  • Records SHALL use primary constructor syntax
  • Output attributes SHALL be applied using [property:] target
  • Records SHALL provide value-based equality for testing

Scenario: Create immutable filter entry record

  • WHEN a WorkOrderFilterEntry is created with WorkOrderNumber 12345 and ItemNumber "ITEM-001"
  • THEN the record is immutable (properties are init-only)
  • AND two records with same values are considered equal

Requirement: SQL Client Package

The system SHALL use Microsoft.Data.SqlClient instead of deprecated System.Data.SqlClient for SQL Server connectivity.

Business Rules

  • All SQL Server connections SHALL use Microsoft.Data.SqlClient.SqlConnection
  • All SQL commands SHALL use Microsoft.Data.SqlClient.SqlCommand
  • NuGet package Microsoft.Data.SqlClient version 5.2+ SHALL be referenced
  • Code SHALL NOT reference System.Data.SqlClient namespace

Scenario: Create SQL connection with modern client

  • WHEN IDbConnectionFactory.CreateLotFinderConnectionAsync is called
  • THEN a Microsoft.Data.SqlClient.SqlConnection instance is returned
  • AND connection supports all modern SQL Server features

Migration Notes

Legacy Pattern New Pattern Status
T4 Text Template SqlKata fluent builder ADDED
Inline WHILE loop Stored procedure MODIFIED
Filter entry classes Record types MODIFIED
Synchronous Dapper Async Dapper MODIFIED
System.Data.SqlClient Microsoft.Data.SqlClient MODIFIED
Static class methods DI-registered services MODIFIED
Newtonsoft.Json System.Text.Json Retained in domain models

Open Questions

None - all design decisions resolved per base specification.