6.9 KiB
6.9 KiB
Plan: Labors Module with Skillset Grouping
This plan implements a standalone Labors module in the GSB Construction ERP application. It replaces/supplements the basic labor_rates lookup catalog with a robust labors table supporting Skilled vs Unskilled categories and many-to-many relationships with a predefined dictionary of skills. These labor records are then integrated into the Project Wizard's Manpower Rate Allocation phase (Step 4).
Success Criteria
- Creation of the
Laborsstandalone module. - Database migrations for
skills,labors, andlabor_skills(grouped skillsets per labor record). - Category attribute on Labor records with values "skilled" and "unskilled".
- Backend Models
LaborandSkillwith correct relations. - Backend CRUD routes & controllers (
LaborController,SkillController) for managing labor profiles and skillsets. - Frontend UI (
Modules/Labors/resources/js/Pages/Labors/Index.tsxandSkills/Index.tsxor similar) to manage Labors (name, category, skills list, hourly rate, status) and Skills list. - Integration into Project Wizard Step 4 (Manpower allocation). Instead of just choosing from general
labor_rates, users select from the newlaborsmodule records, which display the Laborer category (Skilled / Unskilled) and their grouped skillsets as tooltips/badges in the dropdown/table. - Verification Plan with specific tests and manual checks.
Open Questions
- Coexistence of general Trade rates: Do you want to keep
labor_ratesfor generic bidding/budgeting estimates and uselaborsfor specific crew assignments? Or shouldlaborsfully replacelabor_rates? (Our plan assumes fully replacing/extending it by pointingtask_laborstolaborsto ensure consistency). - Predefined Skill Dictionary: Should skills be managed as a master list (e.g. masonry, plumbing) that administrators can edit, or simple free-text tags? (We propose a master
skillstable with a many-to-many relationship).
Proposed Changes
Component 1: Labors Laravel Module Creation & Database Schema
We will create a new Laravel module called Labors using Laravel Modules structure:
c:\laragon\bin\php\php-8.2.30-Win32-vs16-x64\php.exe artisan module:make Labors
[NEW] create_skills_table
Contains the predefined dictionary of skills.
id(BIGINT, PK)ulid(CHAR(26), Unique)name(VARCHAR, Unique) — e.g., "Bricklaying", "Wiring", "Concrete Finishing"description(TEXT, Nullable)timestamps
[NEW] create_labors_table
Contains the Labor Records.
id(BIGINT, PK)ulid(CHAR(26), Unique)name(VARCHAR) — e.g., "Mason - Class A", "General Laborer"category(ENUM:'skilled','unskilled')hourly_rate(DECIMAL(10, 2))status(VARCHAR, Default:'active')timestamps
[NEW] create_labor_skills_table
Junction table grouping skillsets per Labor Record.
labor_id(FK ->labors.idON DELETE CASCADE)skill_id(FK ->skills.idON DELETE CASCADE)- PK is
(labor_id, skill_id)
Component 2: Models and Backend Services
[NEW] Skill.php
- Uses
App\Traits\HasPublicIdentifier. - Relationship:
labors()->belongsToMany(Labor::class)
[NEW] Labor.php
- Uses
App\Traits\HasPublicIdentifier. - Casts
hourly_ratetodecimal:2. - Relationship:
skills()->belongsToMany(Skill::class, 'labor_skills') - Scope:
scopeActive()
[NEW] LaborController.php
- Handles CRUD endpoints for managing labor records.
- Handles syncing many-to-many skills during store and update.
[NEW] SkillController.php
- Handles simple CRUD for the skill dictionary.
Component 3: Navigation and Frontend Views
[NEW] Index.tsx
A premium management page featuring:
- Tabs for "Labor Records" and "Skill Dictionary".
- Forms/modals to create and edit labor records with a skillset selector (multi-select badges).
- Filtering by category (Skilled / Unskilled) or status (Active / Inactive).
[MODIFY] nav-config.ts
- Add a new "Labors" link under the "Management" or "Materials & Logistics" section pointing to the new
labors.indexroute.
Component 4: Project Wizard Step 4 Integration
[MODIFY] 2026_05_28_100004_create_task_resources_tables.php
- Modify
task_laborsto referencelabor_id(FK to newlaborstable) instead oflabor_rate_id. - Note: We will run a clean migrate/reset since this is local dev database, or write a modifying migration.
[MODIFY] ProjectController.php
- In
wizard(): Load$labors = \Modules\Labors\Models\Labor::with('skills')->active()->get()instead oflaborRates. - Update
saveWizardLabor()validation and database transaction to reference the newlabor_id.
[MODIFY] Wizard.tsx
- Update Step 4 table to show Labor Category (Skilled/Unskilled) badge.
- Update dropdown select to list labor profiles with their category and grouped skillsets (e.g., in a tooltip or a badge list).
- Change variable names from
laborRatestolaborsandlabor_rate_ulidtolabor_ulid.
Verification Plan
Automated Tests
- Build verification:
npm run buildto verify TypeScript compile. - Run tests:
c:\laragon\bin\php\php-8.2.30-Win32-vs16-x64\php.exe artisan test Modules/ProjectManagement/tests/Feature/ProjectWizardTest.phpto verify no regressions in the wizard.
Manual Verification
- Access the new "Labors" menu in the sidebar and create multiple skillsets (e.g. Masonry, Plumbing, Carpentry).
- Create labor records matching "Skilled Mason" (category: Skilled) with Masonry skill, and "General Helper" (category: Unskilled) with no skills.
- Access the Project Wizard Step 4 (Manpower allocation). Verify that the new labors are listed in the dropdown with their category badges and their grouped skillsets visible.
- Allocate hours to tasks, save the step, and verify that the database table
task_laborscorrectly associates the values.