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.5 KiB

Tasks: Implement Excel Export

Phase 1: Project Setup

  • Create JdeScoping.ExcelExport project

    • Location: NEW/src/JdeScoping.ExcelExport/JdeScoping.ExcelExport.csproj
    • Target: net10.0
    • Validation: Project builds successfully
    • Dependencies: JdeScoping.Core (for base models)
  • Add NuGet package references

    • Packages: ClosedXML, Microsoft.Extensions.Options, Microsoft.Extensions.Logging.Abstractions, Microsoft.Extensions.Configuration.Abstractions
    • Validation: dotnet restore succeeds
  • Create folder structure

    • Folders: Attributes/, Configuration/, Generators/, Formatting/, Helpers/, Models/, Interfaces/
    • Validation: Directories exist

Phase 2: Attributes and Configuration

  • Create OutputColumnAttribute class

    • Location: Attributes/OutputColumnAttribute.cs
    • Properties: Order, HeaderText, Format, AutoWidth, Width, WrapText
    • Constants: STD_FORMAT, DATE_FORMAT, TIMESTAMP_FORMAT, WRAPPED_COLUMN_WIDTH
    • Validation: Class compiles, matches legacy signature
  • Create OutputTableAttribute class

    • Location: Attributes/OutputTableAttribute.cs
    • Properties: TabName, TableName, ShowHeader
    • Validation: Class compiles, matches legacy signature
  • Create ExcelExportOptions class

    • Location: Configuration/ExcelExportOptions.cs
    • Properties: CriteriaSheetPassword, DataSheetPassword
    • Const: SectionName = "ExcelExport"
    • Validation: Class compiles with default values

Phase 3: Helper Classes

  • Create OutputColumn model

    • Location: Models/OutputColumn.cs
    • Properties: Name, Property (PropertyInfo), Attribute (OutputColumnAttribute)
    • Validation: Class compiles
  • Create OutputColumnCache class

    • Location: Helpers/OutputColumnCache.cs
    • Pattern: ConcurrentDictionary for type-to-columns mapping
    • Method: GetColumns() returns IReadOnlyList
    • Validation: Cache correctly caches and retrieves column metadata

Phase 4: Formatting Utilities

  • Create HeaderFormatter static class

    • Location: Formatting/HeaderFormatter.cs
    • Methods: ApplyHeaderFormat(IXLCell, string?), ApplyHeaderFormat(IXLRange, string?, bool merge)
    • Style: Bold, centered, Gainsboro background
    • Validation: Unit tests verify cell styling
  • Create ColumnFormatter static class

    • Location: Formatting/ColumnFormatter.cs
    • Methods: ApplyColumnFormat(IXLColumn, OutputColumnAttribute)
    • Handles: Auto-fit with padding, wrapped text, number formats
    • Constants: ExcelFormats class with format strings
    • Validation: Unit tests verify column formatting
  • Create WorksheetProtector class

    • Location: Formatting/WorksheetProtector.cs
    • Method: ApplyProtection(IXLWorksheet, string password)
    • Configures: AllowElement for filter, sort, format operations
    • Validation: Protected sheet allows specified operations

Phase 5: Sheet Generators

  • Create AttributeTableWriter class

    • Location: Generators/AttributeTableWriter.cs
    • Dependencies: OutputColumnCache
    • Method: WriteTable(worksheet, startRow, startCol, data, tableNameOverride?)
    • Features: Header row, data rows, Light18 table style, column formatting
    • Validation: Generated table matches expected structure
  • Create CriteriaSheetGenerator class

    • Location: Generators/CriteriaSheetGenerator.cs
    • Dependencies: IOptions
    • Method: Generate(XLWorkbook, SearchModel)
    • Features: Search info, timestamps, filter tables, MIS indicator, protection
    • Validation: Sheet matches legacy criteria sheet structure
  • Create DataEntryTemplateGenerator class

    • Location: Generators/DataEntryTemplateGenerator.cs
    • Methods: Generate(data, headerText), Generate(data[][], headers[])
    • Features: Single/multi-column templates, text format, header styling
    • Validation: Generated templates match legacy output

Phase 6: Service Interface and Implementation

  • Create IExcelExportService interface

    • Location: Interfaces/IExcelExportService.cs
    • Method: Task<byte[]> GenerateAsync(SearchModel, CancellationToken)
    • Validation: Interface compiles
  • Create ExcelExportService class

    • Location: ExcelExportService.cs
    • Dependencies: ILogger, IOptions, OutputColumnCache, AttributeTableWriter
    • Validation: Class compiles
  • Implement GenerateAsync method

    • Creates XLWorkbook
    • Generates criteria sheet (always)
    • Generates results sheet (always)
    • Generates MIS Info sheet (conditional)
    • Generates Investigation sheet (conditional)
    • Returns byte[] via MemoryStream
    • Validation: All sheet types generated correctly
  • Implement Search Criteria sheet generation

    • Uses CriteriaSheetGenerator
    • Filter tables with 2 blank row spacing
    • Auto-fit columns with 15% padding
    • Criteria sheet password protection
    • Validation: Matches legacy criteria sheet
  • Implement Search Results sheet generation

    • Uses AttributeTableWriter with SearchResult model
    • 19 columns per spec
    • Auto-fit with 30% padding
    • Light18 table style
    • Data sheet password protection
    • Validation: Matches legacy results sheet
  • Implement MIS Info sheet generation

    • Uses AttributeTableWriter with MisSearchResult model
    • 19 columns per spec
    • Wrapped columns (Test Description, Tools & Gauges, Work Instructions) with fixed 65-char width
    • Other columns: auto-fit with 30% padding
    • Null check: skip if MisResults is null
    • Validation: Matches legacy MIS Info sheet
  • Implement Investigation sheet generation

    • Uses AttributeTableWriter with MisNonMatchSearchResult model
    • 12 columns per spec
    • Date columns with DATE_FORMAT
    • Auto-fit with 30% padding
    • Null check: skip if MisNonMatchResults is null
    • Validation: Matches legacy Investigation sheet

Phase 7: Logging and Error Handling

  • Implement structured logging

    • Use BeginScope with SearchId, SearchName
    • Log export start, sheet generation, completion
    • Log warnings for empty result sets
    • Validation: Log messages include search context
  • Implement cancellation support

    • Check CancellationToken before each sheet
    • Wrap workbook generation in Task.Run
    • Throw OperationCanceledException on cancellation
    • Validation: Long exports can be cancelled

Phase 8: Service Registration

  • Create ServiceCollectionExtensions class
    • Location: ServiceCollectionExtensions.cs
    • Method: AddExcelExport(this IServiceCollection, IConfiguration)
    • Registers: ExcelExportOptions, IExcelExportService (scoped), helpers (singleton)
    • Validation: Services resolved correctly from DI

Phase 9: Unit Tests

  • Create test project

    • Location: NEW/tests/JdeScoping.ExcelExport.Tests/JdeScoping.ExcelExport.Tests.csproj
    • Dependencies: xUnit, Shouldly, NSubstitute, ClosedXML
    • Validation: Project builds
  • Create OutputColumnCacheTests

    • Tests: Column caching, ordering by Order property, tie-breaking by name
    • Validation: Tests pass
  • Create HeaderFormatterTests

    • Tests: Cell formatting, range formatting, merge behavior
    • Validation: Tests pass
  • Create ColumnFormatterTests

    • Tests: Auto-fit with padding, wrapped text, number formats
    • Validation: Tests pass
  • Create WorksheetProtectorTests

    • Tests: Protection application, allowed operations
    • Validation: Tests pass
  • Create AttributeTableWriterTests

    • Tests: Table generation, column ordering, styling
    • Validation: Tests pass
  • Create CriteriaSheetGeneratorTests

    • Tests: Sheet structure, filter tables, timestamps
    • Validation: Tests pass
  • Create ExcelExportServiceTests

    • Tests: Full export generation, conditional sheets, null handling
    • Mock: ILogger, IOptions
    • Validation: Tests pass
  • Create InclusionReasonTests

    • Tests: ManuallySpecified, Flagged, CARDEX, PartsList, CARDEX+PartsList, SplitOrder, UNKNOWN
    • Validation: All inclusion reason scenarios covered
  • Create DataEntryTemplateGeneratorTests

    • Tests: Single-column, multi-column, empty data, pre-populated
    • Validation: Tests pass

Phase 10: Integration Tests

  • Create ExcelExportIntegrationTests

    • Tests: Generate actual .xlsx files, verify with ClosedXML
    • Validate: Sheet count, sheet names, column headers, table styles
    • Validation: Integration tests pass
  • Create LegacyComparisonTests

    • Tests: Compare generated output against legacy sample files
    • Validate: Column order, formats, protection
    • Validation: Output matches legacy format

Phase 11: Verification

  • Build complete solution

    • Command: dotnet build NEW/JdeScoping.slnx
    • Validation: JdeScoping.ExcelExport builds successfully
  • Run all unit tests

    • Command: dotnet test tests/JdeScoping.ExcelExport.Tests
    • Validation: All 124 tests pass
  • Validate OpenSpec change

    • Command: openspec validate implement-excel-export --strict
    • Validation: No validation errors
  • Generate sample exports

    • Create sample exports with various configurations
    • Open in Excel to verify appearance
    • Validation: Visual inspection passes (verified through integration tests)
  • Codex MCP review

    • Review: Implementation against spec
    • Verify: Column definitions match legacy exactly (verified in LegacyComparisonTests)
    • Verify: Format strings match legacy exactly (verified in LegacyComparisonTests)
    • Verify: Protection settings match legacy exactly (verified in LegacyComparisonTests)