# Phase Plan — Route & Store Management ## Scope Build the full vertical-slice stack for: **Region, Route, Vehicle, Store, Warehouse, Order, OrderItem**. Item model is sourced from ERP Core — excluded from this phase. SaleRoute shape is TBD — excluded until clarified. --- ## Project Structure (target) ``` Distribution/ ├── Models/ # All entity POCOs — unchanged │ ├── Template.cs │ ├── Region.cs │ ├── Route.cs │ ├── Vehicle.cs │ ├── Store.cs │ ├── Warehouse.cs │ ├── SaleRoute.cs # TBD │ ├── Order.cs │ ├── OrderItem.cs │ ├── DeliveryRun.cs │ └── Item.cs # Sourced from ERP Core ├── Data/ │ └── AppDBContext.cs # DbSets + Fluent API config ├── Infra/ │ ├── UoW/ # Already implemented │ │ ├── IUnitOfWork.cs │ │ └── EFUnitOfWork.cs │ └── Repositories/ # Shared generic base only │ ├── IGenericRepo.cs │ └── GenericRepo.cs └── Features/ ├── Region/ │ ├── RegionDTOs.cs │ ├── IRegionRepository.cs │ ├── RegionRepository.cs │ ├── RegionService.cs │ └── RegionController.cs ├── Route/ │ ├── RouteDTOs.cs │ ├── IRouteRepository.cs │ ├── RouteRepository.cs │ ├── RouteService.cs │ └── RouteController.cs ├── Vehicle/ │ ├── VehicleDTOs.cs │ ├── IVehicleRepository.cs │ ├── VehicleRepository.cs │ ├── VehicleService.cs │ └── VehicleController.cs ├── Store/ │ ├── StoreDTOs.cs │ ├── IStoreRepository.cs │ ├── StoreRepository.cs │ ├── StoreService.cs │ └── StoreController.cs ├── Warehouse/ │ ├── WarehouseDTOs.cs │ ├── IWarehouseRepository.cs │ ├── WarehouseRepository.cs │ ├── WarehouseService.cs │ └── WarehouseController.cs └── Order/ ├── OrderDTOs.cs ├── IOrderRepository.cs ├── OrderRepository.cs ├── OrderService.cs └── OrderController.cs ``` --- ## Hard Rules (from AGENTS.md) - Only `uow.CommitAsync()` in services — never in repositories. - Use `DateTime.Now` — never `DateTime.UtcNow`. - Never build anything not explicitly requested. --- ## Step 2 — Complete AppDBContext File: `Data/AppDBContext.cs` Add DbSets and Fluent API configuration: ```csharp public DbSet Regions { get; set; } public DbSet Routes { get; set; } public DbSet Vehicles { get; set; } public DbSet Stores { get; set; } public DbSet Warehouses { get; set; } public DbSet SaleRoutes { get; set; } public DbSet Orders { get; set; } public DbSet OrderItems { get; set; } public DbSet DeliveryRuns { get; set; } public DbSet Items { get; set; } // OnModelCreating modelBuilder.Entity() .HasKey(oi => new { oi.FK_OrderId, oi.FK_ItemId }); ``` --- ## Step 3 — Initial Migration ```powershell dotnet ef migrations add InitialCreate --project Distribution dotnet ef database update --project Distribution ``` Each developer applies this locally. No migration files are shared. --- ## Step 4 — Generic Repository (Infra/Repositories) **`IGenericRepo`** ``` GetByIdAsync(Guid id) GetAllAsync() AddAsync(T entity) Update(T entity) Remove(T entity) ``` **`GenericRepo`** — implements above using DbContext. No `SaveChanges` calls. --- ## Step 5 — Feature Implementation Order Build each feature in this dependency order: ``` 1. Region → no dependencies 2. Route → no dependencies 3. Vehicle → no dependencies 4. Store → no dependencies 5. Warehouse → depends on Vehicle (FK) 6. Order → depends on Store (FK) 7. OrderItem → depends on Order + Item (composite FK) ``` ### Per-feature deliverables #### DTOs (`{Feature}DTOs.cs`) - `CreateRequest` — fields accepted on POST - `UpdateRequest` — fields accepted on PUT - `Response` — shape returned to client (never expose the entity directly) #### Repository interface (`I{Feature}Repository.cs`) Extends `IGenericRepo`. Add feature-specific queries (e.g., `GetByStoreId`). #### Repository implementation (`{Feature}Repository.cs`) Inherits `GenericRepo`. Implements feature-specific queries. No `CommitAsync` calls. #### Service (`{Feature}Service.cs`) - Contains all business logic. - Calls `_uow.CommitAsync(ct)` after write operations. - For multi-step writes: `BeginAsync → work → CommitAsync` (catch → `RollbackAsync`). #### Controller (`{Feature}Controller.cs`) Thin — maps HTTP → service call → returns result. No logic, no UoW calls. --- ## Step 6 — Endpoints ### Region — `/api/regions` | Method | Route | Description | |---|---|---| | GET | `/` | Get all active regions | | GET | `/{id}` | Get region by id | | POST | `/` | Create region | | PUT | `/{id}` | Update region | | DELETE | `/{id}` | Soft delete (set IsActive = false) | ### Route — `/api/routes` | Method | Route | Description | |---|---|---| | GET | `/` | Get all active routes | | GET | `/{id}` | Get route by id | | POST | `/` | Create route | | PUT | `/{id}` | Update route | | DELETE | `/{id}` | Soft delete | ### Vehicle — `/api/vehicles` | Method | Route | Description | |---|---|---| | GET | `/` | Get all active vehicles | | GET | `/{id}` | Get vehicle by id | | POST | `/` | Create vehicle | | PUT | `/{id}` | Update vehicle | | DELETE | `/{id}` | Soft delete | ### Store — `/api/stores` | Method | Route | Description | |---|---|---| | GET | `/` | Get all active stores | | GET | `/{id}` | Get store by id | | POST | `/` | Create store | | PUT | `/{id}` | Update store | | DELETE | `/{id}` | Soft delete | ### Warehouse — `/api/warehouses` | Method | Route | Description | |---|---|---| | GET | `/` | Get all active warehouses | | GET | `/{id}` | Get warehouse by id | | POST | `/` | Create warehouse | | PUT | `/{id}` | Update warehouse | | DELETE | `/{id}` | Soft delete | ### Order — `/api/orders` | Method | Route | Description | |---|---|---| | GET | `/` | Get all active orders | | GET | `/{id}` | Get order with items | | GET | `/store/{storeId}` | Get orders by store | | POST | `/` | Create order with items | | PUT | `/{id}` | Update order | | DELETE | `/{id}` | Soft delete | --- ## Step 7 — DI Registration (Program.cs) Register all feature repositories and services: ```csharp // Generic base builder.Services.AddScoped(typeof(IGenericRepo<>), typeof(GenericRepo<>)); // Feature repositories builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); // Feature services builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); ``` --- ## Deferred | Item | Reason | |---|---| | `SaleRoute` | Shape undefined — implement after clarification | | `Item` model | Sourced from ERP Core — user handles integration | | `DeliveryRun` | Not in scope for this phase | | Driver FK on DeliveryRun | Commented out — depends on HR/Driver module | | Tests | No test project yet — add after endpoints stabilize |