# 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 GenerateAsync(SearchModel search, CancellationToken ct); } // New public interface IExcelTemplateService { byte[] GenerateSingleColumn(IEnumerable data, string headerText); byte[] GenerateMultiColumn(object?[][] data, string[] headers); } // New public interface IExcelParserService { List ParseWorkOrders(Stream fileStream); List ParseItems(Stream fileStream); List<(string LotNumber, string ItemNumber)> ParseComponentLots(Stream fileStream); List 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