Files
jdescopingtool/openspec/specs/sql-business-logic/spec.md
T
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

12 KiB

SQL Business Logic Specification

Purpose

This specification documents stored procedures and functions that implement database-level business logic for the search processing workflow. These SQL objects manage the lifecycle of search requests (submission, execution, completion) and provide complex matching logic for Manufacturing Information System (MIS) data.

Source Reference

Legacy File Purpose
OLD/Database/StoredProcedures/SubmitSearch.sql Create new search record with Queued status
OLD/Database/StoredProcedures/StartSearch.sql Transition search to Processing status
OLD/Database/StoredProcedures/CompleteSearch.sql Finalize search with results or failure
OLD/Database/StoredProcedures/ResetPartialSearches.sql Recovery procedure for stuck searches
OLD/Database/Functions/MatchMis.sql MIS data matching based on routing/master

Requirements

Requirement: Submit search procedure

The system SHALL provide a SubmitSearch stored procedure that creates new search records in the database.

Inputs

  • @p_UserName (VARCHAR(128)) - Username of the person submitting the search
  • @p_Name (VARCHAR(128)) - User-provided name/description for the search
  • @p_Criteria (VARCHAR(MAX)) - JSON-serialized search criteria

Outputs

  • @o_SearchID (INT OUTPUT) - The auto-generated ID of the newly created search record

Business Rules

  • The procedure SHALL insert a new record into the Search table
  • Status SHALL be set to 1 (Queued) for all new searches
  • SubmitDT SHALL be set to the current date/time via GETDATE()
  • The new SearchId SHALL be retrieved using SCOPE_IDENTITY() to ensure the correct ID in concurrent scenarios
  • WHEN SubmitSearch is called with valid username, search name, and criteria
  • THEN a new Search record is inserted with Status = 1 (Queued)
  • AND SubmitDT is set to the current timestamp
  • AND the new SearchId is returned via the @o_SearchID OUTPUT parameter

Scenario: Concurrent search submissions

  • WHEN multiple users submit searches simultaneously
  • THEN each call returns the correct SearchId via SCOPE_IDENTITY()
  • AND no cross-session ID contamination occurs

Requirement: Start search procedure

The system SHALL provide a StartSearch stored procedure that marks a search as being actively processed.

Inputs

  • @p_SearchID (INT) - The ID of the search to start processing

Outputs

  • None (procedure updates record in place)

Business Rules

  • The procedure SHALL update the Status to 2 (Processing)
  • The procedure SHALL set StartDT to the current date/time via GETDATE()
  • Only the search record matching the provided ID SHALL be updated
  • WHEN StartSearch is called with a valid SearchID
  • THEN the search Status is updated to 2 (Processing)
  • AND StartDT is set to the current timestamp

Requirement: Complete search procedure

The system SHALL provide a CompleteSearch stored procedure that finalizes a search with results or failure status.

Inputs

  • @p_SearchID (INT) - The ID of the search to complete
  • @p_WasSuccessful (BIT) - Flag indicating success (1) or failure (0)
  • @p_Results (VARBINARY(MAX)) - Binary Excel file data (may be NULL on failure)

Outputs

  • None (procedure updates record in place)

Business Rules

  • When @p_WasSuccessful = 1, Status SHALL be set to 3 (Complete)
  • When @p_WasSuccessful = 0, Status SHALL be set to 4 (Failed)
  • The Results column SHALL be updated with the provided binary data
  • EndDT SHALL be set to the current date/time via GETDATE()
  • WHEN CompleteSearch is called with WasSuccessful = 1 and Excel binary data
  • THEN the search Status is updated to 3 (Complete)
  • AND the Results column contains the Excel binary
  • AND EndDT is set to the current timestamp
  • WHEN CompleteSearch is called with WasSuccessful = 0
  • THEN the search Status is updated to 4 (Failed)
  • AND EndDT is set to the current timestamp

Requirement: Reset partial searches procedure

The system SHALL provide a ResetPartialSearches stored procedure that recovers searches stuck in a processing state.

Inputs

  • None (parameterless procedure)

Outputs

  • None (procedure updates records in place)

Business Rules

  • The procedure SHALL identify searches where StartDT IS NOT NULL AND EndDT IS NULL
  • These searches represent work that was started but never completed (e.g., service crash)
  • Status SHALL be reset to 1 (Queued) for all identified searches
  • StartDT SHALL be set to NULL to allow re-processing

Scenario: Service restart recovery

  • WHEN the worker service starts and calls ResetPartialSearches
  • THEN all searches with StartDT set but EndDT NULL are reset
  • AND Status is changed back to 1 (Queued)
  • AND StartDT is cleared to NULL
  • AND these searches become eligible for re-processing

Scenario: No stuck searches

  • WHEN ResetPartialSearches is called with no searches in partial state
  • THEN no records are modified

Requirement: MIS matching function

The system SHALL provide a MatchMIS table-valued function that correlates work order operations with Manufacturing Information System (MIS) quality documents.

Inputs

  • @workOrderNumber (BIGINT) - Work order number to match
  • @itemNumber (VARCHAR(25)) - Item/part number
  • @branchCode (VARCHAR(12)) - Branch/plant code
  • @routingType (VARCHAR(3)) - Routing type identifier
  • @issueDate (DATETIME) - Issue date for routing validity
  • @workCenterCode (VARCHAR(12)) - Work center identifier
  • @sequenceNumber (DECIMAL(7,2)) - Operation sequence number
  • @steptimestamp (DATETIME) - Timestamp of the operation step
  • @functionCode (VARCHAR(15)) - Function/operation code
  • @functionOperationDescription (VARCHAR(80)) - Description of the operation

Outputs

Returns a table with the following columns:

  • WorkOrderNumber, ItemNumber, ItemDescription, BranchCode, WorkCenterCode
  • StepTimestamp, SequenceNumber, FunctionCode, FunctionOperationDescription
  • MatchedSequenceNumber (DECIMAL(7,2)) - Sequence number used for MIS lookup
  • RoutingMatch (BIT) - Whether match came from work order routing
  • MasterMatch (BIT) - Whether match came from route master
  • MisNumber, RevID, CharNumber, MisSequenceNumber (VARCHAR(32)) - MIS document identifiers
  • TestDescription, ToolsGauges, WorkInstructions (VARCHAR(2000)) - MIS content
  • SamplingType, SamplingValue, Status (VARCHAR(32)) - MIS metadata
  • ReleaseDate (DATETIME) - MIS document release date

Business Rules

  1. Parent Work Order Resolution: The function SHALL resolve to the parent work order number if available (using TRY_CONVERT to handle non-numeric parent references)

  2. Sequence Number Alias Discovery: The function SHALL find alias sequence numbers using a two-tier approach:

    • First, check WorkOrderRouting (F3112Z1) for matches on work center and function code using the earliest transaction date
    • If no routing matches exist, check RouteMaster (F3003) for matches within the issue date validity range
  3. MIS Matching Priority: The function SHALL attempt MIS matching in priority order:

    • First priority: Match MisData records with Status = 'Current' where steptimestamp falls within ReleaseDate to ObsoleteDate
    • Second priority: Match MisData records with Status = 'BackLevel' where ReleaseDate falls between issueDate and steptimestamp
    • Third priority: Return alias information without MIS data if aliases exist but no MIS match
    • Fourth priority: Return input parameters with NULL matched sequence and both match flags = 0
  4. Item Description Lookup: The function SHALL lookup and include the item description from the Item table

  5. Date Range Handling: NULL ReleaseDate SHALL be treated as '1970-01-01', NULL ObsoleteDate SHALL be treated as '2029-01-01'

Scenario: Match via work order routing with current MIS

  • WHEN MatchMIS is called for a work order with routing data
  • AND a current MIS document exists for the matched sequence
  • THEN results include RoutingMatch = 1 and full MIS details
  • AND MasterMatch indicates whether route master also matched

Scenario: Match via route master when no routing exists

  • WHEN MatchMIS is called for a work order without specific routing
  • AND a route master entry exists for the item/branch/work center
  • THEN results include MasterMatch = 1 and RoutingMatch = 0
  • AND MIS details are included if available

Scenario: BackLevel MIS fallback

  • WHEN no current MIS document matches
  • AND a BackLevel MIS document exists with ReleaseDate in the valid range
  • THEN results include the BackLevel MIS details with Status = 'BackLevel'

Scenario: No MIS match found

  • WHEN no MIS documents match the routing or master sequence
  • THEN results include the input parameters with alias information
  • AND MIS-specific columns are NULL

Scenario: No routing or master match

  • WHEN no work order routing or route master entries match
  • THEN results include input parameters only
  • AND MatchedSequenceNumber is NULL
  • AND RoutingMatch = 0 and MasterMatch = 0

Search Status Codes

Code Name Description
1 Queued Search submitted, awaiting processing
2 Processing Search actively being executed
3 Complete Search finished successfully with results
4 Failed Search encountered an error

State Transition Diagram

[New Search]
     |
     v
 SubmitSearch
     |
     v
 +-------+
 |Queued |<---------+
 |  (1)  |          |
 +---+---+          |
     |              |
     v              |
 StartSearch    ResetPartialSearches
     |              |
     v              |
 +----------+       |
 |Processing|-------+
 |   (2)    |
 +----+-----+
      |
      v
 CompleteSearch
      |
      +---------------+
      |               |
      v               v
 +--------+      +------+
 |Complete|      |Failed|
 |  (3)   |      | (4)  |
 +--------+      +------+

Migration Notes

Legacy Pattern New Pattern Rationale
Status as INT codes (1,2,3,4) Consider enum type or constants Improves readability and type safety
SCOPE_IDENTITY() for new ID EF Core auto-populates Id on SaveChanges Framework handles identity retrieval
Stored procedures for state transitions Entity state management with domain events Enables better testability and event sourcing
VARBINARY(MAX) for Excel storage Consider cloud blob storage reference Reduces database size, enables streaming
Table-valued function for MIS matching LINQ query or stored procedure Evaluate performance tradeoffs

Decisions Made

  • MatchMIS migration: Keep as SQL function - proven logic, better performance for large datasets
  • Domain events: Yes, emit events on status transitions - enables audit trail and future event sourcing
  • Excel storage: Keep in database VARBINARY - match legacy, simpler deployment
  • Reset timeout: No timeout - match legacy behavior, reset any search with StartDT but no EndDT

Codex Review Findings

Medium Priority

  1. State transitions lack validation: Legacy procedures update by ID without checking current Status. ResetPartialSearches uses StartDT/EndDT presence, not Status value. The spec's state diagram implies stricter transitions than implemented.
  2. MatchMIS alias discovery incomplete: RouteMaster is still merged when routing aliases exist (to set MasterMatch on existing sequences). Routing uses earliest transaction date for entire work order which may skip later matches.
  3. MatchMIS truncation: Alias sequence numbers are cast to INT before string compare, which is a lossy conversion not documented in the spec.

Low Priority

  1. CompleteSearch NULL behavior: When @Success is NULL, SQL treats it as failure (Status=4) and still overwrites Results. This edge case is undocumented.
  2. Output column order: MatchMIS columns in spec differ from SQL (SamplingType/SamplingValue vs ToolsGauges/WorkInstructions position) - may matter for ordinal access.