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

144 lines
4.6 KiB
Markdown

# 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
```csharp
// 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