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.
This commit is contained in:
@@ -0,0 +1,143 @@
|
||||
# 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
|
||||
Reference in New Issue
Block a user