======================================================================== Issue #134: feat: Complete Work Reports & Technical Inspections REST API ======================================================================== :State: **OPEN** :Milestone: Jalon 3: Features Différenciantes 🎯 :Labels: enhancement,phase:vps track:software,priority:high :Assignees: Unassigned :Created: 2025-11-18 :Updated: 2025-11-18 :URL: `View on GitHub `_ Description =========== .. raw:: html
:: ## πŸ”§ Complete REST API for Contractor Backoffice (Issue #52 Split) **Priority**: πŸ”΄ HIGH | **Phase**: VPS (Jalon 3) | **Track**: Software **Parent Issue**: #52 (Contractor backoffice) --- ## πŸ“‹ Context Domain entities and migrations **ALREADY IMPLEMENTED** βœ…: - βœ… Migration: `20251203000000_create_work_reports.sql` - βœ… Migration: `20251203000001_create_technical_inspections.sql` - βœ… Domain entity: `backend/src/domain/entities/work_report.rs` (110 lines) - βœ… Domain entity: `backend/src/domain/entities/technical_inspection.rs` (102 lines) **Missing**: REST API handlers + routes configuration ❌ --- ## 🎯 Objective Expose Work Reports and Technical Inspections via REST API for contractor backoffice. --- ## πŸ“ Tasks ### Backend (Rust) #### 1. Repository Traits + Implementations **Create**: `backend/src/application/ports/work_report_repository.rs` ```rust #[async_trait] pub trait WorkReportRepository: Send + Sync { async fn create(&self, report: &WorkReport) -> Result; async fn find_by_id(&self, id: Uuid) -> Result, String>; async fn find_by_building(&self, building_id: Uuid) -> Result, String>; async fn find_by_contractor(&self, contractor_id: Uuid) -> Result, String>; async fn find_by_quote(&self, quote_id: Uuid) -> Result, String>; async fn update(&self, report: &WorkReport) -> Result; async fn delete(&self, id: Uuid) -> Result<(), String>; async fn list_pending_validation(&self, organization_id: Uuid) -> Result, String>; async fn mark_as_validated(&self, id: Uuid, validated_by: Uuid) -> Result<(), String>; async fn count_by_contractor(&self, contractor_id: Uuid) -> Result; } ``` **Create**: `backend/src/infrastructure/database/repositories/work_report_repository_impl.rs` - PostgreSQL implementation (10 methods) - SQL queries with proper error handling **Create**: `backend/src/application/ports/technical_inspection_repository.rs` ```rust #[async_trait] pub trait TechnicalInspectionRepository: Send + Sync { async fn create(&self, inspection: &TechnicalInspection) -> Result; async fn find_by_id(&self, id: Uuid) -> Result, String>; async fn find_by_building(&self, building_id: Uuid) -> Result, String>; async fn find_by_inspector(&self, inspector_id: Uuid) -> Result, String>; async fn find_by_type(&self, building_id: Uuid, inspection_type: InspectionType) -> Result, String>; async fn find_by_status(&self, building_id: Uuid, status: InspectionStatus) -> Result, String>; async fn update(&self, inspection: &TechnicalInspection) -> Result; async fn delete(&self, id: Uuid) -> Result<(), String>; async fn find_overdue(&self, organization_id: Uuid) -> Result, String>; async fn mark_as_completed(&self, id: Uuid) -> Result<(), String>; } ``` **Create**: `backend/src/infrastructure/database/repositories/technical_inspection_repository_impl.rs` #### 2. Use Cases **Create**: `backend/src/application/use_cases/work_report_use_cases.rs` - 10 methods matching repository + business logic **Create**: `backend/src/application/use_cases/technical_inspection_use_cases.rs` - 10 methods matching repository + business logic #### 3. DTOs **Create**: `backend/src/application/dto/work_report_dto.rs` ```rust #[derive(Debug, Serialize, Deserialize)] pub struct CreateWorkReportDto { pub building_id: Uuid, pub contractor_id: Uuid, pub quote_id: Option, pub work_type: WorkType, pub description: String, pub work_date: NaiveDate, pub hours_worked: f64, pub materials_cost_cents: Option, pub labor_cost_cents: Option, pub photo_urls: Vec, pub notes: Option, } #[derive(Debug, Serialize, Deserialize)] pub struct WorkReportResponseDto { pub id: Uuid, pub building_id: Uuid, pub contractor_id: Uuid, pub quote_id: Option, pub work_type: WorkType, pub description: String, pub work_date: NaiveDate, pub hours_worked: f64, pub materials_cost_cents: Option, pub labor_cost_cents: Option, pub total_cost_cents: i64, pub photo_urls: Vec, pub is_validated: bool, pub validated_by: Option, pub validated_at: Option>, pub warranty_type: Option, pub warranty_expiration: Option, pub notes: Option, pub created_at: DateTime, pub updated_at: DateTime, } ``` **Create**: `backend/src/application/dto/technical_inspection_dto.rs` ```rust #[derive(Debug, Serialize, Deserialize)] pub struct CreateTechnicalInspectionDto { pub building_id: Uuid, pub inspector_id: Uuid, pub inspection_type: InspectionType, pub scheduled_date: NaiveDate, pub description: Option, } #[derive(Debug, Serialize, Deserialize)] pub struct TechnicalInspectionResponseDto { pub id: Uuid, pub building_id: Uuid, pub inspector_id: Uuid, pub inspection_type: InspectionType, pub status: InspectionStatus, pub scheduled_date: NaiveDate, pub completed_date: Option, pub findings: Option, pub recommendations: Option, pub compliance_status: bool, pub report_url: Option, pub next_inspection_due: Option, pub description: Option, pub created_at: DateTime, pub updated_at: DateTime, } ``` #### 4. REST Handlers **Create**: `backend/src/infrastructure/web/handlers/work_report_handlers.rs` (~400 lines) Endpoints (10): - `POST /api/v1/work-reports` - Create work report - `GET /api/v1/work-reports/:id` - Get work report - `GET /api/v1/buildings/:id/work-reports` - List building work reports - `GET /api/v1/contractors/:id/work-reports` - List contractor work reports - `GET /api/v1/quotes/:id/work-reports` - List quote work reports - `PUT /api/v1/work-reports/:id` - Update work report - `DELETE /api/v1/work-reports/:id` - Delete work report - `GET /api/v1/work-reports/pending-validation` - List pending validation - `PUT /api/v1/work-reports/:id/validate` - Validate work report (syndic) - `GET /api/v1/contractors/:id/work-reports/stats` - Contractor stats **Create**: `backend/src/infrastructure/web/handlers/technical_inspection_handlers.rs` (~400 lines) Endpoints (10): - `POST /api/v1/inspections` - Create inspection - `GET /api/v1/inspections/:id` - Get inspection - `GET /api/v1/buildings/:id/inspections` - List building inspections - `GET /api/v1/buildings/:id/inspections/type/:type` - List by type - `GET /api/v1/buildings/:id/inspections/status/:status` - List by status - `PUT /api/v1/inspections/:id` - Update inspection - `DELETE /api/v1/inspections/:id` - Delete inspection - `GET /api/v1/inspections/overdue` - List overdue inspections - `PUT /api/v1/inspections/:id/complete` - Mark completed - `GET /api/v1/buildings/:id/inspections/stats` - Inspection stats #### 5. Wire Routes **Update**: `backend/src/infrastructure/web/routes.rs` Add after line 366 (Board Decisions): ```rust // Work Reports (Contractor Backoffice - Issue #52) .service(create_work_report) .service(get_work_report) .service(list_building_work_reports) .service(list_contractor_work_reports) .service(list_quote_work_reports) .service(update_work_report) .service(delete_work_report) .service(list_pending_validation_work_reports) .service(validate_work_report) .service(get_contractor_work_stats) // Technical Inspections (Contractor Backoffice - Issue #52) .service(create_inspection) .service(get_inspection) .service(list_building_inspections) .service(list_inspections_by_type) .service(list_inspections_by_status) .service(update_inspection) .service(delete_inspection) .service(list_overdue_inspections) .service(complete_inspection) .service(get_building_inspection_stats) ``` #### 6. Update AppState **Update**: `backend/src/infrastructure/web/app_state.rs` Add repositories: ```rust pub work_report_repository: Arc, pub technical_inspection_repository: Arc, ``` #### 7. Update mod.rs Files **Update**: `backend/src/application/ports/mod.rs` ```rust pub mod work_report_repository; pub mod technical_inspection_repository; pub use work_report_repository::WorkReportRepository; pub use technical_inspection_repository::TechnicalInspectionRepository; ``` **Update**: `backend/src/infrastructure/database/repositories/mod.rs` ```rust pub mod work_report_repository_impl; pub mod technical_inspection_repository_impl; pub use work_report_repository_impl::PostgresWorkReportRepository; pub use technical_inspection_repository_impl::PostgresTechnicalInspectionRepository; ``` **Update**: `backend/src/application/use_cases/mod.rs` ```rust pub mod work_report_use_cases; pub mod technical_inspection_use_cases; pub use work_report_use_cases::WorkReportUseCases; pub use technical_inspection_use_cases::TechnicalInspectionUseCases; ``` **Update**: `backend/src/application/dto/mod.rs` ```rust pub mod work_report_dto; pub mod technical_inspection_dto; pub use work_report_dto::*; pub use technical_inspection_dto::*; ``` **Update**: `backend/src/infrastructure/web/handlers/mod.rs` ```rust pub mod work_report_handlers; pub mod technical_inspection_handlers; pub use work_report_handlers::*; pub use technical_inspection_handlers::*; ``` --- ## βœ… Acceptance Criteria ### Backend - [ ] WorkReportRepository trait + PostgreSQL impl (10 methods) - [ ] TechnicalInspectionRepository trait + PostgreSQL impl (10 methods) - [ ] WorkReportUseCases (10 methods) - [ ] TechnicalInspectionUseCases (10 methods) - [ ] 2 DTOs per entity (Create + Response) - [ ] 20 REST endpoints total (10 per entity) - [ ] Routes wired in routes.rs - [ ] AppState updated with repositories - [ ] All mod.rs files updated ### Testing - [ ] Unit tests for domain entities (already exist) - [ ] Integration tests for repositories - [ ] E2E tests for REST endpoints ### Documentation - [ ] Update CLAUDE.md with new endpoints - [ ] API documentation (OpenAPI/Swagger) --- ## πŸ“¦ Effort EstimΓ© **8-12 heures** (1-2 jours dev) - Day 1 AM: Repositories + Use Cases (4h) - Day 1 PM: DTOs + Handlers Work Reports (4h) - Day 2 AM: Handlers Technical Inspections (3h) - Day 2 PM: Routes + Tests + Documentation (3h) --- ## πŸ”— Dependencies - βœ… Domain entities exist - βœ… Migrations applied - ❌ REST API layer missing (this issue) --- ## πŸ“š Related Issues - #52: Parent issue (Contractor backoffice) - #91: Contractor Quotes Module (already implemented) - #85: Ticketing System (already implemented) --- ## 🎯 Labels `enhancement`, `phase:vps`, `track:software`, `priority:high` .. raw:: html