From 39a8e1d4cd52fac345a406f79fefd511fd88c8b2 Mon Sep 17 00:00:00 2001 From: Christopher Boyles Date: Mon, 25 May 2026 13:05:20 +0800 Subject: [PATCH] chore: update document approval workflow and bug fixes --- .../app/Enums/ApprovalChainStatus.php | 31 + .../app/Enums/ApprovalStepStatus.php | 21 + .../app/Events/ApprovalCompleted.php | 16 + .../app/Events/ApprovalRequired.php | 18 + .../app/Events/StepApproved.php | 18 + .../app/Events/StepRejected.php | 18 + .../app/Http/Controllers/.gitkeep | 0 .../Http/Controllers/ApprovalController.php | 107 + .../ApprovalWorkflowController.php | 56 + .../app/Listeners/SyncApprovableStatus.php | 56 + .../app/Models/ApprovalChain.php | 76 + .../app/Models/ApprovalStep.php | 46 + .../ApprovalWorkflow/app/Providers/.gitkeep | 0 .../ApprovalWorkflowServiceProvider.php | 46 + .../app/Providers/EventServiceProvider.php | 31 + .../app/Providers/RouteServiceProvider.php | 50 + .../app/Services/ApprovalService.php | 135 + .../app/Traits/HasApprovable.php | 30 + Modules/ApprovalWorkflow/composer.json | 30 + Modules/ApprovalWorkflow/config/.gitkeep | 0 Modules/ApprovalWorkflow/config/config.php | 5 + .../database/factories/.gitkeep | 0 .../database/migrations/.gitkeep | 0 ...26_03_24_210001_create_approval_tables.php | 39 + .../database/seeders/.gitkeep | 0 .../ApprovalWorkflowDatabaseSeeder.php | 16 + Modules/ApprovalWorkflow/module.json | 11 + Modules/ApprovalWorkflow/package.json | 15 + .../resources/assets/.gitkeep | 0 .../resources/assets/js/app.js | 0 .../resources/assets/sass/app.scss | 0 .../js/Components/ApprovableBreakdown.tsx | 83 + .../js/Components/ApprovalTimeline.tsx | 66 + .../resources/js/Pages/Approvals/Index.tsx | 147 ++ .../resources/js/Pages/Approvals/Show.tsx | 157 ++ .../ApprovalWorkflow/resources/views/.gitkeep | 0 .../views/components/layouts/master.blade.php | 30 + .../resources/views/index.blade.php | 5 + Modules/ApprovalWorkflow/routes/.gitkeep | 0 Modules/ApprovalWorkflow/routes/api.php | 8 + Modules/ApprovalWorkflow/routes/web.php | 11 + .../ApprovalWorkflow/tests/Feature/.gitkeep | 0 Modules/ApprovalWorkflow/tests/Unit/.gitkeep | 0 Modules/ApprovalWorkflow/vite.config.js | 41 + .../app/Enums/BidPackageStatus.php | 45 + .../app/Enums/BidSubmissionStatus.php | 31 + .../app/Enums/EvaluationMode.php | 17 + .../app/Events/BidAwarded.php | 14 + .../app/Events/BidPackageOpened.php | 14 + .../app/Events/BidSubmitted.php | 14 + .../Http/Controllers/BidAwardController.php | 51 + .../Controllers/BidInvitationController.php | 88 + .../Http/Controllers/BidPackageController.php | 212 ++ .../Http/Controllers/BidScoreController.php | 43 + .../Controllers/BidSubmissionController.php | 140 + .../BiddingManagement/app/Models/BidAward.php | 73 + .../app/Models/BidCriteria.php | 34 + .../app/Models/BidInvitation.php | 64 + .../app/Models/BidPackage.php | 126 + .../BiddingManagement/app/Models/BidScore.php | 36 + .../app/Models/BidSubmission.php | 89 + .../BiddingManagementServiceProvider.php | 17 + .../app/Providers/EventServiceProvider.php | 14 + .../app/Providers/RouteServiceProvider.php | 32 + Modules/BiddingManagement/composer.json | 28 + ...026_05_23_000001_create_bidding_tables.php | 101 + Modules/BiddingManagement/module.json | 11 + Modules/BiddingManagement/package.json | 15 + .../js/Pages/Bids/Contractor/MyBids.tsx | 203 ++ .../js/Pages/Bids/Contractor/Submit.tsx | 238 ++ .../resources/js/Pages/Bids/Create.tsx | 10 + .../resources/js/Pages/Bids/Edit.tsx | 11 + .../resources/js/Pages/Bids/Form.tsx | 251 ++ .../resources/js/Pages/Bids/Index.tsx | 182 ++ .../resources/js/Pages/Bids/Show.tsx | 599 +++++ Modules/BiddingManagement/routes/api.php | 5 + Modules/BiddingManagement/routes/web.php | 42 + Modules/BiddingManagement/vite.config.js | 28 + .../app/Enums/EquipmentStatus.php | 19 + .../app/Enums/InvoiceStatus.php | 34 + .../app/Events/ContractorApproved.php | 16 + .../Events/ContractorAssignedToProject.php | 18 + .../app/Events/ContractorInvoicePaid.php | 16 + .../app/Events/ContractorInvoiceSubmitted.php | 16 + .../app/Events/ContractorOnboarded.php | 16 + .../app/Http/Controllers/.gitkeep | 0 .../Http/Controllers/ContractorController.php | 278 ++ .../ContractorManagementController.php | 56 + .../ContractorOnboardingController.php | 157 ++ .../app/Livewire/ContractorManager.php | 76 + .../app/Models/Contractor.php | 88 + .../app/Models/ContractorCertification.php | 42 + .../app/Models/ContractorEquipment.php | 45 + .../app/Models/ContractorInvoice.php | 70 + .../app/Models/ContractorPayment.php | 30 + .../app/Models/EquipmentDeployment.php | 41 + .../app/Providers/.gitkeep | 0 .../ContractorManagementServiceProvider.php | 46 + .../app/Providers/EventServiceProvider.php | 27 + .../app/Providers/RouteServiceProvider.php | 50 + Modules/ContractorManagement/composer.json | 30 + Modules/ContractorManagement/config/.gitkeep | 0 .../ContractorManagement/config/config.php | 5 + .../database/factories/.gitkeep | 0 .../database/migrations/.gitkeep | 0 ..._03_24_220001_create_contractor_tables.php | 105 + .../database/seeders/.gitkeep | 0 .../ContractorManagementDatabaseSeeder.php | 16 + Modules/ContractorManagement/module.json | 11 + Modules/ContractorManagement/package.json | 15 + .../resources/assets/.gitkeep | 0 .../resources/assets/js/app.js | 0 .../resources/assets/sass/app.scss | 0 .../resources/js/Pages/Contractors/Create.tsx | 2 + .../resources/js/Pages/Contractors/Edit.tsx | 2 + .../resources/js/Pages/Contractors/Form.tsx | 198 ++ .../resources/js/Pages/Contractors/Index.tsx | 149 ++ .../resources/js/Pages/Contractors/Show.tsx | 356 +++ .../resources/views/.gitkeep | 0 .../views/components/layouts/master.blade.php | 30 + .../resources/views/index.blade.php | 5 + .../livewire/contractor-manager.blade.php | 87 + Modules/ContractorManagement/routes/.gitkeep | 0 Modules/ContractorManagement/routes/api.php | 8 + Modules/ContractorManagement/routes/web.php | 39 + .../tests/Feature/.gitkeep | 0 .../ContractorManagement/tests/Unit/.gitkeep | 0 Modules/ContractorManagement/vite.config.js | 41 + .../app/Http/Controllers/.gitkeep | 0 .../Controllers/DailyReportsController.php | 177 ++ .../Http/Requests/StoreDailyReportRequest.php | 66 + .../Requests/UpdateDailyReportRequest.php | 65 + .../DailyReports/app/Models/DailyReport.php | 74 + .../app/Models/DailyReportActivity.php | 22 + .../app/Models/DailyReportEquipment.php | 21 + .../app/Models/DailyReportIssue.php | 21 + .../app/Models/DailyReportLabor.php | 22 + .../app/Models/DailyReportMaterial.php | 21 + Modules/DailyReports/app/Providers/.gitkeep | 0 .../Providers/DailyReportsServiceProvider.php | 135 + .../app/Providers/EventServiceProvider.php | 30 + .../app/Providers/RouteServiceProvider.php | 50 + Modules/DailyReports/composer.json | 30 + Modules/DailyReports/config/.gitkeep | 0 Modules/DailyReports/config/config.php | 5 + .../DailyReports/database/factories/.gitkeep | 0 .../DailyReports/database/migrations/.gitkeep | 0 ...5_24_091000_create_daily_reports_table.php | 45 + ...00001_create_daily_report_labors_table.php | 26 + ...02_create_daily_report_equipment_table.php | 25 + ...3_create_daily_report_activities_table.php | 26 + ...04_create_daily_report_materials_table.php | 25 + ...00005_create_daily_report_issues_table.php | 25 + ..._add_new_fields_to_daily_reports_table.php | 46 + .../DailyReports/database/seeders/.gitkeep | 0 .../seeders/DailyReportsDatabaseSeeder.php | 16 + Modules/DailyReports/module.json | 11 + Modules/DailyReports/package.json | 15 + .../DailyReports/resources/assets/.gitkeep | 0 .../DailyReports/resources/assets/js/app.js | 0 .../resources/assets/sass/app.scss | 0 .../resources/js/Pages/Create.tsx | 23 + .../DailyReports/resources/js/Pages/Edit.tsx | 24 + .../DailyReports/resources/js/Pages/Index.tsx | 81 + .../js/Pages/Partials/ReportForm.tsx | 338 +++ .../DailyReports/resources/js/Pages/Show.tsx | 251 ++ Modules/DailyReports/resources/views/.gitkeep | 0 .../views/components/layouts/master.blade.php | 29 + .../resources/views/index.blade.php | 7 + Modules/DailyReports/routes/.gitkeep | 0 Modules/DailyReports/routes/api.php | 19 + Modules/DailyReports/routes/web.php | 10 + Modules/DailyReports/tests/Feature/.gitkeep | 0 Modules/DailyReports/tests/Unit/.gitkeep | 0 Modules/DailyReports/vite.config.js | 57 + .../app/Http/Controllers/.gitkeep | 0 .../DocumentApprovalController.php | 56 + .../Http/Controllers/DocumentController.php | 192 ++ .../DocumentManagementController.php | 56 + .../Listeners/DocumentApprovalListener.php | 25 + .../app/Models/Document.php | 90 + .../app/Models/DocumentApproval.php | 37 + .../app/Models/DocumentCategory.php | 25 + .../app/Models/DocumentVersion.php | 28 + .../app/Policies/DocumentPolicy.php | 30 + .../DocumentManagement/app/Providers/.gitkeep | 0 .../DocumentManagementServiceProvider.php | 46 + .../app/Providers/EventServiceProvider.php | 27 + .../app/Providers/RouteServiceProvider.php | 50 + Modules/DocumentManagement/composer.json | 30 + Modules/DocumentManagement/config/.gitkeep | 0 Modules/DocumentManagement/config/config.php | 5 + .../database/factories/.gitkeep | 0 .../database/migrations/.gitkeep | 0 ...26_03_25_010001_create_document_tables.php | 48 + ...42939_create_document_categories_table.php | 29 + ...042940_create_document_approvals_table.php | 32 + ..._status_and_project_to_documents_table.php | 32 + ...cumentable_nullable_on_documents_table.php | 30 + ...e_category_nullable_on_documents_table.php | 28 + .../database/seeders/.gitkeep | 0 .../DocumentManagementDatabaseSeeder.php | 16 + Modules/DocumentManagement/module.json | 11 + Modules/DocumentManagement/package.json | 15 + .../resources/assets/.gitkeep | 0 .../resources/assets/js/app.js | 0 .../resources/assets/sass/app.scss | 0 .../resources/js/Pages/Documents/Index.tsx | 233 ++ .../resources/js/Pages/Documents/Versions.tsx | 110 + .../resources/views/.gitkeep | 0 .../views/components/layouts/master.blade.php | 30 + .../resources/views/index.blade.php | 5 + Modules/DocumentManagement/routes/.gitkeep | 0 Modules/DocumentManagement/routes/api.php | 8 + Modules/DocumentManagement/routes/web.php | 15 + .../DocumentManagement/tests/Feature/.gitkeep | 0 .../DocumentManagement/tests/Unit/.gitkeep | 0 Modules/DocumentManagement/vite.config.js | 41 + .../app/Enums/InvoiceStatus.php | 57 + .../app/Http/Controllers/.gitkeep | 0 .../Http/Controllers/FinanceController.php | 194 ++ .../FinancialManagementController.php | 56 + .../app/Models/FinancialInvoice.php | 93 + .../app/Models/InvoiceLineItem.php | 39 + .../app/Models/RetentionEntry.php | 34 + .../app/Providers/.gitkeep | 0 .../app/Providers/EventServiceProvider.php | 27 + .../FinancialManagementServiceProvider.php | 46 + .../app/Providers/RouteServiceProvider.php | 50 + .../app/Services/ProgressBillingService.php | 121 + Modules/FinancialManagement/composer.json | 30 + Modules/FinancialManagement/config/.gitkeep | 0 Modules/FinancialManagement/config/config.php | 5 + .../database/factories/.gitkeep | 0 .../database/migrations/.gitkeep | 0 ...6_03_25_000001_create_financial_tables.php | 78 + .../database/seeders/.gitkeep | 0 .../FinancialManagementDatabaseSeeder.php | 16 + Modules/FinancialManagement/module.json | 11 + Modules/FinancialManagement/package.json | 15 + .../resources/assets/.gitkeep | 0 .../resources/assets/js/app.js | 0 .../resources/assets/sass/app.scss | 0 .../resources/js/Pages/Invoices/Create.tsx | 101 + .../resources/js/Pages/Invoices/Index.tsx | 134 + .../resources/js/Pages/Invoices/Show.tsx | 161 ++ .../resources/js/Pages/Retention/Index.tsx | 114 + .../resources/views/.gitkeep | 0 .../views/components/layouts/master.blade.php | 30 + .../resources/views/index.blade.php | 5 + Modules/FinancialManagement/routes/.gitkeep | 0 Modules/FinancialManagement/routes/api.php | 8 + Modules/FinancialManagement/routes/web.php | 22 + .../tests/Feature/.gitkeep | 0 .../FinancialManagement/tests/Unit/.gitkeep | 0 Modules/FinancialManagement/vite.config.js | 41 + .../app/Exports/BoqTemplateExport.php | 98 + .../app/Exports/MaterialTemplateExport.php | 37 + .../MasterData/app/Http/Controllers/.gitkeep | 0 .../Http/Controllers/MasterDataController.php | 56 + .../Controllers/MaterialGroupController.php | 110 + .../Controllers/MaterialImportController.php | 167 ++ Modules/MasterData/app/Imports/BoqImport.php | 144 + .../MasterData/app/Imports/MaterialImport.php | 99 + Modules/MasterData/app/Models/Material.php | 72 + .../app/Models/MaterialComponent.php | 27 + .../MasterData/app/Models/MaterialGroup.php | 32 + .../app/Models/MaterialGroupItem.php | 23 + Modules/MasterData/app/Providers/.gitkeep | 0 .../app/Providers/EventServiceProvider.php | 27 + .../Providers/MasterDataServiceProvider.php | 46 + .../app/Providers/RouteServiceProvider.php | 50 + Modules/MasterData/composer.json | 30 + Modules/MasterData/config/.gitkeep | 0 Modules/MasterData/config/config.php | 5 + .../MasterData/database/factories/.gitkeep | 0 .../MasterData/database/migrations/.gitkeep | 0 ..._14_073525_add_type_to_materials_table.php | 28 + ...73534_create_material_components_table.php | 32 + Modules/MasterData/database/seeders/.gitkeep | 0 .../seeders/MasterDataDatabaseSeeder.php | 16 + Modules/MasterData/module.json | 11 + Modules/MasterData/package.json | 15 + Modules/MasterData/resources/assets/.gitkeep | 0 Modules/MasterData/resources/assets/js/app.js | 0 .../MasterData/resources/assets/sass/app.scss | 0 Modules/MasterData/resources/views/.gitkeep | 0 .../views/components/layouts/master.blade.php | 30 + .../resources/views/index.blade.php | 5 + Modules/MasterData/routes/.gitkeep | 0 Modules/MasterData/routes/api.php | 8 + Modules/MasterData/routes/web.php | 8 + Modules/MasterData/tests/Feature/.gitkeep | 0 Modules/MasterData/tests/Unit/.gitkeep | 0 Modules/MasterData/vite.config.js | 41 + .../app/Enums/DeploymentStatus.php | 49 + .../app/Enums/MaterialTransferStatus.php | 37 + .../app/Enums/MovementType.php | 66 + .../app/Enums/PaymentStatus.php | 28 + .../app/Enums/WarehouseType.php | 19 + .../app/Events/MaterialDelivered.php | 16 + .../app/Events/MaterialRequested.php | 16 + .../app/Events/PurchaseOrderPaid.php | 18 + .../app/Http/Controllers/.gitkeep | 0 .../InventoryMovementController.php | 60 + .../Http/Controllers/MaterialController.php | 306 +++ .../MaterialLogisticsController.php | 56 + .../MaterialRequisitionController.php | 263 ++ .../MaterialTransferController.php | 329 +++ .../Controllers/PurchaseOrderController.php | 435 +++ .../Http/Controllers/WarehouseController.php | 161 ++ .../app/Listeners/HandlePurchaseOrderPaid.php | 33 + .../app/Models/InventoryBatch.php | 46 + .../app/Models/InventoryMovement.php | 153 ++ .../app/Models/MaterialDeployment.php | 76 + .../app/Models/MaterialRequirement.php | 44 + .../app/Models/MaterialRequisition.php | 66 + .../app/Models/MaterialRequisitionItem.php | 39 + .../app/Models/MaterialTransfer.php | 191 ++ .../app/Models/MaterialTransferItem.php | 42 + .../app/Models/ProjectInventory.php | 49 + .../app/Models/PurchaseOrder.php | 100 + .../app/Models/PurchaseOrderItem.php | 45 + .../app/Models/Warehouse.php | 56 + .../app/Models/WarehouseStock.php | 58 + .../MaterialLogistics/app/Providers/.gitkeep | 0 .../app/Providers/EventServiceProvider.php | 33 + .../MaterialLogisticsServiceProvider.php | 46 + .../app/Providers/RouteServiceProvider.php | 50 + .../app/Services/DocumentNumberService.php | 45 + .../app/Services/InventoryService.php | 127 + .../app/Services/WarehouseService.php | 417 +++ Modules/MaterialLogistics/composer.json | 30 + Modules/MaterialLogistics/config/.gitkeep | 0 Modules/MaterialLogistics/config/config.php | 5 + .../database/factories/.gitkeep | 0 .../database/migrations/.gitkeep | 0 ...26_03_24_230001_create_material_tables.php | 72 + ...27_000001_create_material_group_tables.php | 43 + .../2026_03_28_000001_create_mr_po_tables.php | 76 + ...0001_create_warehouse_inventory_system.php | 107 + ...sonnel_tracking_to_inventory_movements.php | 41 + ...001_remove_project_id_from_procurement.php | 32 + ..._000002_create_inventory_batches_table.php | 28 + ...4_000003_add_batch_and_requisition_ids.php | 32 + ...000_add_project_id_to_warehouses_table.php | 27 + ...000001_create_material_transfers_table.php | 50 + .../database/seeders/.gitkeep | 0 .../seeders/ConstructionMaterialsSeeder.php | 106 + .../MaterialLogisticsDatabaseSeeder.php | 18 + Modules/MaterialLogistics/module.json | 11 + Modules/MaterialLogistics/package.json | 15 + .../resources/assets/.gitkeep | 0 .../resources/assets/js/app.js | 0 .../resources/assets/sass/app.scss | 0 .../resources/js/Pages/Deployments/Index.tsx | 151 ++ .../resources/js/Pages/Groups/Index.tsx | 307 +++ .../resources/js/Pages/Inventory/Index.tsx | 225 ++ .../js/Pages/Inventory/Movements.tsx | 248 ++ .../js/Pages/Inventory/OperationsForm.tsx | 517 ++++ .../resources/js/Pages/Materials/Index.tsx | 538 ++++ .../js/Pages/PurchaseOrders/Form.tsx | 532 ++++ .../js/Pages/PurchaseOrders/Index.tsx | 239 ++ .../js/Pages/PurchaseOrders/Show.tsx | 245 ++ .../resources/js/Pages/Requirements/Index.tsx | 129 + .../resources/js/Pages/Requisitions/Form.tsx | 245 ++ .../resources/js/Pages/Requisitions/Index.tsx | 150 ++ .../Requisitions/MaterialCatalogModal.tsx | 287 ++ .../resources/js/Pages/Requisitions/Show.tsx | 153 ++ .../resources/js/Pages/Transfers/Create.tsx | 335 +++ .../resources/js/Pages/Transfers/Index.tsx | 93 + .../resources/js/Pages/Transfers/Show.tsx | 250 ++ .../resources/js/Pages/Warehouses/Form.tsx | 127 + .../resources/js/Pages/Warehouses/Index.tsx | 143 + .../resources/js/Pages/Warehouses/Show.tsx | 429 +++ .../resources/views/.gitkeep | 0 .../views/components/layouts/master.blade.php | 30 + .../resources/views/index.blade.php | 5 + .../views/pdf/material-requisition.blade.php | 122 + .../views/pdf/purchase-order.blade.php | 134 + Modules/MaterialLogistics/routes/.gitkeep | 0 Modules/MaterialLogistics/routes/api.php | 8 + Modules/MaterialLogistics/routes/web.php | 75 + .../MaterialLogistics/tests/Feature/.gitkeep | 0 Modules/MaterialLogistics/tests/Unit/.gitkeep | 0 Modules/MaterialLogistics/vite.config.js | 41 + .../app/Http/Controllers/.gitkeep | 0 .../app/Http/Controllers/ItemController.php | 138 + .../app/Http/Controllers/KitController.php | 169 ++ .../MaterialsCatalogController.php | 56 + .../MaterialsCatalog/app/Providers/.gitkeep | 0 .../app/Providers/EventServiceProvider.php | 27 + .../MaterialsCatalogServiceProvider.php | 46 + .../app/Providers/RouteServiceProvider.php | 50 + Modules/MaterialsCatalog/composer.json | 30 + Modules/MaterialsCatalog/config/.gitkeep | 0 Modules/MaterialsCatalog/config/config.php | 5 + .../database/factories/.gitkeep | 0 .../database/migrations/.gitkeep | 0 .../database/seeders/.gitkeep | 0 .../MaterialsCatalogDatabaseSeeder.php | 16 + Modules/MaterialsCatalog/module.json | 11 + Modules/MaterialsCatalog/package.json | 15 + .../resources/assets/.gitkeep | 0 .../resources/assets/js/app.js | 0 .../resources/assets/sass/app.scss | 0 .../resources/js/Pages/Items/Form.tsx | 163 ++ .../resources/js/Pages/Items/Index.tsx | 133 + .../js/Pages/MaterialsCatalog/Form.tsx | 234 ++ .../js/Pages/MaterialsCatalog/Index.tsx | 106 + .../MaterialsCatalog/resources/views/.gitkeep | 0 .../views/components/layouts/master.blade.php | 30 + .../resources/views/index.blade.php | 5 + Modules/MaterialsCatalog/routes/.gitkeep | 0 Modules/MaterialsCatalog/routes/api.php | 8 + Modules/MaterialsCatalog/routes/web.php | 11 + .../MaterialsCatalog/tests/Feature/.gitkeep | 0 Modules/MaterialsCatalog/tests/Unit/.gitkeep | 0 Modules/MaterialsCatalog/vite.config.js | 41 + .../app/Http/Controllers/.gitkeep | 0 .../ProjectDocumentsController.php | 94 + .../ProjectDocuments/app/Providers/.gitkeep | 0 .../app/Providers/EventServiceProvider.php | 30 + .../ProjectDocumentsServiceProvider.php | 135 + .../app/Providers/RouteServiceProvider.php | 50 + Modules/ProjectDocuments/composer.json | 30 + Modules/ProjectDocuments/config/.gitkeep | 0 Modules/ProjectDocuments/config/config.php | 5 + .../database/factories/.gitkeep | 0 .../database/migrations/.gitkeep | 0 .../database/seeders/.gitkeep | 0 .../ProjectDocumentsDatabaseSeeder.php | 16 + Modules/ProjectDocuments/module.json | 11 + Modules/ProjectDocuments/package.json | 15 + .../resources/assets/.gitkeep | 0 .../resources/assets/js/app.js | 0 .../resources/assets/sass/app.scss | 0 .../ProjectDocuments/resources/views/.gitkeep | 0 .../views/components/layouts/master.blade.php | 29 + .../resources/views/index.blade.php | 7 + Modules/ProjectDocuments/routes/.gitkeep | 0 Modules/ProjectDocuments/routes/api.php | 19 + Modules/ProjectDocuments/routes/web.php | 10 + .../ProjectDocuments/tests/Feature/.gitkeep | 0 Modules/ProjectDocuments/tests/Unit/.gitkeep | 0 Modules/ProjectDocuments/vite.config.js | 57 + .../app/Enums/DelayReason.php | 25 + .../app/Enums/ProjectStatus.php | 37 + .../app/Enums/ReportStatus.php | 45 + .../app/Enums/TaskStatus.php | 31 + .../app/Enums/WeatherCondition.php | 43 + .../app/Events/ProjectStatusChanged.php | 18 + .../app/Events/TaskCompleted.php | 16 + .../app/Exports/TaskTemplateExport.php | 39 + .../app/Http/Controllers/.gitkeep | 0 .../Http/Controllers/ProjectController.php | 290 ++ .../ProjectManagementController.php | 56 + .../app/Imports/TaskImport.php | 66 + .../app/Models/HseRecord.php | 75 + .../ProjectManagement/app/Models/Project.php | 206 ++ .../app/Models/ProjectMilestone.php | 83 + Modules/ProjectManagement/app/Models/Task.php | 126 + .../app/Models/TaskActivity.php | 30 + .../app/Models/TaskDelay.php | 57 + .../app/Models/TaskMaterial.php | 63 + .../app/Models/WeeklyStatusReport.php | 102 + .../app/Models/WorkforceMetric.php | 54 + .../app/Observers/ProjectObserver.php | 24 + .../ProjectManagement/app/Providers/.gitkeep | 0 .../app/Providers/EventServiceProvider.php | 34 + .../ProjectManagementServiceProvider.php | 46 + .../app/Providers/RouteServiceProvider.php | 50 + Modules/ProjectManagement/composer.json | 30 + Modules/ProjectManagement/config/.gitkeep | 0 Modules/ProjectManagement/config/config.php | 5 + .../database/factories/.gitkeep | 0 .../database/migrations/.gitkeep | 0 ...026_03_24_200001_create_projects_table.php | 44 + .../2026_03_24_200002_create_tasks_table.php | 35 + ...000_create_weekly_status_reports_table.php | 34 + ..._160001_create_workforce_metrics_table.php | 26 + ..._03_26_160002_create_hse_records_table.php | 34 + ...03_add_contractor_id_to_projects_table.php | 23 + ..._26_200001_create_task_materials_table.php | 42 + ..._03_28_000002_add_po_to_task_materials.php | 27 + ...name_and_contract_duration_to_projects.php | 23 + ...000001_create_project_milestones_table.php | 36 + ..._03_31_000002_create_task_delays_table.php | 32 + ...eather_fields_to_weekly_status_reports.php | 23 + ...26_04_14_000004_create_task_user_table.php | 41 + ...24_000001_create_task_activities_table.php | 26 + .../database/seeders/.gitkeep | 0 .../ProjectManagementDatabaseSeeder.php | 31 + Modules/ProjectManagement/module.json | 11 + Modules/ProjectManagement/package.json | 15 + .../resources/assets/.gitkeep | 0 .../resources/assets/js/app.js | 0 .../resources/assets/sass/app.scss | 0 .../resources/js/Components/ProjectForm.tsx | 379 +++ .../js/Components/PurchaseOrderLookup.tsx | 125 + .../resources/js/Layouts/ProjectLayout.tsx | 124 + .../resources/js/Pages/Projects/Create.tsx | 71 + .../resources/js/Pages/Projects/Edit.tsx | 81 + .../resources/js/Pages/Projects/Index.tsx | 246 ++ .../resources/js/Pages/Projects/Materials.tsx | 73 + .../Pages/Projects/Modules/DailyReports.tsx | 27 + .../js/Pages/Projects/Modules/Documents.tsx | 217 ++ .../js/Pages/Projects/Modules/Progress.tsx | 27 + .../Pages/Projects/Modules/QualityControl.tsx | 27 + .../js/Pages/Projects/Modules/RFIs.tsx | 27 + .../js/Pages/Projects/Modules/Safety.tsx | 27 + .../resources/js/Pages/Projects/Overview.tsx | 202 ++ .../resources/js/Pages/Projects/Show.tsx | 1390 ++++++++++ .../resources/js/Pages/Projects/Team.tsx | 132 + .../resources/js/Pages/Reports/Create.tsx | 259 ++ .../resources/js/Pages/Reports/Edit.tsx | 248 ++ .../resources/js/Pages/Reports/Index.tsx | 243 ++ .../resources/js/Pages/Reports/Show.tsx | 394 +++ .../resources/views/.gitkeep | 0 .../views/components/layouts/master.blade.php | 30 + .../resources/views/index.blade.php | 5 + Modules/ProjectManagement/routes/.gitkeep | 0 Modules/ProjectManagement/routes/api.php | 8 + Modules/ProjectManagement/routes/web.php | 17 + .../ProjectManagement/tests/Feature/.gitkeep | 0 Modules/ProjectManagement/tests/Unit/.gitkeep | 0 Modules/ProjectManagement/vite.config.js | 41 + .../app/Http/Controllers/.gitkeep | 0 .../Controllers/ProjectProgressController.php | 72 + .../ProjectProgress/app/Providers/.gitkeep | 0 .../app/Providers/EventServiceProvider.php | 30 + .../ProjectProgressServiceProvider.php | 135 + .../app/Providers/RouteServiceProvider.php | 50 + Modules/ProjectProgress/composer.json | 30 + Modules/ProjectProgress/config/.gitkeep | 0 Modules/ProjectProgress/config/config.php | 5 + .../database/factories/.gitkeep | 0 .../database/migrations/.gitkeep | 0 .../ProjectProgress/database/seeders/.gitkeep | 0 .../seeders/ProjectProgressDatabaseSeeder.php | 16 + Modules/ProjectProgress/module.json | 11 + Modules/ProjectProgress/package.json | 15 + .../ProjectProgress/resources/assets/.gitkeep | 0 .../resources/assets/js/app.js | 0 .../resources/assets/sass/app.scss | 0 .../ProjectProgress/resources/views/.gitkeep | 0 .../views/components/layouts/master.blade.php | 29 + .../resources/views/index.blade.php | 7 + Modules/ProjectProgress/routes/.gitkeep | 0 Modules/ProjectProgress/routes/api.php | 19 + Modules/ProjectProgress/routes/web.php | 10 + .../ProjectProgress/tests/Feature/.gitkeep | 0 Modules/ProjectProgress/tests/Unit/.gitkeep | 0 Modules/ProjectProgress/vite.config.js | 57 + .../app/Http/Controllers/.gitkeep | 0 .../ProjectQualityControlController.php | 72 + .../app/Providers/.gitkeep | 0 .../app/Providers/EventServiceProvider.php | 30 + .../ProjectQualityControlServiceProvider.php | 135 + .../app/Providers/RouteServiceProvider.php | 50 + Modules/ProjectQualityControl/composer.json | 30 + Modules/ProjectQualityControl/config/.gitkeep | 0 .../ProjectQualityControl/config/config.php | 5 + .../database/factories/.gitkeep | 0 .../database/migrations/.gitkeep | 0 .../database/seeders/.gitkeep | 0 .../ProjectQualityControlDatabaseSeeder.php | 16 + Modules/ProjectQualityControl/module.json | 11 + Modules/ProjectQualityControl/package.json | 15 + .../resources/assets/.gitkeep | 0 .../resources/assets/js/app.js | 0 .../resources/assets/sass/app.scss | 0 .../resources/views/.gitkeep | 0 .../views/components/layouts/master.blade.php | 29 + .../resources/views/index.blade.php | 7 + Modules/ProjectQualityControl/routes/.gitkeep | 0 Modules/ProjectQualityControl/routes/api.php | 19 + Modules/ProjectQualityControl/routes/web.php | 10 + .../tests/Feature/.gitkeep | 0 .../ProjectQualityControl/tests/Unit/.gitkeep | 0 Modules/ProjectQualityControl/vite.config.js | 57 + .../ProjectRFIs/app/Http/Controllers/.gitkeep | 0 .../Controllers/ProjectRFIsController.php | 72 + Modules/ProjectRFIs/app/Providers/.gitkeep | 0 .../app/Providers/EventServiceProvider.php | 30 + .../Providers/ProjectRFIsServiceProvider.php | 135 + .../app/Providers/RouteServiceProvider.php | 50 + Modules/ProjectRFIs/composer.json | 30 + Modules/ProjectRFIs/config/.gitkeep | 0 Modules/ProjectRFIs/config/config.php | 5 + .../ProjectRFIs/database/factories/.gitkeep | 0 .../ProjectRFIs/database/migrations/.gitkeep | 0 Modules/ProjectRFIs/database/seeders/.gitkeep | 0 .../seeders/ProjectRFIsDatabaseSeeder.php | 16 + Modules/ProjectRFIs/module.json | 11 + Modules/ProjectRFIs/package.json | 15 + Modules/ProjectRFIs/resources/assets/.gitkeep | 0 .../ProjectRFIs/resources/assets/js/app.js | 0 .../resources/assets/sass/app.scss | 0 Modules/ProjectRFIs/resources/views/.gitkeep | 0 .../views/components/layouts/master.blade.php | 29 + .../resources/views/index.blade.php | 7 + Modules/ProjectRFIs/routes/.gitkeep | 0 Modules/ProjectRFIs/routes/api.php | 19 + Modules/ProjectRFIs/routes/web.php | 10 + Modules/ProjectRFIs/tests/Feature/.gitkeep | 0 Modules/ProjectRFIs/tests/Unit/.gitkeep | 0 Modules/ProjectRFIs/vite.config.js | 57 + .../app/Http/Controllers/.gitkeep | 0 .../Controllers/ProjectReportsController.php | 65 + .../Controllers/StatusReportController.php | 315 +++ Modules/ProjectReports/app/Providers/.gitkeep | 0 .../app/Providers/EventServiceProvider.php | 30 + .../ProjectReportsServiceProvider.php | 135 + .../app/Providers/RouteServiceProvider.php | 50 + Modules/ProjectReports/composer.json | 30 + Modules/ProjectReports/config/.gitkeep | 0 Modules/ProjectReports/config/config.php | 5 + .../database/factories/.gitkeep | 0 .../database/migrations/.gitkeep | 0 .../ProjectReports/database/seeders/.gitkeep | 0 .../seeders/ProjectReportsDatabaseSeeder.php | 16 + Modules/ProjectReports/module.json | 11 + Modules/ProjectReports/package.json | 15 + .../ProjectReports/resources/assets/.gitkeep | 0 .../ProjectReports/resources/assets/js/app.js | 0 .../resources/assets/sass/app.scss | 0 .../resources/js/Pages/Reports/Index.tsx | 97 + .../ProjectReports/resources/views/.gitkeep | 0 .../views/components/layouts/master.blade.php | 29 + .../resources/views/index.blade.php | 7 + Modules/ProjectReports/routes/.gitkeep | 0 Modules/ProjectReports/routes/api.php | 19 + Modules/ProjectReports/routes/web.php | 10 + Modules/ProjectReports/tests/Feature/.gitkeep | 0 Modules/ProjectReports/tests/Unit/.gitkeep | 0 Modules/ProjectReports/vite.config.js | 57 + .../app/Http/Controllers/.gitkeep | 0 .../Controllers/ProjectSafetyController.php | 72 + Modules/ProjectSafety/app/Providers/.gitkeep | 0 .../app/Providers/EventServiceProvider.php | 30 + .../ProjectSafetyServiceProvider.php | 135 + .../app/Providers/RouteServiceProvider.php | 50 + Modules/ProjectSafety/composer.json | 30 + Modules/ProjectSafety/config/.gitkeep | 0 Modules/ProjectSafety/config/config.php | 5 + .../ProjectSafety/database/factories/.gitkeep | 0 .../database/migrations/.gitkeep | 0 .../ProjectSafety/database/seeders/.gitkeep | 0 .../seeders/ProjectSafetyDatabaseSeeder.php | 16 + Modules/ProjectSafety/module.json | 11 + Modules/ProjectSafety/package.json | 15 + .../ProjectSafety/resources/assets/.gitkeep | 0 .../ProjectSafety/resources/assets/js/app.js | 0 .../resources/assets/sass/app.scss | 0 .../ProjectSafety/resources/views/.gitkeep | 0 .../views/components/layouts/master.blade.php | 29 + .../resources/views/index.blade.php | 7 + Modules/ProjectSafety/routes/.gitkeep | 0 Modules/ProjectSafety/routes/api.php | 19 + Modules/ProjectSafety/routes/web.php | 10 + Modules/ProjectSafety/tests/Feature/.gitkeep | 0 Modules/ProjectSafety/tests/Unit/.gitkeep | 0 Modules/ProjectSafety/vite.config.js | 57 + .../app/Http/Controllers/.gitkeep | 0 .../RolesPermissionsController.php | 41 + .../RolesPermissions/app/Providers/.gitkeep | 0 .../app/Providers/EventServiceProvider.php | 30 + .../RolesPermissionsServiceProvider.php | 135 + .../app/Providers/RouteServiceProvider.php | 50 + Modules/RolesPermissions/composer.json | 30 + Modules/RolesPermissions/config/.gitkeep | 0 Modules/RolesPermissions/config/config.php | 5 + .../database/factories/.gitkeep | 0 .../database/migrations/.gitkeep | 0 .../database/seeders/.gitkeep | 0 .../RolesPermissionsDatabaseSeeder.php | 104 + Modules/RolesPermissions/module.json | 11 + Modules/RolesPermissions/package.json | 15 + .../resources/assets/.gitkeep | 0 .../resources/assets/js/app.js | 0 .../resources/assets/sass/app.scss | 0 .../resources/js/Pages/Roles/Index.tsx | 190 ++ .../RolesPermissions/resources/views/.gitkeep | 0 .../views/components/layouts/master.blade.php | 29 + .../resources/views/index.blade.php | 7 + Modules/RolesPermissions/routes/.gitkeep | 0 Modules/RolesPermissions/routes/api.php | 19 + Modules/RolesPermissions/routes/web.php | 19 + .../RolesPermissions/tests/Feature/.gitkeep | 0 Modules/RolesPermissions/tests/Unit/.gitkeep | 0 Modules/RolesPermissions/vite.config.js | 57 + .../app/Http/Controllers/.gitkeep | 0 .../app/Http/Controllers/TaskController.php | 273 ++ .../Http/Controllers/TaskDelayController.php | 59 + .../Http/Controllers/TaskImportController.php | 42 + .../Controllers/TaskManagementController.php | 65 + .../Controllers/TaskMaterialController.php | 133 + Modules/TaskManagement/app/Providers/.gitkeep | 0 .../app/Providers/EventServiceProvider.php | 30 + .../app/Providers/RouteServiceProvider.php | 50 + .../TaskManagementServiceProvider.php | 135 + Modules/TaskManagement/composer.json | 30 + Modules/TaskManagement/config/.gitkeep | 0 Modules/TaskManagement/config/config.php | 5 + .../database/factories/.gitkeep | 0 .../database/migrations/.gitkeep | 0 .../TaskManagement/database/seeders/.gitkeep | 0 .../seeders/TaskManagementDatabaseSeeder.php | 16 + Modules/TaskManagement/module.json | 11 + Modules/TaskManagement/package.json | 15 + .../TaskManagement/resources/assets/.gitkeep | 0 .../TaskManagement/resources/assets/js/app.js | 0 .../resources/assets/sass/app.scss | 0 .../resources/js/Components/KanbanBoard.tsx | 183 ++ .../resources/js/Pages/Tasks/Index.tsx | 458 ++++ .../TaskManagement/resources/views/.gitkeep | 0 .../views/components/layouts/master.blade.php | 29 + .../resources/views/index.blade.php | 7 + Modules/TaskManagement/routes/.gitkeep | 0 Modules/TaskManagement/routes/api.php | 19 + Modules/TaskManagement/routes/web.php | 33 + Modules/TaskManagement/tests/Feature/.gitkeep | 0 Modules/TaskManagement/tests/Unit/.gitkeep | 0 Modules/TaskManagement/vite.config.js | 57 + .../app/Enums/DependencyType.php | 21 + .../app/Http/Controllers/.gitkeep | 0 .../Http/Controllers/MilestoneController.php | 105 + .../Http/Controllers/ScheduleController.php | 110 + .../TimelineSchedulingController.php | 56 + .../app/Models/Milestone.php | 41 + .../app/Models/TaskDependency.php | 31 + .../TimelineScheduling/app/Providers/.gitkeep | 0 .../app/Providers/EventServiceProvider.php | 27 + .../app/Providers/RouteServiceProvider.php | 50 + .../TimelineSchedulingServiceProvider.php | 46 + .../app/Services/GanttDataTransformer.php | 68 + Modules/TimelineScheduling/composer.json | 30 + Modules/TimelineScheduling/config/.gitkeep | 0 Modules/TimelineScheduling/config/config.php | 5 + .../database/factories/.gitkeep | 0 .../database/migrations/.gitkeep | 0 ..._03_25_020001_create_scheduling_tables.php | 40 + .../database/seeders/.gitkeep | 0 .../TimelineSchedulingDatabaseSeeder.php | 16 + Modules/TimelineScheduling/module.json | 11 + Modules/TimelineScheduling/package.json | 15 + .../resources/assets/.gitkeep | 0 .../resources/assets/js/app.js | 0 .../resources/assets/sass/app.scss | 0 .../resources/js/Pages/Schedule/Gantt.tsx | 248 ++ .../resources/js/Pages/Timeline/Index.tsx | 257 ++ .../resources/views/.gitkeep | 0 .../views/components/layouts/master.blade.php | 30 + .../resources/views/index.blade.php | 5 + Modules/TimelineScheduling/routes/.gitkeep | 0 Modules/TimelineScheduling/routes/api.php | 8 + Modules/TimelineScheduling/routes/web.php | 11 + .../TimelineScheduling/tests/Feature/.gitkeep | 0 .../TimelineScheduling/tests/Unit/.gitkeep | 0 Modules/TimelineScheduling/vite.config.js | 41 + .../app/Http/Controllers/.gitkeep | 0 .../app/Http/Controllers/Controller.php | 9 + .../app/Http/Controllers/UserController.php | 476 ++++ .../Controllers/UserManagementController.php | 56 + .../Http/Middleware/EnsureUserIsActive.php | 23 + .../app/Livewire/UserManager.php | 117 + .../app/Models/CustomerProfile.php | 23 + .../app/Models/EmployeeProfile.php | 31 + Modules/UserManagement/app/Providers/.gitkeep | 0 .../app/Providers/EventServiceProvider.php | 27 + .../app/Providers/RouteServiceProvider.php | 50 + .../UserManagementServiceProvider.php | 46 + Modules/UserManagement/composer.json | 30 + Modules/UserManagement/config/.gitkeep | 0 Modules/UserManagement/config/config.php | 5 + .../database/factories/.gitkeep | 0 .../database/migrations/.gitkeep | 0 ..._user_management_fields_to_users_table.php | 27 + ..._100002_create_employee_profiles_table.php | 28 + ..._100003_create_customer_profiles_table.php | 27 + ...actor_to_user_type_enum_in_users_table.php | 18 + .../UserManagement/database/seeders/.gitkeep | 0 .../seeders/UserManagementDatabaseSeeder.php | 64 + Modules/UserManagement/module.json | 11 + Modules/UserManagement/package.json | 15 + .../UserManagement/resources/assets/.gitkeep | 0 .../UserManagement/resources/assets/js/app.js | 0 .../resources/assets/sass/app.scss | 0 .../resources/js/Pages/Users/BulkImport.tsx | 345 +++ .../js/Pages/Users/ChangePassword.tsx | 131 + .../resources/js/Pages/Users/Create.tsx | 386 +++ .../resources/js/Pages/Users/Edit.tsx | 327 +++ .../resources/js/Pages/Users/Index.tsx | 222 ++ .../resources/js/Pages/Users/Show.tsx | 170 ++ .../UserManagement/resources/views/.gitkeep | 0 .../views/components/layouts/master.blade.php | 30 + .../resources/views/index.blade.php | 5 + .../views/livewire/user-manager.blade.php | 115 + Modules/UserManagement/routes/.gitkeep | 0 Modules/UserManagement/routes/api.php | 8 + Modules/UserManagement/routes/web.php | 20 + Modules/UserManagement/tests/Feature/.gitkeep | 0 Modules/UserManagement/tests/Unit/.gitkeep | 0 Modules/UserManagement/vite.config.js | 41 + PLAN-contractor-admin.md | 52 + app/Http/Controllers/DashboardController.php | 63 + .../Middleware/CheckContractorHierarchy.php | 58 + app/Http/Middleware/EnforcePasswordChange.php | 33 + app/Http/Middleware/HandleInertiaRequests.php | 14 +- app/Http/Requests/Auth/LoginRequest.php | 9 + app/Models/User.php | 103 +- app/Observers/UserObserver.php | 52 + .../Modules/Support/ModuleServiceProvider.php | 89 + app/Providers/AppServiceProvider.php | 8 + app/Scopes/TenantScope.php | 86 + app/Traits/BelongsToTenant.php | 35 + app/Traits/HasPublicIdentifier.php | 32 + app/Traits/HasStateMachine.php | 84 + bootstrap/app.php | 7 +- check.php | 14 + components.json | 4 +- composer.json | 41 +- composer.lock | 2332 ++++++++++++----- config/modules.php | 2 +- .../2026_03_26_180000_add_ulid_columns.php | 73 + ...ock_threshold_to_warehouse_stock_table.php | 22 + ...target_warehouse_id_to_purchase_orders.php | 29 + ..._05_19_000000_create_contractors_table.php | 37 + ...1_add_contractor_fields_to_users_table.php | 29 + ...dd_scoping_and_catalog_sharing_columns.php | 37 + ...3_010000_add_user_provisioning_columns.php | 23 + .../ConstructionRolesAndPermissionsSeeder.php | 132 + database/seeders/DatabaseSeeder.php | 27 +- database/seeders/MainContractorSeeder.php | 55 + database/seeders/RolePermissionSeeder.php | 44 + .../seeders/RolesAndPermissionsSeeder.php | 79 + .../seeders/SuperAdminPermissionSeeder.php | 82 + database/seeders/SuperAdminSeeder.php | 93 + docs/PLAN-construction-erp.md | 10 +- docs/PLAN-contractor-onboarding.md | 108 + docs/PLAN-direct-permission-assignment.md | 72 + docs/PLAN-gantt-capitalization.md | 214 ++ docs/PLAN-inventory-operations.md | 59 + docs/PLAN-limit-roles.md | 47 + docs/PLAN-material-crud-views.md | 109 + docs/PLAN-material-select-tabs.md | 43 + docs/PLAN-material-validation-flow.md | 385 +++ docs/PLAN-po-transit-pipeline.md | 37 + docs/PLAN-pos-operations-ui.md | 40 + docs/PLAN-role-permission-fix.md | 49 + docs/PLAN-site-execution-dash.md | 46 + docs/PLAN-task-progress-bars.md | 103 + docs/PLAN.md | 61 + module_info.txt | Bin 0 -> 5254 bytes module_info_v12.txt | 0 modules_statuses.json | 22 + package-lock.json | 90 + package.json | 3 + postcss.config.js | 1 - project-warehouse-transition.md | 14 + resources/css/app.css | 21 +- resources/js/Components/AppSidebar.tsx | 255 ++ .../js/Components/Dashboard/ActivityFeed.tsx | 51 + .../js/Components/Dashboard/BlockerList.tsx | 85 + .../Components/Dashboard/ResourceSummary.tsx | 108 + .../js/Components/Dashboard/WeatherWidget.tsx | 53 + resources/js/Components/DataTableToolbar.tsx | 79 + .../js/Components/MaterialBrowserModal.tsx | 178 ++ .../js/Components/MaterialPickerModal.tsx | 322 +++ resources/js/Components/ui/avatar.tsx | 109 + resources/js/Components/ui/badge.tsx | 52 + resources/js/Components/ui/button.tsx | 15 +- resources/js/Components/ui/card.tsx | 103 + resources/js/Components/ui/checkbox.tsx | 24 + resources/js/Components/ui/dialog.tsx | 158 ++ resources/js/Components/ui/dropdown-menu.tsx | 266 ++ resources/js/Components/ui/form.tsx | 82 + resources/js/Components/ui/input.tsx | 24 + resources/js/Components/ui/label.tsx | 18 + resources/js/Components/ui/select.tsx | 201 ++ resources/js/Components/ui/separator.tsx | 25 + resources/js/Components/ui/sheet.tsx | 138 + resources/js/Components/ui/sidebar.tsx | 721 +++++ resources/js/Components/ui/skeleton.tsx | 13 + resources/js/Components/ui/sonner.tsx | 49 + resources/js/Components/ui/table.tsx | 114 + resources/js/Components/ui/tabs.tsx | 80 + resources/js/Components/ui/textarea.tsx | 22 + resources/js/Components/ui/tooltip.tsx | 66 + resources/js/Layouts/AuthenticatedLayout.tsx | 203 +- resources/js/Pages/Auth/Login.tsx | 725 ++++- resources/js/Pages/Dashboard.tsx | 67 +- resources/js/app.tsx | 26 +- resources/js/hooks/use-mobile.ts | 19 + resources/js/lib/nav-config.ts | 168 ++ resources/js/types/index.d.ts | 82 + resources/views/app.blade.php | 11 +- routes/web.php | 5 +- storage/clear_data.php | 42 + storage/test_po.php | 19 + test_po.php | 11 + test_po2.php | 13 + test_req.php | Bin 0 -> 486 bytes test_script.php | 1 + tests/Feature/ContractorOnboardingTest.php | 190 ++ tests/Feature/TenantScopeTest.php | 269 ++ tsconfig.json | 3 +- vite.config.js | 47 +- warehouse-drawer-lookup.md | 34 + 910 files changed, 49994 insertions(+), 1010 deletions(-) create mode 100644 Modules/ApprovalWorkflow/app/Enums/ApprovalChainStatus.php create mode 100644 Modules/ApprovalWorkflow/app/Enums/ApprovalStepStatus.php create mode 100644 Modules/ApprovalWorkflow/app/Events/ApprovalCompleted.php create mode 100644 Modules/ApprovalWorkflow/app/Events/ApprovalRequired.php create mode 100644 Modules/ApprovalWorkflow/app/Events/StepApproved.php create mode 100644 Modules/ApprovalWorkflow/app/Events/StepRejected.php create mode 100644 Modules/ApprovalWorkflow/app/Http/Controllers/.gitkeep create mode 100644 Modules/ApprovalWorkflow/app/Http/Controllers/ApprovalController.php create mode 100644 Modules/ApprovalWorkflow/app/Http/Controllers/ApprovalWorkflowController.php create mode 100644 Modules/ApprovalWorkflow/app/Listeners/SyncApprovableStatus.php create mode 100644 Modules/ApprovalWorkflow/app/Models/ApprovalChain.php create mode 100644 Modules/ApprovalWorkflow/app/Models/ApprovalStep.php create mode 100644 Modules/ApprovalWorkflow/app/Providers/.gitkeep create mode 100644 Modules/ApprovalWorkflow/app/Providers/ApprovalWorkflowServiceProvider.php create mode 100644 Modules/ApprovalWorkflow/app/Providers/EventServiceProvider.php create mode 100644 Modules/ApprovalWorkflow/app/Providers/RouteServiceProvider.php create mode 100644 Modules/ApprovalWorkflow/app/Services/ApprovalService.php create mode 100644 Modules/ApprovalWorkflow/app/Traits/HasApprovable.php create mode 100644 Modules/ApprovalWorkflow/composer.json create mode 100644 Modules/ApprovalWorkflow/config/.gitkeep create mode 100644 Modules/ApprovalWorkflow/config/config.php create mode 100644 Modules/ApprovalWorkflow/database/factories/.gitkeep create mode 100644 Modules/ApprovalWorkflow/database/migrations/.gitkeep create mode 100644 Modules/ApprovalWorkflow/database/migrations/2026_03_24_210001_create_approval_tables.php create mode 100644 Modules/ApprovalWorkflow/database/seeders/.gitkeep create mode 100644 Modules/ApprovalWorkflow/database/seeders/ApprovalWorkflowDatabaseSeeder.php create mode 100644 Modules/ApprovalWorkflow/module.json create mode 100644 Modules/ApprovalWorkflow/package.json create mode 100644 Modules/ApprovalWorkflow/resources/assets/.gitkeep create mode 100644 Modules/ApprovalWorkflow/resources/assets/js/app.js create mode 100644 Modules/ApprovalWorkflow/resources/assets/sass/app.scss create mode 100644 Modules/ApprovalWorkflow/resources/js/Components/ApprovableBreakdown.tsx create mode 100644 Modules/ApprovalWorkflow/resources/js/Components/ApprovalTimeline.tsx create mode 100644 Modules/ApprovalWorkflow/resources/js/Pages/Approvals/Index.tsx create mode 100644 Modules/ApprovalWorkflow/resources/js/Pages/Approvals/Show.tsx create mode 100644 Modules/ApprovalWorkflow/resources/views/.gitkeep create mode 100644 Modules/ApprovalWorkflow/resources/views/components/layouts/master.blade.php create mode 100644 Modules/ApprovalWorkflow/resources/views/index.blade.php create mode 100644 Modules/ApprovalWorkflow/routes/.gitkeep create mode 100644 Modules/ApprovalWorkflow/routes/api.php create mode 100644 Modules/ApprovalWorkflow/routes/web.php create mode 100644 Modules/ApprovalWorkflow/tests/Feature/.gitkeep create mode 100644 Modules/ApprovalWorkflow/tests/Unit/.gitkeep create mode 100644 Modules/ApprovalWorkflow/vite.config.js create mode 100644 Modules/BiddingManagement/app/Enums/BidPackageStatus.php create mode 100644 Modules/BiddingManagement/app/Enums/BidSubmissionStatus.php create mode 100644 Modules/BiddingManagement/app/Enums/EvaluationMode.php create mode 100644 Modules/BiddingManagement/app/Events/BidAwarded.php create mode 100644 Modules/BiddingManagement/app/Events/BidPackageOpened.php create mode 100644 Modules/BiddingManagement/app/Events/BidSubmitted.php create mode 100644 Modules/BiddingManagement/app/Http/Controllers/BidAwardController.php create mode 100644 Modules/BiddingManagement/app/Http/Controllers/BidInvitationController.php create mode 100644 Modules/BiddingManagement/app/Http/Controllers/BidPackageController.php create mode 100644 Modules/BiddingManagement/app/Http/Controllers/BidScoreController.php create mode 100644 Modules/BiddingManagement/app/Http/Controllers/BidSubmissionController.php create mode 100644 Modules/BiddingManagement/app/Models/BidAward.php create mode 100644 Modules/BiddingManagement/app/Models/BidCriteria.php create mode 100644 Modules/BiddingManagement/app/Models/BidInvitation.php create mode 100644 Modules/BiddingManagement/app/Models/BidPackage.php create mode 100644 Modules/BiddingManagement/app/Models/BidScore.php create mode 100644 Modules/BiddingManagement/app/Models/BidSubmission.php create mode 100644 Modules/BiddingManagement/app/Providers/BiddingManagementServiceProvider.php create mode 100644 Modules/BiddingManagement/app/Providers/EventServiceProvider.php create mode 100644 Modules/BiddingManagement/app/Providers/RouteServiceProvider.php create mode 100644 Modules/BiddingManagement/composer.json create mode 100644 Modules/BiddingManagement/database/migrations/2026_05_23_000001_create_bidding_tables.php create mode 100644 Modules/BiddingManagement/module.json create mode 100644 Modules/BiddingManagement/package.json create mode 100644 Modules/BiddingManagement/resources/js/Pages/Bids/Contractor/MyBids.tsx create mode 100644 Modules/BiddingManagement/resources/js/Pages/Bids/Contractor/Submit.tsx create mode 100644 Modules/BiddingManagement/resources/js/Pages/Bids/Create.tsx create mode 100644 Modules/BiddingManagement/resources/js/Pages/Bids/Edit.tsx create mode 100644 Modules/BiddingManagement/resources/js/Pages/Bids/Form.tsx create mode 100644 Modules/BiddingManagement/resources/js/Pages/Bids/Index.tsx create mode 100644 Modules/BiddingManagement/resources/js/Pages/Bids/Show.tsx create mode 100644 Modules/BiddingManagement/routes/api.php create mode 100644 Modules/BiddingManagement/routes/web.php create mode 100644 Modules/BiddingManagement/vite.config.js create mode 100644 Modules/ContractorManagement/app/Enums/EquipmentStatus.php create mode 100644 Modules/ContractorManagement/app/Enums/InvoiceStatus.php create mode 100644 Modules/ContractorManagement/app/Events/ContractorApproved.php create mode 100644 Modules/ContractorManagement/app/Events/ContractorAssignedToProject.php create mode 100644 Modules/ContractorManagement/app/Events/ContractorInvoicePaid.php create mode 100644 Modules/ContractorManagement/app/Events/ContractorInvoiceSubmitted.php create mode 100644 Modules/ContractorManagement/app/Events/ContractorOnboarded.php create mode 100644 Modules/ContractorManagement/app/Http/Controllers/.gitkeep create mode 100644 Modules/ContractorManagement/app/Http/Controllers/ContractorController.php create mode 100644 Modules/ContractorManagement/app/Http/Controllers/ContractorManagementController.php create mode 100644 Modules/ContractorManagement/app/Http/Controllers/ContractorOnboardingController.php create mode 100644 Modules/ContractorManagement/app/Livewire/ContractorManager.php create mode 100644 Modules/ContractorManagement/app/Models/Contractor.php create mode 100644 Modules/ContractorManagement/app/Models/ContractorCertification.php create mode 100644 Modules/ContractorManagement/app/Models/ContractorEquipment.php create mode 100644 Modules/ContractorManagement/app/Models/ContractorInvoice.php create mode 100644 Modules/ContractorManagement/app/Models/ContractorPayment.php create mode 100644 Modules/ContractorManagement/app/Models/EquipmentDeployment.php create mode 100644 Modules/ContractorManagement/app/Providers/.gitkeep create mode 100644 Modules/ContractorManagement/app/Providers/ContractorManagementServiceProvider.php create mode 100644 Modules/ContractorManagement/app/Providers/EventServiceProvider.php create mode 100644 Modules/ContractorManagement/app/Providers/RouteServiceProvider.php create mode 100644 Modules/ContractorManagement/composer.json create mode 100644 Modules/ContractorManagement/config/.gitkeep create mode 100644 Modules/ContractorManagement/config/config.php create mode 100644 Modules/ContractorManagement/database/factories/.gitkeep create mode 100644 Modules/ContractorManagement/database/migrations/.gitkeep create mode 100644 Modules/ContractorManagement/database/migrations/2026_03_24_220001_create_contractor_tables.php create mode 100644 Modules/ContractorManagement/database/seeders/.gitkeep create mode 100644 Modules/ContractorManagement/database/seeders/ContractorManagementDatabaseSeeder.php create mode 100644 Modules/ContractorManagement/module.json create mode 100644 Modules/ContractorManagement/package.json create mode 100644 Modules/ContractorManagement/resources/assets/.gitkeep create mode 100644 Modules/ContractorManagement/resources/assets/js/app.js create mode 100644 Modules/ContractorManagement/resources/assets/sass/app.scss create mode 100644 Modules/ContractorManagement/resources/js/Pages/Contractors/Create.tsx create mode 100644 Modules/ContractorManagement/resources/js/Pages/Contractors/Edit.tsx create mode 100644 Modules/ContractorManagement/resources/js/Pages/Contractors/Form.tsx create mode 100644 Modules/ContractorManagement/resources/js/Pages/Contractors/Index.tsx create mode 100644 Modules/ContractorManagement/resources/js/Pages/Contractors/Show.tsx create mode 100644 Modules/ContractorManagement/resources/views/.gitkeep create mode 100644 Modules/ContractorManagement/resources/views/components/layouts/master.blade.php create mode 100644 Modules/ContractorManagement/resources/views/index.blade.php create mode 100644 Modules/ContractorManagement/resources/views/livewire/contractor-manager.blade.php create mode 100644 Modules/ContractorManagement/routes/.gitkeep create mode 100644 Modules/ContractorManagement/routes/api.php create mode 100644 Modules/ContractorManagement/routes/web.php create mode 100644 Modules/ContractorManagement/tests/Feature/.gitkeep create mode 100644 Modules/ContractorManagement/tests/Unit/.gitkeep create mode 100644 Modules/ContractorManagement/vite.config.js create mode 100644 Modules/DailyReports/app/Http/Controllers/.gitkeep create mode 100644 Modules/DailyReports/app/Http/Controllers/DailyReportsController.php create mode 100644 Modules/DailyReports/app/Http/Requests/StoreDailyReportRequest.php create mode 100644 Modules/DailyReports/app/Http/Requests/UpdateDailyReportRequest.php create mode 100644 Modules/DailyReports/app/Models/DailyReport.php create mode 100644 Modules/DailyReports/app/Models/DailyReportActivity.php create mode 100644 Modules/DailyReports/app/Models/DailyReportEquipment.php create mode 100644 Modules/DailyReports/app/Models/DailyReportIssue.php create mode 100644 Modules/DailyReports/app/Models/DailyReportLabor.php create mode 100644 Modules/DailyReports/app/Models/DailyReportMaterial.php create mode 100644 Modules/DailyReports/app/Providers/.gitkeep create mode 100644 Modules/DailyReports/app/Providers/DailyReportsServiceProvider.php create mode 100644 Modules/DailyReports/app/Providers/EventServiceProvider.php create mode 100644 Modules/DailyReports/app/Providers/RouteServiceProvider.php create mode 100644 Modules/DailyReports/composer.json create mode 100644 Modules/DailyReports/config/.gitkeep create mode 100644 Modules/DailyReports/config/config.php create mode 100644 Modules/DailyReports/database/factories/.gitkeep create mode 100644 Modules/DailyReports/database/migrations/.gitkeep create mode 100644 Modules/DailyReports/database/migrations/2026_05_24_091000_create_daily_reports_table.php create mode 100644 Modules/DailyReports/database/migrations/2026_05_25_000001_create_daily_report_labors_table.php create mode 100644 Modules/DailyReports/database/migrations/2026_05_25_000002_create_daily_report_equipment_table.php create mode 100644 Modules/DailyReports/database/migrations/2026_05_25_000003_create_daily_report_activities_table.php create mode 100644 Modules/DailyReports/database/migrations/2026_05_25_000004_create_daily_report_materials_table.php create mode 100644 Modules/DailyReports/database/migrations/2026_05_25_000005_create_daily_report_issues_table.php create mode 100644 Modules/DailyReports/database/migrations/2026_05_25_000006_add_new_fields_to_daily_reports_table.php create mode 100644 Modules/DailyReports/database/seeders/.gitkeep create mode 100644 Modules/DailyReports/database/seeders/DailyReportsDatabaseSeeder.php create mode 100644 Modules/DailyReports/module.json create mode 100644 Modules/DailyReports/package.json create mode 100644 Modules/DailyReports/resources/assets/.gitkeep create mode 100644 Modules/DailyReports/resources/assets/js/app.js create mode 100644 Modules/DailyReports/resources/assets/sass/app.scss create mode 100644 Modules/DailyReports/resources/js/Pages/Create.tsx create mode 100644 Modules/DailyReports/resources/js/Pages/Edit.tsx create mode 100644 Modules/DailyReports/resources/js/Pages/Index.tsx create mode 100644 Modules/DailyReports/resources/js/Pages/Partials/ReportForm.tsx create mode 100644 Modules/DailyReports/resources/js/Pages/Show.tsx create mode 100644 Modules/DailyReports/resources/views/.gitkeep create mode 100644 Modules/DailyReports/resources/views/components/layouts/master.blade.php create mode 100644 Modules/DailyReports/resources/views/index.blade.php create mode 100644 Modules/DailyReports/routes/.gitkeep create mode 100644 Modules/DailyReports/routes/api.php create mode 100644 Modules/DailyReports/routes/web.php create mode 100644 Modules/DailyReports/tests/Feature/.gitkeep create mode 100644 Modules/DailyReports/tests/Unit/.gitkeep create mode 100644 Modules/DailyReports/vite.config.js create mode 100644 Modules/DocumentManagement/app/Http/Controllers/.gitkeep create mode 100644 Modules/DocumentManagement/app/Http/Controllers/DocumentApprovalController.php create mode 100644 Modules/DocumentManagement/app/Http/Controllers/DocumentController.php create mode 100644 Modules/DocumentManagement/app/Http/Controllers/DocumentManagementController.php create mode 100644 Modules/DocumentManagement/app/Listeners/DocumentApprovalListener.php create mode 100644 Modules/DocumentManagement/app/Models/Document.php create mode 100644 Modules/DocumentManagement/app/Models/DocumentApproval.php create mode 100644 Modules/DocumentManagement/app/Models/DocumentCategory.php create mode 100644 Modules/DocumentManagement/app/Models/DocumentVersion.php create mode 100644 Modules/DocumentManagement/app/Policies/DocumentPolicy.php create mode 100644 Modules/DocumentManagement/app/Providers/.gitkeep create mode 100644 Modules/DocumentManagement/app/Providers/DocumentManagementServiceProvider.php create mode 100644 Modules/DocumentManagement/app/Providers/EventServiceProvider.php create mode 100644 Modules/DocumentManagement/app/Providers/RouteServiceProvider.php create mode 100644 Modules/DocumentManagement/composer.json create mode 100644 Modules/DocumentManagement/config/.gitkeep create mode 100644 Modules/DocumentManagement/config/config.php create mode 100644 Modules/DocumentManagement/database/factories/.gitkeep create mode 100644 Modules/DocumentManagement/database/migrations/.gitkeep create mode 100644 Modules/DocumentManagement/database/migrations/2026_03_25_010001_create_document_tables.php create mode 100644 Modules/DocumentManagement/database/migrations/2026_05_25_042939_create_document_categories_table.php create mode 100644 Modules/DocumentManagement/database/migrations/2026_05_25_042940_create_document_approvals_table.php create mode 100644 Modules/DocumentManagement/database/migrations/2026_05_25_043000_add_status_and_project_to_documents_table.php create mode 100644 Modules/DocumentManagement/database/migrations/2026_05_25_044442_make_documentable_nullable_on_documents_table.php create mode 100644 Modules/DocumentManagement/database/migrations/2026_05_25_044801_make_category_nullable_on_documents_table.php create mode 100644 Modules/DocumentManagement/database/seeders/.gitkeep create mode 100644 Modules/DocumentManagement/database/seeders/DocumentManagementDatabaseSeeder.php create mode 100644 Modules/DocumentManagement/module.json create mode 100644 Modules/DocumentManagement/package.json create mode 100644 Modules/DocumentManagement/resources/assets/.gitkeep create mode 100644 Modules/DocumentManagement/resources/assets/js/app.js create mode 100644 Modules/DocumentManagement/resources/assets/sass/app.scss create mode 100644 Modules/DocumentManagement/resources/js/Pages/Documents/Index.tsx create mode 100644 Modules/DocumentManagement/resources/js/Pages/Documents/Versions.tsx create mode 100644 Modules/DocumentManagement/resources/views/.gitkeep create mode 100644 Modules/DocumentManagement/resources/views/components/layouts/master.blade.php create mode 100644 Modules/DocumentManagement/resources/views/index.blade.php create mode 100644 Modules/DocumentManagement/routes/.gitkeep create mode 100644 Modules/DocumentManagement/routes/api.php create mode 100644 Modules/DocumentManagement/routes/web.php create mode 100644 Modules/DocumentManagement/tests/Feature/.gitkeep create mode 100644 Modules/DocumentManagement/tests/Unit/.gitkeep create mode 100644 Modules/DocumentManagement/vite.config.js create mode 100644 Modules/FinancialManagement/app/Enums/InvoiceStatus.php create mode 100644 Modules/FinancialManagement/app/Http/Controllers/.gitkeep create mode 100644 Modules/FinancialManagement/app/Http/Controllers/FinanceController.php create mode 100644 Modules/FinancialManagement/app/Http/Controllers/FinancialManagementController.php create mode 100644 Modules/FinancialManagement/app/Models/FinancialInvoice.php create mode 100644 Modules/FinancialManagement/app/Models/InvoiceLineItem.php create mode 100644 Modules/FinancialManagement/app/Models/RetentionEntry.php create mode 100644 Modules/FinancialManagement/app/Providers/.gitkeep create mode 100644 Modules/FinancialManagement/app/Providers/EventServiceProvider.php create mode 100644 Modules/FinancialManagement/app/Providers/FinancialManagementServiceProvider.php create mode 100644 Modules/FinancialManagement/app/Providers/RouteServiceProvider.php create mode 100644 Modules/FinancialManagement/app/Services/ProgressBillingService.php create mode 100644 Modules/FinancialManagement/composer.json create mode 100644 Modules/FinancialManagement/config/.gitkeep create mode 100644 Modules/FinancialManagement/config/config.php create mode 100644 Modules/FinancialManagement/database/factories/.gitkeep create mode 100644 Modules/FinancialManagement/database/migrations/.gitkeep create mode 100644 Modules/FinancialManagement/database/migrations/2026_03_25_000001_create_financial_tables.php create mode 100644 Modules/FinancialManagement/database/seeders/.gitkeep create mode 100644 Modules/FinancialManagement/database/seeders/FinancialManagementDatabaseSeeder.php create mode 100644 Modules/FinancialManagement/module.json create mode 100644 Modules/FinancialManagement/package.json create mode 100644 Modules/FinancialManagement/resources/assets/.gitkeep create mode 100644 Modules/FinancialManagement/resources/assets/js/app.js create mode 100644 Modules/FinancialManagement/resources/assets/sass/app.scss create mode 100644 Modules/FinancialManagement/resources/js/Pages/Invoices/Create.tsx create mode 100644 Modules/FinancialManagement/resources/js/Pages/Invoices/Index.tsx create mode 100644 Modules/FinancialManagement/resources/js/Pages/Invoices/Show.tsx create mode 100644 Modules/FinancialManagement/resources/js/Pages/Retention/Index.tsx create mode 100644 Modules/FinancialManagement/resources/views/.gitkeep create mode 100644 Modules/FinancialManagement/resources/views/components/layouts/master.blade.php create mode 100644 Modules/FinancialManagement/resources/views/index.blade.php create mode 100644 Modules/FinancialManagement/routes/.gitkeep create mode 100644 Modules/FinancialManagement/routes/api.php create mode 100644 Modules/FinancialManagement/routes/web.php create mode 100644 Modules/FinancialManagement/tests/Feature/.gitkeep create mode 100644 Modules/FinancialManagement/tests/Unit/.gitkeep create mode 100644 Modules/FinancialManagement/vite.config.js create mode 100644 Modules/MasterData/app/Exports/BoqTemplateExport.php create mode 100644 Modules/MasterData/app/Exports/MaterialTemplateExport.php create mode 100644 Modules/MasterData/app/Http/Controllers/.gitkeep create mode 100644 Modules/MasterData/app/Http/Controllers/MasterDataController.php create mode 100644 Modules/MasterData/app/Http/Controllers/MaterialGroupController.php create mode 100644 Modules/MasterData/app/Http/Controllers/MaterialImportController.php create mode 100644 Modules/MasterData/app/Imports/BoqImport.php create mode 100644 Modules/MasterData/app/Imports/MaterialImport.php create mode 100644 Modules/MasterData/app/Models/Material.php create mode 100644 Modules/MasterData/app/Models/MaterialComponent.php create mode 100644 Modules/MasterData/app/Models/MaterialGroup.php create mode 100644 Modules/MasterData/app/Models/MaterialGroupItem.php create mode 100644 Modules/MasterData/app/Providers/.gitkeep create mode 100644 Modules/MasterData/app/Providers/EventServiceProvider.php create mode 100644 Modules/MasterData/app/Providers/MasterDataServiceProvider.php create mode 100644 Modules/MasterData/app/Providers/RouteServiceProvider.php create mode 100644 Modules/MasterData/composer.json create mode 100644 Modules/MasterData/config/.gitkeep create mode 100644 Modules/MasterData/config/config.php create mode 100644 Modules/MasterData/database/factories/.gitkeep create mode 100644 Modules/MasterData/database/migrations/.gitkeep create mode 100644 Modules/MasterData/database/migrations/2026_04_14_073525_add_type_to_materials_table.php create mode 100644 Modules/MasterData/database/migrations/2026_04_14_073534_create_material_components_table.php create mode 100644 Modules/MasterData/database/seeders/.gitkeep create mode 100644 Modules/MasterData/database/seeders/MasterDataDatabaseSeeder.php create mode 100644 Modules/MasterData/module.json create mode 100644 Modules/MasterData/package.json create mode 100644 Modules/MasterData/resources/assets/.gitkeep create mode 100644 Modules/MasterData/resources/assets/js/app.js create mode 100644 Modules/MasterData/resources/assets/sass/app.scss create mode 100644 Modules/MasterData/resources/views/.gitkeep create mode 100644 Modules/MasterData/resources/views/components/layouts/master.blade.php create mode 100644 Modules/MasterData/resources/views/index.blade.php create mode 100644 Modules/MasterData/routes/.gitkeep create mode 100644 Modules/MasterData/routes/api.php create mode 100644 Modules/MasterData/routes/web.php create mode 100644 Modules/MasterData/tests/Feature/.gitkeep create mode 100644 Modules/MasterData/tests/Unit/.gitkeep create mode 100644 Modules/MasterData/vite.config.js create mode 100644 Modules/MaterialLogistics/app/Enums/DeploymentStatus.php create mode 100644 Modules/MaterialLogistics/app/Enums/MaterialTransferStatus.php create mode 100644 Modules/MaterialLogistics/app/Enums/MovementType.php create mode 100644 Modules/MaterialLogistics/app/Enums/PaymentStatus.php create mode 100644 Modules/MaterialLogistics/app/Enums/WarehouseType.php create mode 100644 Modules/MaterialLogistics/app/Events/MaterialDelivered.php create mode 100644 Modules/MaterialLogistics/app/Events/MaterialRequested.php create mode 100644 Modules/MaterialLogistics/app/Events/PurchaseOrderPaid.php create mode 100644 Modules/MaterialLogistics/app/Http/Controllers/.gitkeep create mode 100644 Modules/MaterialLogistics/app/Http/Controllers/InventoryMovementController.php create mode 100644 Modules/MaterialLogistics/app/Http/Controllers/MaterialController.php create mode 100644 Modules/MaterialLogistics/app/Http/Controllers/MaterialLogisticsController.php create mode 100644 Modules/MaterialLogistics/app/Http/Controllers/MaterialRequisitionController.php create mode 100644 Modules/MaterialLogistics/app/Http/Controllers/MaterialTransferController.php create mode 100644 Modules/MaterialLogistics/app/Http/Controllers/PurchaseOrderController.php create mode 100644 Modules/MaterialLogistics/app/Http/Controllers/WarehouseController.php create mode 100644 Modules/MaterialLogistics/app/Listeners/HandlePurchaseOrderPaid.php create mode 100644 Modules/MaterialLogistics/app/Models/InventoryBatch.php create mode 100644 Modules/MaterialLogistics/app/Models/InventoryMovement.php create mode 100644 Modules/MaterialLogistics/app/Models/MaterialDeployment.php create mode 100644 Modules/MaterialLogistics/app/Models/MaterialRequirement.php create mode 100644 Modules/MaterialLogistics/app/Models/MaterialRequisition.php create mode 100644 Modules/MaterialLogistics/app/Models/MaterialRequisitionItem.php create mode 100644 Modules/MaterialLogistics/app/Models/MaterialTransfer.php create mode 100644 Modules/MaterialLogistics/app/Models/MaterialTransferItem.php create mode 100644 Modules/MaterialLogistics/app/Models/ProjectInventory.php create mode 100644 Modules/MaterialLogistics/app/Models/PurchaseOrder.php create mode 100644 Modules/MaterialLogistics/app/Models/PurchaseOrderItem.php create mode 100644 Modules/MaterialLogistics/app/Models/Warehouse.php create mode 100644 Modules/MaterialLogistics/app/Models/WarehouseStock.php create mode 100644 Modules/MaterialLogistics/app/Providers/.gitkeep create mode 100644 Modules/MaterialLogistics/app/Providers/EventServiceProvider.php create mode 100644 Modules/MaterialLogistics/app/Providers/MaterialLogisticsServiceProvider.php create mode 100644 Modules/MaterialLogistics/app/Providers/RouteServiceProvider.php create mode 100644 Modules/MaterialLogistics/app/Services/DocumentNumberService.php create mode 100644 Modules/MaterialLogistics/app/Services/InventoryService.php create mode 100644 Modules/MaterialLogistics/app/Services/WarehouseService.php create mode 100644 Modules/MaterialLogistics/composer.json create mode 100644 Modules/MaterialLogistics/config/.gitkeep create mode 100644 Modules/MaterialLogistics/config/config.php create mode 100644 Modules/MaterialLogistics/database/factories/.gitkeep create mode 100644 Modules/MaterialLogistics/database/migrations/.gitkeep create mode 100644 Modules/MaterialLogistics/database/migrations/2026_03_24_230001_create_material_tables.php create mode 100644 Modules/MaterialLogistics/database/migrations/2026_03_27_000001_create_material_group_tables.php create mode 100644 Modules/MaterialLogistics/database/migrations/2026_03_28_000001_create_mr_po_tables.php create mode 100644 Modules/MaterialLogistics/database/migrations/2026_03_29_000001_create_warehouse_inventory_system.php create mode 100644 Modules/MaterialLogistics/database/migrations/2026_04_08_000001_add_personnel_tracking_to_inventory_movements.php create mode 100644 Modules/MaterialLogistics/database/migrations/2026_04_14_000001_remove_project_id_from_procurement.php create mode 100644 Modules/MaterialLogistics/database/migrations/2026_04_14_000002_create_inventory_batches_table.php create mode 100644 Modules/MaterialLogistics/database/migrations/2026_04_14_000003_add_batch_and_requisition_ids.php create mode 100644 Modules/MaterialLogistics/database/migrations/2026_05_13_000000_add_project_id_to_warehouses_table.php create mode 100644 Modules/MaterialLogistics/database/migrations/2026_05_13_000001_create_material_transfers_table.php create mode 100644 Modules/MaterialLogistics/database/seeders/.gitkeep create mode 100644 Modules/MaterialLogistics/database/seeders/ConstructionMaterialsSeeder.php create mode 100644 Modules/MaterialLogistics/database/seeders/MaterialLogisticsDatabaseSeeder.php create mode 100644 Modules/MaterialLogistics/module.json create mode 100644 Modules/MaterialLogistics/package.json create mode 100644 Modules/MaterialLogistics/resources/assets/.gitkeep create mode 100644 Modules/MaterialLogistics/resources/assets/js/app.js create mode 100644 Modules/MaterialLogistics/resources/assets/sass/app.scss create mode 100644 Modules/MaterialLogistics/resources/js/Pages/Deployments/Index.tsx create mode 100644 Modules/MaterialLogistics/resources/js/Pages/Groups/Index.tsx create mode 100644 Modules/MaterialLogistics/resources/js/Pages/Inventory/Index.tsx create mode 100644 Modules/MaterialLogistics/resources/js/Pages/Inventory/Movements.tsx create mode 100644 Modules/MaterialLogistics/resources/js/Pages/Inventory/OperationsForm.tsx create mode 100644 Modules/MaterialLogistics/resources/js/Pages/Materials/Index.tsx create mode 100644 Modules/MaterialLogistics/resources/js/Pages/PurchaseOrders/Form.tsx create mode 100644 Modules/MaterialLogistics/resources/js/Pages/PurchaseOrders/Index.tsx create mode 100644 Modules/MaterialLogistics/resources/js/Pages/PurchaseOrders/Show.tsx create mode 100644 Modules/MaterialLogistics/resources/js/Pages/Requirements/Index.tsx create mode 100644 Modules/MaterialLogistics/resources/js/Pages/Requisitions/Form.tsx create mode 100644 Modules/MaterialLogistics/resources/js/Pages/Requisitions/Index.tsx create mode 100644 Modules/MaterialLogistics/resources/js/Pages/Requisitions/MaterialCatalogModal.tsx create mode 100644 Modules/MaterialLogistics/resources/js/Pages/Requisitions/Show.tsx create mode 100644 Modules/MaterialLogistics/resources/js/Pages/Transfers/Create.tsx create mode 100644 Modules/MaterialLogistics/resources/js/Pages/Transfers/Index.tsx create mode 100644 Modules/MaterialLogistics/resources/js/Pages/Transfers/Show.tsx create mode 100644 Modules/MaterialLogistics/resources/js/Pages/Warehouses/Form.tsx create mode 100644 Modules/MaterialLogistics/resources/js/Pages/Warehouses/Index.tsx create mode 100644 Modules/MaterialLogistics/resources/js/Pages/Warehouses/Show.tsx create mode 100644 Modules/MaterialLogistics/resources/views/.gitkeep create mode 100644 Modules/MaterialLogistics/resources/views/components/layouts/master.blade.php create mode 100644 Modules/MaterialLogistics/resources/views/index.blade.php create mode 100644 Modules/MaterialLogistics/resources/views/pdf/material-requisition.blade.php create mode 100644 Modules/MaterialLogistics/resources/views/pdf/purchase-order.blade.php create mode 100644 Modules/MaterialLogistics/routes/.gitkeep create mode 100644 Modules/MaterialLogistics/routes/api.php create mode 100644 Modules/MaterialLogistics/routes/web.php create mode 100644 Modules/MaterialLogistics/tests/Feature/.gitkeep create mode 100644 Modules/MaterialLogistics/tests/Unit/.gitkeep create mode 100644 Modules/MaterialLogistics/vite.config.js create mode 100644 Modules/MaterialsCatalog/app/Http/Controllers/.gitkeep create mode 100644 Modules/MaterialsCatalog/app/Http/Controllers/ItemController.php create mode 100644 Modules/MaterialsCatalog/app/Http/Controllers/KitController.php create mode 100644 Modules/MaterialsCatalog/app/Http/Controllers/MaterialsCatalogController.php create mode 100644 Modules/MaterialsCatalog/app/Providers/.gitkeep create mode 100644 Modules/MaterialsCatalog/app/Providers/EventServiceProvider.php create mode 100644 Modules/MaterialsCatalog/app/Providers/MaterialsCatalogServiceProvider.php create mode 100644 Modules/MaterialsCatalog/app/Providers/RouteServiceProvider.php create mode 100644 Modules/MaterialsCatalog/composer.json create mode 100644 Modules/MaterialsCatalog/config/.gitkeep create mode 100644 Modules/MaterialsCatalog/config/config.php create mode 100644 Modules/MaterialsCatalog/database/factories/.gitkeep create mode 100644 Modules/MaterialsCatalog/database/migrations/.gitkeep create mode 100644 Modules/MaterialsCatalog/database/seeders/.gitkeep create mode 100644 Modules/MaterialsCatalog/database/seeders/MaterialsCatalogDatabaseSeeder.php create mode 100644 Modules/MaterialsCatalog/module.json create mode 100644 Modules/MaterialsCatalog/package.json create mode 100644 Modules/MaterialsCatalog/resources/assets/.gitkeep create mode 100644 Modules/MaterialsCatalog/resources/assets/js/app.js create mode 100644 Modules/MaterialsCatalog/resources/assets/sass/app.scss create mode 100644 Modules/MaterialsCatalog/resources/js/Pages/Items/Form.tsx create mode 100644 Modules/MaterialsCatalog/resources/js/Pages/Items/Index.tsx create mode 100644 Modules/MaterialsCatalog/resources/js/Pages/MaterialsCatalog/Form.tsx create mode 100644 Modules/MaterialsCatalog/resources/js/Pages/MaterialsCatalog/Index.tsx create mode 100644 Modules/MaterialsCatalog/resources/views/.gitkeep create mode 100644 Modules/MaterialsCatalog/resources/views/components/layouts/master.blade.php create mode 100644 Modules/MaterialsCatalog/resources/views/index.blade.php create mode 100644 Modules/MaterialsCatalog/routes/.gitkeep create mode 100644 Modules/MaterialsCatalog/routes/api.php create mode 100644 Modules/MaterialsCatalog/routes/web.php create mode 100644 Modules/MaterialsCatalog/tests/Feature/.gitkeep create mode 100644 Modules/MaterialsCatalog/tests/Unit/.gitkeep create mode 100644 Modules/MaterialsCatalog/vite.config.js create mode 100644 Modules/ProjectDocuments/app/Http/Controllers/.gitkeep create mode 100644 Modules/ProjectDocuments/app/Http/Controllers/ProjectDocumentsController.php create mode 100644 Modules/ProjectDocuments/app/Providers/.gitkeep create mode 100644 Modules/ProjectDocuments/app/Providers/EventServiceProvider.php create mode 100644 Modules/ProjectDocuments/app/Providers/ProjectDocumentsServiceProvider.php create mode 100644 Modules/ProjectDocuments/app/Providers/RouteServiceProvider.php create mode 100644 Modules/ProjectDocuments/composer.json create mode 100644 Modules/ProjectDocuments/config/.gitkeep create mode 100644 Modules/ProjectDocuments/config/config.php create mode 100644 Modules/ProjectDocuments/database/factories/.gitkeep create mode 100644 Modules/ProjectDocuments/database/migrations/.gitkeep create mode 100644 Modules/ProjectDocuments/database/seeders/.gitkeep create mode 100644 Modules/ProjectDocuments/database/seeders/ProjectDocumentsDatabaseSeeder.php create mode 100644 Modules/ProjectDocuments/module.json create mode 100644 Modules/ProjectDocuments/package.json create mode 100644 Modules/ProjectDocuments/resources/assets/.gitkeep create mode 100644 Modules/ProjectDocuments/resources/assets/js/app.js create mode 100644 Modules/ProjectDocuments/resources/assets/sass/app.scss create mode 100644 Modules/ProjectDocuments/resources/views/.gitkeep create mode 100644 Modules/ProjectDocuments/resources/views/components/layouts/master.blade.php create mode 100644 Modules/ProjectDocuments/resources/views/index.blade.php create mode 100644 Modules/ProjectDocuments/routes/.gitkeep create mode 100644 Modules/ProjectDocuments/routes/api.php create mode 100644 Modules/ProjectDocuments/routes/web.php create mode 100644 Modules/ProjectDocuments/tests/Feature/.gitkeep create mode 100644 Modules/ProjectDocuments/tests/Unit/.gitkeep create mode 100644 Modules/ProjectDocuments/vite.config.js create mode 100644 Modules/ProjectManagement/app/Enums/DelayReason.php create mode 100644 Modules/ProjectManagement/app/Enums/ProjectStatus.php create mode 100644 Modules/ProjectManagement/app/Enums/ReportStatus.php create mode 100644 Modules/ProjectManagement/app/Enums/TaskStatus.php create mode 100644 Modules/ProjectManagement/app/Enums/WeatherCondition.php create mode 100644 Modules/ProjectManagement/app/Events/ProjectStatusChanged.php create mode 100644 Modules/ProjectManagement/app/Events/TaskCompleted.php create mode 100644 Modules/ProjectManagement/app/Exports/TaskTemplateExport.php create mode 100644 Modules/ProjectManagement/app/Http/Controllers/.gitkeep create mode 100644 Modules/ProjectManagement/app/Http/Controllers/ProjectController.php create mode 100644 Modules/ProjectManagement/app/Http/Controllers/ProjectManagementController.php create mode 100644 Modules/ProjectManagement/app/Imports/TaskImport.php create mode 100644 Modules/ProjectManagement/app/Models/HseRecord.php create mode 100644 Modules/ProjectManagement/app/Models/Project.php create mode 100644 Modules/ProjectManagement/app/Models/ProjectMilestone.php create mode 100644 Modules/ProjectManagement/app/Models/Task.php create mode 100644 Modules/ProjectManagement/app/Models/TaskActivity.php create mode 100644 Modules/ProjectManagement/app/Models/TaskDelay.php create mode 100644 Modules/ProjectManagement/app/Models/TaskMaterial.php create mode 100644 Modules/ProjectManagement/app/Models/WeeklyStatusReport.php create mode 100644 Modules/ProjectManagement/app/Models/WorkforceMetric.php create mode 100644 Modules/ProjectManagement/app/Observers/ProjectObserver.php create mode 100644 Modules/ProjectManagement/app/Providers/.gitkeep create mode 100644 Modules/ProjectManagement/app/Providers/EventServiceProvider.php create mode 100644 Modules/ProjectManagement/app/Providers/ProjectManagementServiceProvider.php create mode 100644 Modules/ProjectManagement/app/Providers/RouteServiceProvider.php create mode 100644 Modules/ProjectManagement/composer.json create mode 100644 Modules/ProjectManagement/config/.gitkeep create mode 100644 Modules/ProjectManagement/config/config.php create mode 100644 Modules/ProjectManagement/database/factories/.gitkeep create mode 100644 Modules/ProjectManagement/database/migrations/.gitkeep create mode 100644 Modules/ProjectManagement/database/migrations/2026_03_24_200001_create_projects_table.php create mode 100644 Modules/ProjectManagement/database/migrations/2026_03_24_200002_create_tasks_table.php create mode 100644 Modules/ProjectManagement/database/migrations/2026_03_26_160000_create_weekly_status_reports_table.php create mode 100644 Modules/ProjectManagement/database/migrations/2026_03_26_160001_create_workforce_metrics_table.php create mode 100644 Modules/ProjectManagement/database/migrations/2026_03_26_160002_create_hse_records_table.php create mode 100644 Modules/ProjectManagement/database/migrations/2026_03_26_160003_add_contractor_id_to_projects_table.php create mode 100644 Modules/ProjectManagement/database/migrations/2026_03_26_200001_create_task_materials_table.php create mode 100644 Modules/ProjectManagement/database/migrations/2026_03_28_000002_add_po_to_task_materials.php create mode 100644 Modules/ProjectManagement/database/migrations/2026_03_31_000001_add_client_name_and_contract_duration_to_projects.php create mode 100644 Modules/ProjectManagement/database/migrations/2026_03_31_000001_create_project_milestones_table.php create mode 100644 Modules/ProjectManagement/database/migrations/2026_03_31_000002_create_task_delays_table.php create mode 100644 Modules/ProjectManagement/database/migrations/2026_03_31_000003_add_weather_fields_to_weekly_status_reports.php create mode 100644 Modules/ProjectManagement/database/migrations/2026_04_14_000004_create_task_user_table.php create mode 100644 Modules/ProjectManagement/database/migrations/2026_05_24_000001_create_task_activities_table.php create mode 100644 Modules/ProjectManagement/database/seeders/.gitkeep create mode 100644 Modules/ProjectManagement/database/seeders/ProjectManagementDatabaseSeeder.php create mode 100644 Modules/ProjectManagement/module.json create mode 100644 Modules/ProjectManagement/package.json create mode 100644 Modules/ProjectManagement/resources/assets/.gitkeep create mode 100644 Modules/ProjectManagement/resources/assets/js/app.js create mode 100644 Modules/ProjectManagement/resources/assets/sass/app.scss create mode 100644 Modules/ProjectManagement/resources/js/Components/ProjectForm.tsx create mode 100644 Modules/ProjectManagement/resources/js/Components/PurchaseOrderLookup.tsx create mode 100644 Modules/ProjectManagement/resources/js/Layouts/ProjectLayout.tsx create mode 100644 Modules/ProjectManagement/resources/js/Pages/Projects/Create.tsx create mode 100644 Modules/ProjectManagement/resources/js/Pages/Projects/Edit.tsx create mode 100644 Modules/ProjectManagement/resources/js/Pages/Projects/Index.tsx create mode 100644 Modules/ProjectManagement/resources/js/Pages/Projects/Materials.tsx create mode 100644 Modules/ProjectManagement/resources/js/Pages/Projects/Modules/DailyReports.tsx create mode 100644 Modules/ProjectManagement/resources/js/Pages/Projects/Modules/Documents.tsx create mode 100644 Modules/ProjectManagement/resources/js/Pages/Projects/Modules/Progress.tsx create mode 100644 Modules/ProjectManagement/resources/js/Pages/Projects/Modules/QualityControl.tsx create mode 100644 Modules/ProjectManagement/resources/js/Pages/Projects/Modules/RFIs.tsx create mode 100644 Modules/ProjectManagement/resources/js/Pages/Projects/Modules/Safety.tsx create mode 100644 Modules/ProjectManagement/resources/js/Pages/Projects/Overview.tsx create mode 100644 Modules/ProjectManagement/resources/js/Pages/Projects/Show.tsx create mode 100644 Modules/ProjectManagement/resources/js/Pages/Projects/Team.tsx create mode 100644 Modules/ProjectManagement/resources/js/Pages/Reports/Create.tsx create mode 100644 Modules/ProjectManagement/resources/js/Pages/Reports/Edit.tsx create mode 100644 Modules/ProjectManagement/resources/js/Pages/Reports/Index.tsx create mode 100644 Modules/ProjectManagement/resources/js/Pages/Reports/Show.tsx create mode 100644 Modules/ProjectManagement/resources/views/.gitkeep create mode 100644 Modules/ProjectManagement/resources/views/components/layouts/master.blade.php create mode 100644 Modules/ProjectManagement/resources/views/index.blade.php create mode 100644 Modules/ProjectManagement/routes/.gitkeep create mode 100644 Modules/ProjectManagement/routes/api.php create mode 100644 Modules/ProjectManagement/routes/web.php create mode 100644 Modules/ProjectManagement/tests/Feature/.gitkeep create mode 100644 Modules/ProjectManagement/tests/Unit/.gitkeep create mode 100644 Modules/ProjectManagement/vite.config.js create mode 100644 Modules/ProjectProgress/app/Http/Controllers/.gitkeep create mode 100644 Modules/ProjectProgress/app/Http/Controllers/ProjectProgressController.php create mode 100644 Modules/ProjectProgress/app/Providers/.gitkeep create mode 100644 Modules/ProjectProgress/app/Providers/EventServiceProvider.php create mode 100644 Modules/ProjectProgress/app/Providers/ProjectProgressServiceProvider.php create mode 100644 Modules/ProjectProgress/app/Providers/RouteServiceProvider.php create mode 100644 Modules/ProjectProgress/composer.json create mode 100644 Modules/ProjectProgress/config/.gitkeep create mode 100644 Modules/ProjectProgress/config/config.php create mode 100644 Modules/ProjectProgress/database/factories/.gitkeep create mode 100644 Modules/ProjectProgress/database/migrations/.gitkeep create mode 100644 Modules/ProjectProgress/database/seeders/.gitkeep create mode 100644 Modules/ProjectProgress/database/seeders/ProjectProgressDatabaseSeeder.php create mode 100644 Modules/ProjectProgress/module.json create mode 100644 Modules/ProjectProgress/package.json create mode 100644 Modules/ProjectProgress/resources/assets/.gitkeep create mode 100644 Modules/ProjectProgress/resources/assets/js/app.js create mode 100644 Modules/ProjectProgress/resources/assets/sass/app.scss create mode 100644 Modules/ProjectProgress/resources/views/.gitkeep create mode 100644 Modules/ProjectProgress/resources/views/components/layouts/master.blade.php create mode 100644 Modules/ProjectProgress/resources/views/index.blade.php create mode 100644 Modules/ProjectProgress/routes/.gitkeep create mode 100644 Modules/ProjectProgress/routes/api.php create mode 100644 Modules/ProjectProgress/routes/web.php create mode 100644 Modules/ProjectProgress/tests/Feature/.gitkeep create mode 100644 Modules/ProjectProgress/tests/Unit/.gitkeep create mode 100644 Modules/ProjectProgress/vite.config.js create mode 100644 Modules/ProjectQualityControl/app/Http/Controllers/.gitkeep create mode 100644 Modules/ProjectQualityControl/app/Http/Controllers/ProjectQualityControlController.php create mode 100644 Modules/ProjectQualityControl/app/Providers/.gitkeep create mode 100644 Modules/ProjectQualityControl/app/Providers/EventServiceProvider.php create mode 100644 Modules/ProjectQualityControl/app/Providers/ProjectQualityControlServiceProvider.php create mode 100644 Modules/ProjectQualityControl/app/Providers/RouteServiceProvider.php create mode 100644 Modules/ProjectQualityControl/composer.json create mode 100644 Modules/ProjectQualityControl/config/.gitkeep create mode 100644 Modules/ProjectQualityControl/config/config.php create mode 100644 Modules/ProjectQualityControl/database/factories/.gitkeep create mode 100644 Modules/ProjectQualityControl/database/migrations/.gitkeep create mode 100644 Modules/ProjectQualityControl/database/seeders/.gitkeep create mode 100644 Modules/ProjectQualityControl/database/seeders/ProjectQualityControlDatabaseSeeder.php create mode 100644 Modules/ProjectQualityControl/module.json create mode 100644 Modules/ProjectQualityControl/package.json create mode 100644 Modules/ProjectQualityControl/resources/assets/.gitkeep create mode 100644 Modules/ProjectQualityControl/resources/assets/js/app.js create mode 100644 Modules/ProjectQualityControl/resources/assets/sass/app.scss create mode 100644 Modules/ProjectQualityControl/resources/views/.gitkeep create mode 100644 Modules/ProjectQualityControl/resources/views/components/layouts/master.blade.php create mode 100644 Modules/ProjectQualityControl/resources/views/index.blade.php create mode 100644 Modules/ProjectQualityControl/routes/.gitkeep create mode 100644 Modules/ProjectQualityControl/routes/api.php create mode 100644 Modules/ProjectQualityControl/routes/web.php create mode 100644 Modules/ProjectQualityControl/tests/Feature/.gitkeep create mode 100644 Modules/ProjectQualityControl/tests/Unit/.gitkeep create mode 100644 Modules/ProjectQualityControl/vite.config.js create mode 100644 Modules/ProjectRFIs/app/Http/Controllers/.gitkeep create mode 100644 Modules/ProjectRFIs/app/Http/Controllers/ProjectRFIsController.php create mode 100644 Modules/ProjectRFIs/app/Providers/.gitkeep create mode 100644 Modules/ProjectRFIs/app/Providers/EventServiceProvider.php create mode 100644 Modules/ProjectRFIs/app/Providers/ProjectRFIsServiceProvider.php create mode 100644 Modules/ProjectRFIs/app/Providers/RouteServiceProvider.php create mode 100644 Modules/ProjectRFIs/composer.json create mode 100644 Modules/ProjectRFIs/config/.gitkeep create mode 100644 Modules/ProjectRFIs/config/config.php create mode 100644 Modules/ProjectRFIs/database/factories/.gitkeep create mode 100644 Modules/ProjectRFIs/database/migrations/.gitkeep create mode 100644 Modules/ProjectRFIs/database/seeders/.gitkeep create mode 100644 Modules/ProjectRFIs/database/seeders/ProjectRFIsDatabaseSeeder.php create mode 100644 Modules/ProjectRFIs/module.json create mode 100644 Modules/ProjectRFIs/package.json create mode 100644 Modules/ProjectRFIs/resources/assets/.gitkeep create mode 100644 Modules/ProjectRFIs/resources/assets/js/app.js create mode 100644 Modules/ProjectRFIs/resources/assets/sass/app.scss create mode 100644 Modules/ProjectRFIs/resources/views/.gitkeep create mode 100644 Modules/ProjectRFIs/resources/views/components/layouts/master.blade.php create mode 100644 Modules/ProjectRFIs/resources/views/index.blade.php create mode 100644 Modules/ProjectRFIs/routes/.gitkeep create mode 100644 Modules/ProjectRFIs/routes/api.php create mode 100644 Modules/ProjectRFIs/routes/web.php create mode 100644 Modules/ProjectRFIs/tests/Feature/.gitkeep create mode 100644 Modules/ProjectRFIs/tests/Unit/.gitkeep create mode 100644 Modules/ProjectRFIs/vite.config.js create mode 100644 Modules/ProjectReports/app/Http/Controllers/.gitkeep create mode 100644 Modules/ProjectReports/app/Http/Controllers/ProjectReportsController.php create mode 100644 Modules/ProjectReports/app/Http/Controllers/StatusReportController.php create mode 100644 Modules/ProjectReports/app/Providers/.gitkeep create mode 100644 Modules/ProjectReports/app/Providers/EventServiceProvider.php create mode 100644 Modules/ProjectReports/app/Providers/ProjectReportsServiceProvider.php create mode 100644 Modules/ProjectReports/app/Providers/RouteServiceProvider.php create mode 100644 Modules/ProjectReports/composer.json create mode 100644 Modules/ProjectReports/config/.gitkeep create mode 100644 Modules/ProjectReports/config/config.php create mode 100644 Modules/ProjectReports/database/factories/.gitkeep create mode 100644 Modules/ProjectReports/database/migrations/.gitkeep create mode 100644 Modules/ProjectReports/database/seeders/.gitkeep create mode 100644 Modules/ProjectReports/database/seeders/ProjectReportsDatabaseSeeder.php create mode 100644 Modules/ProjectReports/module.json create mode 100644 Modules/ProjectReports/package.json create mode 100644 Modules/ProjectReports/resources/assets/.gitkeep create mode 100644 Modules/ProjectReports/resources/assets/js/app.js create mode 100644 Modules/ProjectReports/resources/assets/sass/app.scss create mode 100644 Modules/ProjectReports/resources/js/Pages/Reports/Index.tsx create mode 100644 Modules/ProjectReports/resources/views/.gitkeep create mode 100644 Modules/ProjectReports/resources/views/components/layouts/master.blade.php create mode 100644 Modules/ProjectReports/resources/views/index.blade.php create mode 100644 Modules/ProjectReports/routes/.gitkeep create mode 100644 Modules/ProjectReports/routes/api.php create mode 100644 Modules/ProjectReports/routes/web.php create mode 100644 Modules/ProjectReports/tests/Feature/.gitkeep create mode 100644 Modules/ProjectReports/tests/Unit/.gitkeep create mode 100644 Modules/ProjectReports/vite.config.js create mode 100644 Modules/ProjectSafety/app/Http/Controllers/.gitkeep create mode 100644 Modules/ProjectSafety/app/Http/Controllers/ProjectSafetyController.php create mode 100644 Modules/ProjectSafety/app/Providers/.gitkeep create mode 100644 Modules/ProjectSafety/app/Providers/EventServiceProvider.php create mode 100644 Modules/ProjectSafety/app/Providers/ProjectSafetyServiceProvider.php create mode 100644 Modules/ProjectSafety/app/Providers/RouteServiceProvider.php create mode 100644 Modules/ProjectSafety/composer.json create mode 100644 Modules/ProjectSafety/config/.gitkeep create mode 100644 Modules/ProjectSafety/config/config.php create mode 100644 Modules/ProjectSafety/database/factories/.gitkeep create mode 100644 Modules/ProjectSafety/database/migrations/.gitkeep create mode 100644 Modules/ProjectSafety/database/seeders/.gitkeep create mode 100644 Modules/ProjectSafety/database/seeders/ProjectSafetyDatabaseSeeder.php create mode 100644 Modules/ProjectSafety/module.json create mode 100644 Modules/ProjectSafety/package.json create mode 100644 Modules/ProjectSafety/resources/assets/.gitkeep create mode 100644 Modules/ProjectSafety/resources/assets/js/app.js create mode 100644 Modules/ProjectSafety/resources/assets/sass/app.scss create mode 100644 Modules/ProjectSafety/resources/views/.gitkeep create mode 100644 Modules/ProjectSafety/resources/views/components/layouts/master.blade.php create mode 100644 Modules/ProjectSafety/resources/views/index.blade.php create mode 100644 Modules/ProjectSafety/routes/.gitkeep create mode 100644 Modules/ProjectSafety/routes/api.php create mode 100644 Modules/ProjectSafety/routes/web.php create mode 100644 Modules/ProjectSafety/tests/Feature/.gitkeep create mode 100644 Modules/ProjectSafety/tests/Unit/.gitkeep create mode 100644 Modules/ProjectSafety/vite.config.js create mode 100644 Modules/RolesPermissions/app/Http/Controllers/.gitkeep create mode 100644 Modules/RolesPermissions/app/Http/Controllers/RolesPermissionsController.php create mode 100644 Modules/RolesPermissions/app/Providers/.gitkeep create mode 100644 Modules/RolesPermissions/app/Providers/EventServiceProvider.php create mode 100644 Modules/RolesPermissions/app/Providers/RolesPermissionsServiceProvider.php create mode 100644 Modules/RolesPermissions/app/Providers/RouteServiceProvider.php create mode 100644 Modules/RolesPermissions/composer.json create mode 100644 Modules/RolesPermissions/config/.gitkeep create mode 100644 Modules/RolesPermissions/config/config.php create mode 100644 Modules/RolesPermissions/database/factories/.gitkeep create mode 100644 Modules/RolesPermissions/database/migrations/.gitkeep create mode 100644 Modules/RolesPermissions/database/seeders/.gitkeep create mode 100644 Modules/RolesPermissions/database/seeders/RolesPermissionsDatabaseSeeder.php create mode 100644 Modules/RolesPermissions/module.json create mode 100644 Modules/RolesPermissions/package.json create mode 100644 Modules/RolesPermissions/resources/assets/.gitkeep create mode 100644 Modules/RolesPermissions/resources/assets/js/app.js create mode 100644 Modules/RolesPermissions/resources/assets/sass/app.scss create mode 100644 Modules/RolesPermissions/resources/js/Pages/Roles/Index.tsx create mode 100644 Modules/RolesPermissions/resources/views/.gitkeep create mode 100644 Modules/RolesPermissions/resources/views/components/layouts/master.blade.php create mode 100644 Modules/RolesPermissions/resources/views/index.blade.php create mode 100644 Modules/RolesPermissions/routes/.gitkeep create mode 100644 Modules/RolesPermissions/routes/api.php create mode 100644 Modules/RolesPermissions/routes/web.php create mode 100644 Modules/RolesPermissions/tests/Feature/.gitkeep create mode 100644 Modules/RolesPermissions/tests/Unit/.gitkeep create mode 100644 Modules/RolesPermissions/vite.config.js create mode 100644 Modules/TaskManagement/app/Http/Controllers/.gitkeep create mode 100644 Modules/TaskManagement/app/Http/Controllers/TaskController.php create mode 100644 Modules/TaskManagement/app/Http/Controllers/TaskDelayController.php create mode 100644 Modules/TaskManagement/app/Http/Controllers/TaskImportController.php create mode 100644 Modules/TaskManagement/app/Http/Controllers/TaskManagementController.php create mode 100644 Modules/TaskManagement/app/Http/Controllers/TaskMaterialController.php create mode 100644 Modules/TaskManagement/app/Providers/.gitkeep create mode 100644 Modules/TaskManagement/app/Providers/EventServiceProvider.php create mode 100644 Modules/TaskManagement/app/Providers/RouteServiceProvider.php create mode 100644 Modules/TaskManagement/app/Providers/TaskManagementServiceProvider.php create mode 100644 Modules/TaskManagement/composer.json create mode 100644 Modules/TaskManagement/config/.gitkeep create mode 100644 Modules/TaskManagement/config/config.php create mode 100644 Modules/TaskManagement/database/factories/.gitkeep create mode 100644 Modules/TaskManagement/database/migrations/.gitkeep create mode 100644 Modules/TaskManagement/database/seeders/.gitkeep create mode 100644 Modules/TaskManagement/database/seeders/TaskManagementDatabaseSeeder.php create mode 100644 Modules/TaskManagement/module.json create mode 100644 Modules/TaskManagement/package.json create mode 100644 Modules/TaskManagement/resources/assets/.gitkeep create mode 100644 Modules/TaskManagement/resources/assets/js/app.js create mode 100644 Modules/TaskManagement/resources/assets/sass/app.scss create mode 100644 Modules/TaskManagement/resources/js/Components/KanbanBoard.tsx create mode 100644 Modules/TaskManagement/resources/js/Pages/Tasks/Index.tsx create mode 100644 Modules/TaskManagement/resources/views/.gitkeep create mode 100644 Modules/TaskManagement/resources/views/components/layouts/master.blade.php create mode 100644 Modules/TaskManagement/resources/views/index.blade.php create mode 100644 Modules/TaskManagement/routes/.gitkeep create mode 100644 Modules/TaskManagement/routes/api.php create mode 100644 Modules/TaskManagement/routes/web.php create mode 100644 Modules/TaskManagement/tests/Feature/.gitkeep create mode 100644 Modules/TaskManagement/tests/Unit/.gitkeep create mode 100644 Modules/TaskManagement/vite.config.js create mode 100644 Modules/TimelineScheduling/app/Enums/DependencyType.php create mode 100644 Modules/TimelineScheduling/app/Http/Controllers/.gitkeep create mode 100644 Modules/TimelineScheduling/app/Http/Controllers/MilestoneController.php create mode 100644 Modules/TimelineScheduling/app/Http/Controllers/ScheduleController.php create mode 100644 Modules/TimelineScheduling/app/Http/Controllers/TimelineSchedulingController.php create mode 100644 Modules/TimelineScheduling/app/Models/Milestone.php create mode 100644 Modules/TimelineScheduling/app/Models/TaskDependency.php create mode 100644 Modules/TimelineScheduling/app/Providers/.gitkeep create mode 100644 Modules/TimelineScheduling/app/Providers/EventServiceProvider.php create mode 100644 Modules/TimelineScheduling/app/Providers/RouteServiceProvider.php create mode 100644 Modules/TimelineScheduling/app/Providers/TimelineSchedulingServiceProvider.php create mode 100644 Modules/TimelineScheduling/app/Services/GanttDataTransformer.php create mode 100644 Modules/TimelineScheduling/composer.json create mode 100644 Modules/TimelineScheduling/config/.gitkeep create mode 100644 Modules/TimelineScheduling/config/config.php create mode 100644 Modules/TimelineScheduling/database/factories/.gitkeep create mode 100644 Modules/TimelineScheduling/database/migrations/.gitkeep create mode 100644 Modules/TimelineScheduling/database/migrations/2026_03_25_020001_create_scheduling_tables.php create mode 100644 Modules/TimelineScheduling/database/seeders/.gitkeep create mode 100644 Modules/TimelineScheduling/database/seeders/TimelineSchedulingDatabaseSeeder.php create mode 100644 Modules/TimelineScheduling/module.json create mode 100644 Modules/TimelineScheduling/package.json create mode 100644 Modules/TimelineScheduling/resources/assets/.gitkeep create mode 100644 Modules/TimelineScheduling/resources/assets/js/app.js create mode 100644 Modules/TimelineScheduling/resources/assets/sass/app.scss create mode 100644 Modules/TimelineScheduling/resources/js/Pages/Schedule/Gantt.tsx create mode 100644 Modules/TimelineScheduling/resources/js/Pages/Timeline/Index.tsx create mode 100644 Modules/TimelineScheduling/resources/views/.gitkeep create mode 100644 Modules/TimelineScheduling/resources/views/components/layouts/master.blade.php create mode 100644 Modules/TimelineScheduling/resources/views/index.blade.php create mode 100644 Modules/TimelineScheduling/routes/.gitkeep create mode 100644 Modules/TimelineScheduling/routes/api.php create mode 100644 Modules/TimelineScheduling/routes/web.php create mode 100644 Modules/TimelineScheduling/tests/Feature/.gitkeep create mode 100644 Modules/TimelineScheduling/tests/Unit/.gitkeep create mode 100644 Modules/TimelineScheduling/vite.config.js create mode 100644 Modules/UserManagement/app/Http/Controllers/.gitkeep create mode 100644 Modules/UserManagement/app/Http/Controllers/Controller.php create mode 100644 Modules/UserManagement/app/Http/Controllers/UserController.php create mode 100644 Modules/UserManagement/app/Http/Controllers/UserManagementController.php create mode 100644 Modules/UserManagement/app/Http/Middleware/EnsureUserIsActive.php create mode 100644 Modules/UserManagement/app/Livewire/UserManager.php create mode 100644 Modules/UserManagement/app/Models/CustomerProfile.php create mode 100644 Modules/UserManagement/app/Models/EmployeeProfile.php create mode 100644 Modules/UserManagement/app/Providers/.gitkeep create mode 100644 Modules/UserManagement/app/Providers/EventServiceProvider.php create mode 100644 Modules/UserManagement/app/Providers/RouteServiceProvider.php create mode 100644 Modules/UserManagement/app/Providers/UserManagementServiceProvider.php create mode 100644 Modules/UserManagement/composer.json create mode 100644 Modules/UserManagement/config/.gitkeep create mode 100644 Modules/UserManagement/config/config.php create mode 100644 Modules/UserManagement/database/factories/.gitkeep create mode 100644 Modules/UserManagement/database/migrations/.gitkeep create mode 100644 Modules/UserManagement/database/migrations/2026_03_24_100001_add_user_management_fields_to_users_table.php create mode 100644 Modules/UserManagement/database/migrations/2026_03_24_100002_create_employee_profiles_table.php create mode 100644 Modules/UserManagement/database/migrations/2026_03_24_100003_create_customer_profiles_table.php create mode 100644 Modules/UserManagement/database/migrations/2026_05_23_102200_add_contractor_to_user_type_enum_in_users_table.php create mode 100644 Modules/UserManagement/database/seeders/.gitkeep create mode 100644 Modules/UserManagement/database/seeders/UserManagementDatabaseSeeder.php create mode 100644 Modules/UserManagement/module.json create mode 100644 Modules/UserManagement/package.json create mode 100644 Modules/UserManagement/resources/assets/.gitkeep create mode 100644 Modules/UserManagement/resources/assets/js/app.js create mode 100644 Modules/UserManagement/resources/assets/sass/app.scss create mode 100644 Modules/UserManagement/resources/js/Pages/Users/BulkImport.tsx create mode 100644 Modules/UserManagement/resources/js/Pages/Users/ChangePassword.tsx create mode 100644 Modules/UserManagement/resources/js/Pages/Users/Create.tsx create mode 100644 Modules/UserManagement/resources/js/Pages/Users/Edit.tsx create mode 100644 Modules/UserManagement/resources/js/Pages/Users/Index.tsx create mode 100644 Modules/UserManagement/resources/js/Pages/Users/Show.tsx create mode 100644 Modules/UserManagement/resources/views/.gitkeep create mode 100644 Modules/UserManagement/resources/views/components/layouts/master.blade.php create mode 100644 Modules/UserManagement/resources/views/index.blade.php create mode 100644 Modules/UserManagement/resources/views/livewire/user-manager.blade.php create mode 100644 Modules/UserManagement/routes/.gitkeep create mode 100644 Modules/UserManagement/routes/api.php create mode 100644 Modules/UserManagement/routes/web.php create mode 100644 Modules/UserManagement/tests/Feature/.gitkeep create mode 100644 Modules/UserManagement/tests/Unit/.gitkeep create mode 100644 Modules/UserManagement/vite.config.js create mode 100644 PLAN-contractor-admin.md create mode 100644 app/Http/Controllers/DashboardController.php create mode 100644 app/Http/Middleware/CheckContractorHierarchy.php create mode 100644 app/Http/Middleware/EnforcePasswordChange.php create mode 100644 app/Observers/UserObserver.php create mode 100644 app/Overrides/Nwidart/Modules/Support/ModuleServiceProvider.php create mode 100644 app/Scopes/TenantScope.php create mode 100644 app/Traits/BelongsToTenant.php create mode 100644 app/Traits/HasPublicIdentifier.php create mode 100644 app/Traits/HasStateMachine.php create mode 100644 check.php create mode 100644 database/migrations/2026_03_26_180000_add_ulid_columns.php create mode 100644 database/migrations/2026_03_30_173842_add_low_stock_threshold_to_warehouse_stock_table.php create mode 100644 database/migrations/2026_04_08_151238_add_target_warehouse_id_to_purchase_orders.php create mode 100644 database/migrations/2026_05_19_000000_create_contractors_table.php create mode 100644 database/migrations/2026_05_19_000001_add_contractor_fields_to_users_table.php create mode 100644 database/migrations/2026_05_23_000000_add_scoping_and_catalog_sharing_columns.php create mode 100644 database/migrations/2026_05_23_010000_add_user_provisioning_columns.php create mode 100644 database/seeders/ConstructionRolesAndPermissionsSeeder.php create mode 100644 database/seeders/MainContractorSeeder.php create mode 100644 database/seeders/RolePermissionSeeder.php create mode 100644 database/seeders/RolesAndPermissionsSeeder.php create mode 100644 database/seeders/SuperAdminPermissionSeeder.php create mode 100644 database/seeders/SuperAdminSeeder.php create mode 100644 docs/PLAN-contractor-onboarding.md create mode 100644 docs/PLAN-direct-permission-assignment.md create mode 100644 docs/PLAN-gantt-capitalization.md create mode 100644 docs/PLAN-inventory-operations.md create mode 100644 docs/PLAN-limit-roles.md create mode 100644 docs/PLAN-material-crud-views.md create mode 100644 docs/PLAN-material-select-tabs.md create mode 100644 docs/PLAN-material-validation-flow.md create mode 100644 docs/PLAN-po-transit-pipeline.md create mode 100644 docs/PLAN-pos-operations-ui.md create mode 100644 docs/PLAN-role-permission-fix.md create mode 100644 docs/PLAN-site-execution-dash.md create mode 100644 docs/PLAN-task-progress-bars.md create mode 100644 docs/PLAN.md create mode 100644 module_info.txt create mode 100644 module_info_v12.txt create mode 100644 modules_statuses.json create mode 100644 project-warehouse-transition.md create mode 100644 resources/js/Components/AppSidebar.tsx create mode 100644 resources/js/Components/Dashboard/ActivityFeed.tsx create mode 100644 resources/js/Components/Dashboard/BlockerList.tsx create mode 100644 resources/js/Components/Dashboard/ResourceSummary.tsx create mode 100644 resources/js/Components/Dashboard/WeatherWidget.tsx create mode 100644 resources/js/Components/DataTableToolbar.tsx create mode 100644 resources/js/Components/MaterialBrowserModal.tsx create mode 100644 resources/js/Components/MaterialPickerModal.tsx create mode 100644 resources/js/Components/ui/avatar.tsx create mode 100644 resources/js/Components/ui/badge.tsx create mode 100644 resources/js/Components/ui/card.tsx create mode 100644 resources/js/Components/ui/checkbox.tsx create mode 100644 resources/js/Components/ui/dialog.tsx create mode 100644 resources/js/Components/ui/dropdown-menu.tsx create mode 100644 resources/js/Components/ui/form.tsx create mode 100644 resources/js/Components/ui/input.tsx create mode 100644 resources/js/Components/ui/label.tsx create mode 100644 resources/js/Components/ui/select.tsx create mode 100644 resources/js/Components/ui/separator.tsx create mode 100644 resources/js/Components/ui/sheet.tsx create mode 100644 resources/js/Components/ui/sidebar.tsx create mode 100644 resources/js/Components/ui/skeleton.tsx create mode 100644 resources/js/Components/ui/sonner.tsx create mode 100644 resources/js/Components/ui/table.tsx create mode 100644 resources/js/Components/ui/tabs.tsx create mode 100644 resources/js/Components/ui/textarea.tsx create mode 100644 resources/js/Components/ui/tooltip.tsx create mode 100644 resources/js/hooks/use-mobile.ts create mode 100644 resources/js/lib/nav-config.ts create mode 100644 storage/clear_data.php create mode 100644 storage/test_po.php create mode 100644 test_po.php create mode 100644 test_po2.php create mode 100644 test_req.php create mode 100644 test_script.php create mode 100644 tests/Feature/ContractorOnboardingTest.php create mode 100644 tests/Feature/TenantScopeTest.php create mode 100644 warehouse-drawer-lookup.md diff --git a/Modules/ApprovalWorkflow/app/Enums/ApprovalChainStatus.php b/Modules/ApprovalWorkflow/app/Enums/ApprovalChainStatus.php new file mode 100644 index 0000000..2150c3f --- /dev/null +++ b/Modules/ApprovalWorkflow/app/Enums/ApprovalChainStatus.php @@ -0,0 +1,31 @@ + 'Pending', + self::InReview => 'In Review', + self::Approved => 'Approved', + self::Rejected => 'Rejected', + }; + } + + public function allowedTransitions(): array + { + return match ($this) { + self::Pending => [self::InReview, self::Rejected], + self::InReview => [self::Approved, self::Rejected], + self::Approved => [], + self::Rejected => [self::Pending], + }; + } +} diff --git a/Modules/ApprovalWorkflow/app/Enums/ApprovalStepStatus.php b/Modules/ApprovalWorkflow/app/Enums/ApprovalStepStatus.php new file mode 100644 index 0000000..6aec377 --- /dev/null +++ b/Modules/ApprovalWorkflow/app/Enums/ApprovalStepStatus.php @@ -0,0 +1,21 @@ + 'Pending', + self::Approved => 'Approved', + self::Rejected => 'Rejected', + self::Skipped => 'Skipped', + }; + } +} diff --git a/Modules/ApprovalWorkflow/app/Events/ApprovalCompleted.php b/Modules/ApprovalWorkflow/app/Events/ApprovalCompleted.php new file mode 100644 index 0000000..9c63682 --- /dev/null +++ b/Modules/ApprovalWorkflow/app/Events/ApprovalCompleted.php @@ -0,0 +1,16 @@ +user(); + $tab = $request->get('tab', 'pending'); + + $query = ApprovalChain::query(); + + if ($tab === 'history') { + $query->whereHas('steps', function ($q) use ($user) { + $q->where('approver_id', $user->id)->where('status', '!=', 'pending'); + }); + } else { + $query->whereHas('steps', function ($q) use ($user) { + $q->where('approver_id', $user->id)->where('status', 'pending'); + })->whereIn('status', ['pending', 'in_review']); + } + + $chains = $query->with(['steps.approver:id,name', 'initiator:id,name']) + ->latest() + ->paginate(15) + ->withQueryString(); + + return Inertia::render('ApprovalWorkflow::Approvals/Index', [ + 'approvals' => $chains, + 'tab' => $tab, + ]); + } + + /** + * Show a specific approval chain. + */ + public function show(ApprovalChain $approvalChain) + { + $approvalChain->load(['steps.approver:id,name,email', 'initiator:id,name,email', 'approvable']); + + $breakdownData = null; + + if ($approvalChain->approvable) { + if (method_exists($approvalChain->approvable, 'items')) { + $approvalChain->approvable->load('items'); + } + + $breakdownData = [ + 'document_number' => $approvalChain->approvable->document_number ?? $approvalChain->approvable->po_number ?? null, + 'total_cost' => $approvalChain->approvable->total_cost ?? 0, + 'notes' => $approvalChain->approvable->notes ?? null, + ]; + } + + return Inertia::render('ApprovalWorkflow::Approvals/Show', [ + 'chain' => $approvalChain, + 'breakdownData' => $breakdownData, + ]); + } + + /** + * Approve the current step. + */ + public function approve(Request $request, ApprovalChain $approvalChain) + { + $request->validate(['notes' => 'nullable|string|max:1000']); + + try { + $this->approvalService->approve($approvalChain, $request->user(), $request->notes); + } catch (\InvalidArgumentException $e) { + return back()->with('error', $e->getMessage()); + } + + return back()->with('success', 'Step approved successfully.'); + } + + /** + * Reject the current step (rejects entire chain). + */ + public function reject(Request $request, ApprovalChain $approvalChain) + { + $request->validate(['notes' => 'required|string|max:1000']); + + try { + $this->approvalService->reject($approvalChain, $request->user(), $request->notes); + } catch (\InvalidArgumentException $e) { + return back()->with('error', $e->getMessage()); + } + + return back()->with('success', 'Approval rejected.'); + } +} diff --git a/Modules/ApprovalWorkflow/app/Http/Controllers/ApprovalWorkflowController.php b/Modules/ApprovalWorkflow/app/Http/Controllers/ApprovalWorkflowController.php new file mode 100644 index 0000000..faeadc1 --- /dev/null +++ b/Modules/ApprovalWorkflow/app/Http/Controllers/ApprovalWorkflowController.php @@ -0,0 +1,56 @@ +chain; + $approvable = $chain->approvable; + + if (!$approvable) { + return; + } + + // If the model defines a custom hook, use it + if (method_exists($approvable, 'onApprovalCompleted')) { + $approvable->onApprovalCompleted($chain); + return; + } + + // Otherwise, attempt a generic status sync + $fillable = $approvable->getFillable(); + $updates = []; + + if (in_array('status', $fillable)) { + $updates['status'] = $chain->status->value; + } + + if ($chain->status->value === 'approved') { + if (in_array('approved_by', $fillable)) { + $lastStep = $chain->steps()->where('status', 'approved')->orderByDesc('acted_at')->first(); + if ($lastStep) { + $updates['approved_by'] = $lastStep->approver_id; + } + } + if (in_array('approved_at', $fillable)) { + $lastStep = $chain->steps()->where('status', 'approved')->orderByDesc('acted_at')->first(); + if ($lastStep) { + $updates['approved_at'] = $lastStep->acted_at; + } else { + $updates['approved_at'] = now(); + } + } + } + + if (!empty($updates)) { + $approvable->update($updates); + } + } +} diff --git a/Modules/ApprovalWorkflow/app/Models/ApprovalChain.php b/Modules/ApprovalWorkflow/app/Models/ApprovalChain.php new file mode 100644 index 0000000..e1427ba --- /dev/null +++ b/Modules/ApprovalWorkflow/app/Models/ApprovalChain.php @@ -0,0 +1,76 @@ + ApprovalChainStatus::class, + 'completed_at' => 'datetime', + ]; + } + + public function approvable(): MorphTo + { + return $this->morphTo(); + } + + public function initiator(): BelongsTo + { + return $this->belongsTo(User::class, 'initiated_by'); + } + + public function steps(): HasMany + { + return $this->hasMany(ApprovalStep::class)->orderBy('order'); + } + + public function currentStep(): ?ApprovalStep + { + return $this->steps()->where('status', 'pending')->first(); + } + + public function isFullyApproved(): bool + { + return $this->steps()->where('status', '!=', 'approved')->doesntExist(); + } + + public function transitionTo(ApprovalChainStatus $newStatus): void + { + $allowed = $this->status->allowedTransitions(); + if (!in_array($newStatus, $allowed)) { + throw new \InvalidArgumentException( + "Cannot transition chain from {$this->status->label()} to {$newStatus->label()}" + ); + } + + $updates = ['status' => $newStatus]; + if (in_array($newStatus, [ApprovalChainStatus::Approved, ApprovalChainStatus::Rejected])) { + $updates['completed_at'] = now(); + } + + $this->update($updates); + } +} diff --git a/Modules/ApprovalWorkflow/app/Models/ApprovalStep.php b/Modules/ApprovalWorkflow/app/Models/ApprovalStep.php new file mode 100644 index 0000000..2370710 --- /dev/null +++ b/Modules/ApprovalWorkflow/app/Models/ApprovalStep.php @@ -0,0 +1,46 @@ + ApprovalStepStatus::class, + 'acted_at' => 'datetime', + ]; + } + + public function chain(): BelongsTo + { + return $this->belongsTo(ApprovalChain::class, 'approval_chain_id'); + } + + public function approver(): BelongsTo + { + return $this->belongsTo(User::class, 'approver_id'); + } + + public function isPending(): bool + { + return $this->status === ApprovalStepStatus::Pending; + } +} diff --git a/Modules/ApprovalWorkflow/app/Providers/.gitkeep b/Modules/ApprovalWorkflow/app/Providers/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/Modules/ApprovalWorkflow/app/Providers/ApprovalWorkflowServiceProvider.php b/Modules/ApprovalWorkflow/app/Providers/ApprovalWorkflowServiceProvider.php new file mode 100644 index 0000000..a772690 --- /dev/null +++ b/Modules/ApprovalWorkflow/app/Providers/ApprovalWorkflowServiceProvider.php @@ -0,0 +1,46 @@ +command('inspire')->hourly(); + // } +} diff --git a/Modules/ApprovalWorkflow/app/Providers/EventServiceProvider.php b/Modules/ApprovalWorkflow/app/Providers/EventServiceProvider.php new file mode 100644 index 0000000..d57f8d7 --- /dev/null +++ b/Modules/ApprovalWorkflow/app/Providers/EventServiceProvider.php @@ -0,0 +1,31 @@ +> + */ + protected $listen = [ + \Modules\ApprovalWorkflow\Events\ApprovalCompleted::class => [ + \Modules\ApprovalWorkflow\Listeners\SyncApprovableStatus::class, + ], + ]; + + /** + * Indicates if events should be discovered. + * + * @var bool + */ + protected static $shouldDiscoverEvents = true; + + /** + * Configure the proper event listeners for email verification. + */ + protected function configureEmailVerification(): void {} +} diff --git a/Modules/ApprovalWorkflow/app/Providers/RouteServiceProvider.php b/Modules/ApprovalWorkflow/app/Providers/RouteServiceProvider.php new file mode 100644 index 0000000..2b5161a --- /dev/null +++ b/Modules/ApprovalWorkflow/app/Providers/RouteServiceProvider.php @@ -0,0 +1,50 @@ +mapApiRoutes(); + $this->mapWebRoutes(); + } + + /** + * Define the "web" routes for the application. + * + * These routes all receive session state, CSRF protection, etc. + */ + protected function mapWebRoutes(): void + { + Route::middleware('web')->group(module_path($this->name, '/routes/web.php')); + } + + /** + * Define the "api" routes for the application. + * + * These routes are typically stateless. + */ + protected function mapApiRoutes(): void + { + Route::middleware('api')->prefix('api')->name('api.')->group(module_path($this->name, '/routes/api.php')); + } +} diff --git a/Modules/ApprovalWorkflow/app/Services/ApprovalService.php b/Modules/ApprovalWorkflow/app/Services/ApprovalService.php new file mode 100644 index 0000000..d3e81a0 --- /dev/null +++ b/Modules/ApprovalWorkflow/app/Services/ApprovalService.php @@ -0,0 +1,135 @@ + $approverIds — ordered list of user IDs + */ + public function createChain( + Model $approvable, + array $approverIds, + string $type = 'general', + ?int $initiatedBy = null, + ?string $notes = null, + ): ApprovalChain { + $chain = ApprovalChain::create([ + 'approvable_type' => $approvable->getMorphClass(), + 'approvable_id' => $approvable->getKey(), + 'type' => $type, + 'status' => ApprovalChainStatus::Pending, + 'initiated_by' => $initiatedBy, + 'notes' => $notes, + ]); + + foreach ($approverIds as $order => $userId) { + ApprovalStep::create([ + 'approval_chain_id' => $chain->id, + 'approver_id' => $userId, + 'order' => $order, + 'status' => ApprovalStepStatus::Pending, + ]); + } + + // Auto-transition to InReview and notify first approver + $chain->transitionTo(ApprovalChainStatus::InReview); + $firstStep = $chain->currentStep(); + if ($firstStep) { + ApprovalRequired::dispatch($chain, $firstStep); + } + + return $chain->load('steps.approver'); + } + + /** + * Approve the current pending step. + */ + public function approve(ApprovalChain $chain, User $approver, ?string $notes = null): ApprovalChain + { + $step = $this->getCurrentStepForApprover($chain, $approver); + + $step->update([ + 'status' => ApprovalStepStatus::Approved, + 'notes' => $notes, + 'acted_at' => now(), + ]); + + StepApproved::dispatch($chain, $step); + + // Check if all steps are approved + if ($chain->isFullyApproved()) { + $chain->transitionTo(ApprovalChainStatus::Approved); + ApprovalCompleted::dispatch($chain); + } else { + // Notify next approver + $nextStep = $chain->currentStep(); + if ($nextStep) { + ApprovalRequired::dispatch($chain, $nextStep); + } + } + + return $chain->fresh('steps.approver'); + } + + /** + * Reject the current pending step (rejects the entire chain). + */ + public function reject(ApprovalChain $chain, User $approver, ?string $notes = null): ApprovalChain + { + $step = $this->getCurrentStepForApprover($chain, $approver); + + $step->update([ + 'status' => ApprovalStepStatus::Rejected, + 'notes' => $notes, + 'acted_at' => now(), + ]); + + // Skip remaining steps + $chain->steps() + ->where('order', '>', $step->order) + ->where('status', 'pending') + ->update(['status' => ApprovalStepStatus::Skipped->value]); + + $chain->transitionTo(ApprovalChainStatus::Rejected); + + StepRejected::dispatch($chain, $step); + ApprovalCompleted::dispatch($chain); + + return $chain->fresh('steps.approver'); + } + + public function getNextApprover(ApprovalChain $chain): ?User + { + $step = $chain->currentStep(); + return $step?->approver; + } + + private function getCurrentStepForApprover(ApprovalChain $chain, User $approver): ApprovalStep + { + $step = $chain->currentStep(); + + if (!$step) { + throw new \InvalidArgumentException('No pending step found in this approval chain.'); + } + + if ($step->approver_id !== $approver->id) { + throw new \InvalidArgumentException('You are not the current approver for this step.'); + } + + return $step; + } +} diff --git a/Modules/ApprovalWorkflow/app/Traits/HasApprovable.php b/Modules/ApprovalWorkflow/app/Traits/HasApprovable.php new file mode 100644 index 0000000..427ae9e --- /dev/null +++ b/Modules/ApprovalWorkflow/app/Traits/HasApprovable.php @@ -0,0 +1,30 @@ +morphMany(ApprovalChain::class, 'approvable'); + } + + public function latestApprovalChain(): ?ApprovalChain + { + return $this->approvalChains()->latest()->first(); + } + + public function isApproved(): bool + { + $chain = $this->latestApprovalChain(); + return $chain && $chain->status->value === 'approved'; + } + + public function isPendingApproval(): bool + { + $chain = $this->latestApprovalChain(); + return $chain && in_array($chain->status->value, ['pending', 'in_review']); + } +} diff --git a/Modules/ApprovalWorkflow/composer.json b/Modules/ApprovalWorkflow/composer.json new file mode 100644 index 0000000..baa1a3c --- /dev/null +++ b/Modules/ApprovalWorkflow/composer.json @@ -0,0 +1,30 @@ +{ + "name": "nwidart/approvalworkflow", + "description": "", + "authors": [ + { + "name": "Nicolas Widart", + "email": "n.widart@gmail.com" + } + ], + "extra": { + "laravel": { + "providers": [], + "aliases": { + + } + } + }, + "autoload": { + "psr-4": { + "Modules\\ApprovalWorkflow\\": "app/", + "Modules\\ApprovalWorkflow\\Database\\Factories\\": "database/factories/", + "Modules\\ApprovalWorkflow\\Database\\Seeders\\": "database/seeders/" + } + }, + "autoload-dev": { + "psr-4": { + "Modules\\ApprovalWorkflow\\Tests\\": "tests/" + } + } +} diff --git a/Modules/ApprovalWorkflow/config/.gitkeep b/Modules/ApprovalWorkflow/config/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/Modules/ApprovalWorkflow/config/config.php b/Modules/ApprovalWorkflow/config/config.php new file mode 100644 index 0000000..8895c25 --- /dev/null +++ b/Modules/ApprovalWorkflow/config/config.php @@ -0,0 +1,5 @@ + 'ApprovalWorkflow', +]; diff --git a/Modules/ApprovalWorkflow/database/factories/.gitkeep b/Modules/ApprovalWorkflow/database/factories/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/Modules/ApprovalWorkflow/database/migrations/.gitkeep b/Modules/ApprovalWorkflow/database/migrations/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/Modules/ApprovalWorkflow/database/migrations/2026_03_24_210001_create_approval_tables.php b/Modules/ApprovalWorkflow/database/migrations/2026_03_24_210001_create_approval_tables.php new file mode 100644 index 0000000..67e2f1a --- /dev/null +++ b/Modules/ApprovalWorkflow/database/migrations/2026_03_24_210001_create_approval_tables.php @@ -0,0 +1,39 @@ +id(); + $table->morphs('approvable'); // approvable_type + approvable_id + $table->string('type')->default('general'); // e.g., material_request, invoice, purchase_order + $table->string('status')->default('pending'); + $table->text('notes')->nullable(); + $table->foreignId('initiated_by')->nullable()->constrained('users')->nullOnDelete(); + $table->timestamp('completed_at')->nullable(); + $table->timestamps(); + }); + + Schema::create('approval_steps', function (Blueprint $table) { + $table->id(); + $table->foreignId('approval_chain_id')->constrained()->cascadeOnDelete(); + $table->foreignId('approver_id')->constrained('users')->cascadeOnDelete(); + $table->integer('order')->default(0); + $table->string('status')->default('pending'); + $table->text('notes')->nullable(); + $table->timestamp('acted_at')->nullable(); + $table->timestamps(); + }); + } + + public function down(): void + { + Schema::dropIfExists('approval_steps'); + Schema::dropIfExists('approval_chains'); + } +}; diff --git a/Modules/ApprovalWorkflow/database/seeders/.gitkeep b/Modules/ApprovalWorkflow/database/seeders/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/Modules/ApprovalWorkflow/database/seeders/ApprovalWorkflowDatabaseSeeder.php b/Modules/ApprovalWorkflow/database/seeders/ApprovalWorkflowDatabaseSeeder.php new file mode 100644 index 0000000..fea89b0 --- /dev/null +++ b/Modules/ApprovalWorkflow/database/seeders/ApprovalWorkflowDatabaseSeeder.php @@ -0,0 +1,16 @@ +call([]); + } +} diff --git a/Modules/ApprovalWorkflow/module.json b/Modules/ApprovalWorkflow/module.json new file mode 100644 index 0000000..44d5248 --- /dev/null +++ b/Modules/ApprovalWorkflow/module.json @@ -0,0 +1,11 @@ +{ + "name": "ApprovalWorkflow", + "alias": "approvalworkflow", + "description": "", + "keywords": [], + "priority": 0, + "providers": [ + "Modules\\ApprovalWorkflow\\Providers\\ApprovalWorkflowServiceProvider" + ], + "files": [] +} diff --git a/Modules/ApprovalWorkflow/package.json b/Modules/ApprovalWorkflow/package.json new file mode 100644 index 0000000..d6fbfc8 --- /dev/null +++ b/Modules/ApprovalWorkflow/package.json @@ -0,0 +1,15 @@ +{ + "private": true, + "type": "module", + "scripts": { + "dev": "vite", + "build": "vite build" + }, + "devDependencies": { + "axios": "^1.1.2", + "laravel-vite-plugin": "^0.7.5", + "sass": "^1.69.5", + "postcss": "^8.3.7", + "vite": "^4.0.0" + } +} diff --git a/Modules/ApprovalWorkflow/resources/assets/.gitkeep b/Modules/ApprovalWorkflow/resources/assets/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/Modules/ApprovalWorkflow/resources/assets/js/app.js b/Modules/ApprovalWorkflow/resources/assets/js/app.js new file mode 100644 index 0000000..e69de29 diff --git a/Modules/ApprovalWorkflow/resources/assets/sass/app.scss b/Modules/ApprovalWorkflow/resources/assets/sass/app.scss new file mode 100644 index 0000000..e69de29 diff --git a/Modules/ApprovalWorkflow/resources/js/Components/ApprovableBreakdown.tsx b/Modules/ApprovalWorkflow/resources/js/Components/ApprovableBreakdown.tsx new file mode 100644 index 0000000..067b410 --- /dev/null +++ b/Modules/ApprovalWorkflow/resources/js/Components/ApprovableBreakdown.tsx @@ -0,0 +1,83 @@ +import { Card, CardContent, CardHeader, CardTitle } from '@/Components/ui/card'; +import { Button } from '@/Components/ui/button'; +import { ExternalLink, FileText, ShoppingCart } from 'lucide-react'; + +interface Props { + chain: any; + breakdownData?: any; +} + +export default function ApprovableBreakdown({ chain, breakdownData }: Props) { + const approvable = chain.approvable; + if (!approvable || !breakdownData) return null; + + let title = 'Document Breakdown'; + let icon = ; + let details: { label: string; value: React.ReactNode }[] = []; + let linkUrl = '#'; + + switch (chain.approvable_type) { + case 'Modules\\MaterialLogistics\\Models\\MaterialRequisition': + title = 'Material Requisition Details'; + icon = ; + linkUrl = route('requisitions.show', approvable.ulid || approvable.id); + details = [ + { label: 'Document Number', value: breakdownData.document_number || `REQ-${approvable.id}` }, + { label: 'Total Cost', value: breakdownData.total_cost != null ? `₱${parseFloat(breakdownData.total_cost).toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })}` : 'N/A' }, + { label: 'Notes', value: breakdownData.notes || 'None' }, + ]; + break; + case 'Modules\\MaterialLogistics\\Models\\PurchaseOrder': + title = 'Purchase Order Details'; + icon = ; + linkUrl = route('purchase-orders.show', approvable.ulid || approvable.id); + details = [ + { label: 'PO Number', value: breakdownData.document_number || `PO-${approvable.id}` }, + { label: 'Total Amount', value: breakdownData.total_cost != null ? `₱${parseFloat(breakdownData.total_cost).toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })}` : 'N/A' }, + { label: 'Notes', value: breakdownData.notes || 'None' }, + ]; + break; + default: + title = 'Generic Document'; + break; + } + + return ( + + + + {icon} {title} + + + + + + + {details.length > 0 ? ( +
+ {details.map((detail, idx) => ( +
+

{detail.label}

+

{detail.value}

+
+ ))} +
+ ) : ( +

Details not found or unsupported document type.

+ )} + + +
+
+ ); +} diff --git a/Modules/ApprovalWorkflow/resources/js/Components/ApprovalTimeline.tsx b/Modules/ApprovalWorkflow/resources/js/Components/ApprovalTimeline.tsx new file mode 100644 index 0000000..15ef6e7 --- /dev/null +++ b/Modules/ApprovalWorkflow/resources/js/Components/ApprovalTimeline.tsx @@ -0,0 +1,66 @@ +import { Badge } from '@/Components/ui/badge'; +import { CheckCircle2, Circle, XCircle, SkipForward } from 'lucide-react'; + +interface Step { + id: number; ulid: string; + order: number; + status: string; + notes?: string; + acted_at?: string; + approver: { id: number; ulid: string; name: string }; +} + +interface Props { + steps: Step[]; +} + +const statusConfig: Record; color: string; bgColor: string }> = { + pending: { icon: Circle, color: 'text-gray-400', bgColor: 'bg-gray-100' }, + approved: { icon: CheckCircle2, color: 'text-green-600', bgColor: 'bg-green-50' }, + rejected: { icon: XCircle, color: 'text-red-600', bgColor: 'bg-red-50' }, + skipped: { icon: SkipForward, color: 'text-gray-400', bgColor: 'bg-gray-50' }, +}; + +export default function ApprovalTimeline({ steps }: Props) { + return ( +
+ {steps.map((step, idx) => { + const config = statusConfig[step.status] || statusConfig.pending; + const Icon = config.icon; + const isLast = idx === steps.length - 1; + + return ( +
+ {/* Timeline line + icon */} +
+
+ +
+ {!isLast && ( +
+ )} +
+ + {/* Content */} +
+
+ {step.approver.name} + + {step.status.replace(/_/g, ' ').replace(/\b\w/g, c => c.toUpperCase())} + +
+ {step.notes && ( +

"{step.notes}"

+ )} + {step.acted_at && ( +

+ {new Date(step.acted_at).toLocaleString()} +

+ )} +
+
+ ); + })} +
+ ); +} diff --git a/Modules/ApprovalWorkflow/resources/js/Pages/Approvals/Index.tsx b/Modules/ApprovalWorkflow/resources/js/Pages/Approvals/Index.tsx new file mode 100644 index 0000000..1af8ebf --- /dev/null +++ b/Modules/ApprovalWorkflow/resources/js/Pages/Approvals/Index.tsx @@ -0,0 +1,147 @@ +import AuthenticatedLayout from '@/Layouts/AuthenticatedLayout'; +import { Head, Link, usePage } from '@inertiajs/react'; +import { Badge } from '@/Components/ui/badge'; +import { Button } from '@/Components/ui/button'; +import { Card, CardContent, CardHeader, CardTitle } from '@/Components/ui/card'; +import { + Table, TableBody, TableCell, TableHead, TableHeader, TableRow, +} from '@/Components/ui/table'; +import { PaginatedData, PageProps } from '@/types'; +import { ClipboardCheck, Eye } from 'lucide-react'; + +interface ChainItem { + id: number; ulid: string; + approvable_type: string; + type: string; + status: string; + notes?: string; + created_at: string; + initiator?: { id: number; ulid: string; name: string }; + steps: { + id: number; ulid: string; order: number; status: string; + approver: { id: number; ulid: string; name: string }; + }[]; +} + +interface Props extends PageProps { + approvals: PaginatedData; + tab: string; +} + +const typeLabel = (type: string) => type.replace(/_/g, ' ').replace(/\b\w/g, c => c.toUpperCase()); +const statusVariant = (s: string) => { + switch (s) { + case 'approved': return 'default'; + case 'rejected': return 'destructive'; + case 'in_review': return 'secondary'; + default: return 'outline'; + } +}; + +export default function Index({ approvals, tab }: Props) { + const { flash } = usePage().props; + const isHistory = tab === 'history'; + + return ( + + +

+ {isHistory ? 'Approval History' : 'Pending Approvals'} +

+
+ } + > + + +
+
+ {flash?.success &&
{flash.success}
} + {flash?.error &&
{flash.error}
} + +
+ + Pending Approvals + + + Approval History + +
+ + + {isHistory ? 'Your Past Approvals' : 'Items Awaiting Your Approval'} + + + + + Type + Initiated By + Status + Steps + Submitted + Actions + + + + {approvals.data.length === 0 ? ( + + + {isHistory ? 'No past approvals found.' : "No pending approvals. You're all caught up! 🎉"} + + + ) : ( + approvals.data.map((chain) => ( + + {typeLabel(chain.type)} + {chain.initiator?.name || '-'} + + + {typeLabel(chain.status)} + + + + {chain.steps.filter(s => s.status === 'approved').length}/{chain.steps.length} + + + {new Date(chain.created_at).toLocaleDateString()} + + + + + + + + )) + )} + +
+ + {approvals.last_page > 1 && ( +
+

+ Showing {approvals.from} to {approvals.to} of {approvals.total} +

+
+ {approvals.prev_page_url && ( + + + + )} + {approvals.next_page_url && ( + + + + )} +
+
+ )} +
+
+
+
+ + ); +} diff --git a/Modules/ApprovalWorkflow/resources/js/Pages/Approvals/Show.tsx b/Modules/ApprovalWorkflow/resources/js/Pages/Approvals/Show.tsx new file mode 100644 index 0000000..3b1f2c6 --- /dev/null +++ b/Modules/ApprovalWorkflow/resources/js/Pages/Approvals/Show.tsx @@ -0,0 +1,157 @@ +import AuthenticatedLayout from '@/Layouts/AuthenticatedLayout'; +import { Head, Link, router, usePage } from '@inertiajs/react'; +import { Badge } from '@/Components/ui/badge'; +import { Button } from '@/Components/ui/button'; +import { Card, CardContent, CardHeader, CardTitle } from '@/Components/ui/card'; +import { Input } from '@/Components/ui/input'; +import { Label } from '@/Components/ui/label'; +import ApprovalTimeline from '../../Components/ApprovalTimeline'; +import ApprovableBreakdown from '../../Components/ApprovableBreakdown'; +import { ArrowLeft, CheckCircle2, XCircle } from 'lucide-react'; +import { PageProps } from '@/types'; +import { useState } from 'react'; + +interface Step { + id: number; ulid: string; order: number; status: string; notes?: string; + acted_at?: string; approver: { id: number; ulid: string; name: string; email: string }; +} + +interface ChainData { + id: number; ulid: string; approvable_type: string; type: string; status: string; + notes?: string; created_at: string; completed_at?: string; + initiator?: { id: number; ulid: string; name: string; email: string }; + steps: Step[]; + approvable?: any; +} + +interface Props extends PageProps { + chain: ChainData; + breakdownData: any; +} + +const typeLabel = (s: string) => s.replace(/_/g, ' ').replace(/\b\w/g, c => c.toUpperCase()); +const statusVariant = (s: string) => { + switch (s) { case 'approved': return 'default'; case 'rejected': return 'destructive'; case 'in_review': return 'secondary'; default: return 'outline'; } +}; + +export default function Show({ chain, breakdownData }: Props) { + const { flash, auth } = usePage().props; + const [approveNotes, setApproveNotes] = useState(''); + const [rejectNotes, setRejectNotes] = useState(''); + + const currentStep = chain.steps.find(s => s.status === 'pending'); + const isCurrentApprover = currentStep && currentStep.approver.id === auth.user.id; + + const handleApprove = () => { + router.patch(route('approvals.approve', chain.ulid), { notes: approveNotes || undefined }); + }; + + const handleReject = () => { + if (!rejectNotes.trim()) { + alert('Please provide a reason for rejection.'); + return; + } + router.patch(route('approvals.reject', chain.ulid), { notes: rejectNotes }); + }; + + return ( + + + + +
+

+ Approval: {typeLabel(chain.type)} #{chain.id} +

+
+ {typeLabel(chain.status)} + + } + > + + +
+
+ {flash?.success &&
{flash.success}
} + {flash?.error &&
{flash.error}
} + + {/* Chain Info */} + + Details + +
+
+

Type

+

{typeLabel(chain.type)}

+
+
+

Initiated By

+

{chain.initiator?.name || 'System'}

+
+
+

Submitted

+

{new Date(chain.created_at).toLocaleString()}

+
+ {chain.completed_at && ( +
+

Completed

+

{new Date(chain.completed_at).toLocaleString()}

+
+ )} +
+ {chain.notes && ( +
+

Notes

+

{chain.notes}

+
+ )} +
+
+ + {/* Approvable Breakdown */} + + + {/* Timeline */} + + Approval Progress + + + + + + {/* Action Buttons */} + {isCurrentApprover && chain.status === 'in_review' && ( + + Your Action Required + +
+ +