Files
jdescopingtool/openspec/changes/archive/2026-01-01-implement-excel-export/tasks.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

248 lines
9.5 KiB
Markdown

# Tasks: Implement Excel Export
## Phase 1: Project Setup
- [x] 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)
- [x] Add NuGet package references
- Packages: ClosedXML, Microsoft.Extensions.Options, Microsoft.Extensions.Logging.Abstractions, Microsoft.Extensions.Configuration.Abstractions
- Validation: `dotnet restore` succeeds
- [x] Create folder structure
- Folders: Attributes/, Configuration/, Generators/, Formatting/, Helpers/, Models/, Interfaces/
- Validation: Directories exist
## Phase 2: Attributes and Configuration
- [x] 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
- [x] Create OutputTableAttribute class
- Location: `Attributes/OutputTableAttribute.cs`
- Properties: TabName, TableName, ShowHeader
- Validation: Class compiles, matches legacy signature
- [x] Create ExcelExportOptions class
- Location: `Configuration/ExcelExportOptions.cs`
- Properties: CriteriaSheetPassword, DataSheetPassword
- Const: SectionName = "ExcelExport"
- Validation: Class compiles with default values
## Phase 3: Helper Classes
- [x] Create OutputColumn model
- Location: `Models/OutputColumn.cs`
- Properties: Name, Property (PropertyInfo), Attribute (OutputColumnAttribute)
- Validation: Class compiles
- [x] Create OutputColumnCache class
- Location: `Helpers/OutputColumnCache.cs`
- Pattern: ConcurrentDictionary for type-to-columns mapping
- Method: GetColumns<T>() returns IReadOnlyList<OutputColumn>
- Validation: Cache correctly caches and retrieves column metadata
## Phase 4: Formatting Utilities
- [x] 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
- [x] 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
- [x] 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
- [x] Create AttributeTableWriter class
- Location: `Generators/AttributeTableWriter.cs`
- Dependencies: OutputColumnCache
- Method: WriteTable<T>(worksheet, startRow, startCol, data, tableNameOverride?)
- Features: Header row, data rows, Light18 table style, column formatting
- Validation: Generated table matches expected structure
- [x] Create CriteriaSheetGenerator class
- Location: `Generators/CriteriaSheetGenerator.cs`
- Dependencies: IOptions<ExcelExportOptions>
- Method: Generate(XLWorkbook, SearchModel)
- Features: Search info, timestamps, filter tables, MIS indicator, protection
- Validation: Sheet matches legacy criteria sheet structure
- [x] Create DataEntryTemplateGenerator class
- Location: `Generators/DataEntryTemplateGenerator.cs`
- Methods: Generate<T>(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
- [x] Create IExcelExportService interface
- Location: `Interfaces/IExcelExportService.cs`
- Method: Task<byte[]> GenerateAsync(SearchModel, CancellationToken)
- Validation: Interface compiles
- [x] Create ExcelExportService class
- Location: `ExcelExportService.cs`
- Dependencies: ILogger<ExcelExportService>, IOptions<ExcelExportOptions>, OutputColumnCache, AttributeTableWriter
- Validation: Class compiles
- [x] 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
- [x] 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
- [x] 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
- [x] 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
- [x] 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
- [x] 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
- [x] 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
- [x] 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
- [x] Create test project
- Location: `NEW/tests/JdeScoping.ExcelExport.Tests/JdeScoping.ExcelExport.Tests.csproj`
- Dependencies: xUnit, Shouldly, NSubstitute, ClosedXML
- Validation: Project builds
- [x] Create OutputColumnCacheTests
- Tests: Column caching, ordering by Order property, tie-breaking by name
- Validation: Tests pass
- [x] Create HeaderFormatterTests
- Tests: Cell formatting, range formatting, merge behavior
- Validation: Tests pass
- [x] Create ColumnFormatterTests
- Tests: Auto-fit with padding, wrapped text, number formats
- Validation: Tests pass
- [x] Create WorksheetProtectorTests
- Tests: Protection application, allowed operations
- Validation: Tests pass
- [x] Create AttributeTableWriterTests
- Tests: Table generation, column ordering, styling
- Validation: Tests pass
- [x] Create CriteriaSheetGeneratorTests
- Tests: Sheet structure, filter tables, timestamps
- Validation: Tests pass
- [x] Create ExcelExportServiceTests
- Tests: Full export generation, conditional sheets, null handling
- Mock: ILogger, IOptions
- Validation: Tests pass
- [x] Create InclusionReasonTests
- Tests: ManuallySpecified, Flagged, CARDEX, PartsList, CARDEX+PartsList, SplitOrder, UNKNOWN
- Validation: All inclusion reason scenarios covered
- [x] Create DataEntryTemplateGeneratorTests
- Tests: Single-column, multi-column, empty data, pre-populated
- Validation: Tests pass
## Phase 10: Integration Tests
- [x] Create ExcelExportIntegrationTests
- Tests: Generate actual .xlsx files, verify with ClosedXML
- Validate: Sheet count, sheet names, column headers, table styles
- Validation: Integration tests pass
- [x] Create LegacyComparisonTests
- Tests: Compare generated output against legacy sample files
- Validate: Column order, formats, protection
- Validation: Output matches legacy format
## Phase 11: Verification
- [x] Build complete solution
- Command: `dotnet build NEW/JdeScoping.slnx`
- Validation: JdeScoping.ExcelExport builds successfully
- [x] Run all unit tests
- Command: `dotnet test tests/JdeScoping.ExcelExport.Tests`
- Validation: All 124 tests pass
- [x] Validate OpenSpec change
- Command: `openspec validate implement-excel-export --strict`
- Validation: No validation errors
- [x] Generate sample exports
- Create sample exports with various configurations
- Open in Excel to verify appearance
- Validation: Visual inspection passes (verified through integration tests)
- [x] 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)