Files
jdescopingtool/PLANS/2026-01-01-excelio-consolidation-design.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

4.6 KiB

ExcelIO Consolidation Design

Problem

After the architecture cleanup, Excel file I/O code is scattered across multiple projects:

  • JdeScoping.ExcelExport - search result report generation
  • JdeScoping.Api/Controllers/FileIOController.*.cs - upload parsing and template downloads
  • JdeScoping.Api/Helpers/ExcelTemplateGenerator.cs - template generation helper

The project name "ExcelExport" no longer reflects its broader responsibility for all Excel I/O operations.

Goal

  1. Rename JdeScoping.ExcelExport to JdeScoping.ExcelIO
  2. Consolidate ALL Excel file I/O into the ExcelIO project
  3. Integrate with search processor for report generation
  4. Move related tests to JdeScoping.ExcelIO.Tests

Design Decisions

Decision Choice Rationale
Parser scope Pure I/O only ExcelIO parses/writes files; API handles database lookups
Integration point In ExcelIO IExcelExportService takes search results, returns byte[]
Service structure Separate services IExcelExportService, IExcelTemplateService, IExcelParserService
Interface location Core project Follows existing pattern, enables dependency inversion

Target Structure

JdeScoping.ExcelIO Project

ExcelIO/
├── Export/
│   ├── ExcelExportService.cs
│   ├── Generators/
│   │   ├── AttributeTableWriter.cs
│   │   ├── CriteriaSheetGenerator.cs
│   │   └── DataEntryTemplateGenerator.cs
│   └── Formatting/
│       ├── ColumnFormatter.cs
│       ├── ExcelFormats.cs
│       ├── HeaderFormatter.cs
│       └── WorksheetProtector.cs
├── Templates/
│   └── ExcelTemplateService.cs
├── Parsing/
│   ├── ExcelParserService.cs
│   └── Parsers/
│       ├── WorkOrderParser.cs
│       ├── ItemParser.cs
│       ├── ComponentLotParser.cs
│       └── PartOperationParser.cs
├── Shared/
│   ├── Attributes/
│   ├── Helpers/
│   └── Models/
└── ServiceCollectionExtensions.cs

Interfaces in Core/Interfaces

// Existing, moved from ExcelIO
public interface IExcelExportService
{
    Task<byte[]> GenerateAsync(SearchModel search, CancellationToken ct);
}

// New
public interface IExcelTemplateService
{
    byte[] GenerateSingleColumn<T>(IEnumerable<T> data, string headerText);
    byte[] GenerateMultiColumn(object?[][] data, string[] headers);
}

// New
public interface IExcelParserService
{
    List<long> ParseWorkOrders(Stream fileStream);
    List<string> ParseItems(Stream fileStream);
    List<(string LotNumber, string ItemNumber)> ParseComponentLots(Stream fileStream);
    List<PartOperationViewModel> ParsePartOperations(Stream fileStream);
}

Code Movement

From Api to ExcelIO

From To
Api/Helpers/ExcelTemplateGenerator.cs ExcelIO/Templates/ExcelTemplateService.cs
Excel parsing logic from FileIOController.*.cs ExcelIO/Parsing/ExcelParserService.cs

FileIOController Changes

The 5 partial class files become thin wrappers:

  • Inject IExcelParserService and IExcelTemplateService
  • Call parser for uploads, then repository for DB lookups
  • Call template service for downloads

Api Project Reference Changes

  • Remove: ClosedXML package reference
  • Add: Project reference to JdeScoping.ExcelIO

Test Movement

From To Reason
Api.Tests/FileControllerTests.cs (parsing tests) ExcelIO.Tests/Parsing/ Tests Excel parsing logic
Api.Tests/FileControllerTests.cs (controller tests) Keep in Api.Tests Tests HTTP behavior

ExcelIO.Tests Structure

ExcelIO.Tests/
├── Export/           (existing tests, reorganized)
├── Templates/
│   └── ExcelTemplateServiceTests.cs
└── Parsing/
    └── ExcelParserServiceTests.cs

Search Processor Integration

The search processor will:

  1. Execute search query → get results
  2. Call IExcelExportService.GenerateAsync(searchModel) → get byte[]
  3. Call repository to store byte[] in Search.Results column

Host project will:

  • Reference JdeScoping.ExcelIO
  • Register services via services.AddExcelIO()
  • Inject and call the export service

Verification

  1. Build: dotnet build succeeds, no ClosedXML in Api
  2. Tests: All tests pass, count preserved (~49 in ExcelIO.Tests)
  3. Functional: Templates download, uploads parse, exports generate
  4. Structure: Solution file updated with renamed projects