Team Roster Feature
Some checks failed
Tests / PHP 8.3 (push) Has been cancelled
Tests / PHP 8.4 (push) Has been cancelled
Tests / PHP 8.5 (push) Has been cancelled

This commit is contained in:
2026-06-08 17:45:15 +08:00
parent 3cb68bc6b0
commit 32c3e3af69
26 changed files with 1170 additions and 371 deletions

View File

@@ -16,6 +16,7 @@ use Modules\ProjectManagement\Models\Project;
use Modules\ProjectManagement\Models\ProjectMilestone;
use Modules\ProjectManagement\Models\Task;
use Modules\Labors\Models\Labor;
use Modules\MasterData\Models\Team;
use Modules\MasterData\Models\EquipmentRate;
use Barryvdh\DomPDF\Facade\Pdf;
use PhpOffice\PhpSpreadsheet\Spreadsheet;
@@ -89,7 +90,7 @@ class ProjectController extends Controller
public function create()
{
$employees = User::whereIn('user_type', ['admin', 'employee'])->with('employeeProfile')->select('id', 'ulid', 'name', 'email')->get();
$employees = User::whereIn('user_type', ['admin', 'employee'])->with('employeeProfile')->select('id', 'ulid', 'name', 'email', 'profile_picture')->get();
$projects = Project::active()->with('parentProject:id,ulid,name,code')->get(['id', 'ulid', 'name', 'code', 'parent_project_id', 'project_type']);
return Inertia::render('ProjectManagement::Projects/Create', [
@@ -181,7 +182,7 @@ class ProjectController extends Controller
$employees = User::whereIn('user_type', ['admin', 'employee'])
->with('employeeProfile')
->select('id', 'ulid', 'name', 'email')
->select('id', 'ulid', 'name', 'email', 'profile_picture')
->get();
return Inertia::render('ProjectManagement::Projects/Team', [
@@ -239,7 +240,7 @@ class ProjectController extends Controller
'materialsEstimates.material',
]);
$employees = User::whereIn('user_type', ['admin', 'employee'])->with('employeeProfile')->select('id', 'ulid', 'name', 'email')->get();
$employees = User::whereIn('user_type', ['admin', 'employee'])->with('employeeProfile')->select('id', 'ulid', 'name', 'email', 'profile_picture')->get();
$projects = Project::active()->with('parentProject:id,ulid,name,code')->where('id', '!=', $project->id)->get(['id', 'ulid', 'name', 'code', 'parent_project_id', 'project_type']);
$materials = \Modules\MasterData\Models\Material::where('type', 'single')
@@ -407,9 +408,10 @@ class ProjectController extends Controller
'milestones' => fn ($q) => $q->orderBy('sort_order'),
'tasks' => fn ($q) => $q->with(['taskLabors.labor.skills', 'taskEquipments', 'taskIssues'])->orderBy('sort_order'),
'materialsEstimates.material',
'personnel:id,ulid,name,email',
]);
$employees = User::whereIn('user_type', ['admin', 'employee'])->with('employeeProfile')->select('id', 'ulid', 'name', 'email')->get();
$employees = User::whereIn('user_type', ['admin', 'employee'])->with('employeeProfile')->select('id', 'ulid', 'name', 'email', 'profile_picture')->get();
$parentProjects = Project::active()->with('parentProject:id,ulid,name,code')->where('id', '!=', $project->id)->get(['id', 'ulid', 'name', 'code', 'parent_project_id', 'project_type']);
$materials = \Modules\MasterData\Models\Material::where('type', 'single')
->where('status', 'active')
@@ -438,6 +440,7 @@ class ProjectController extends Controller
$labors = \Modules\Labors\Models\Labor::with('skills')->active()->get();
$equipments = \Modules\Equipments\Models\Equipment::with('specifications')->active()->get();
$teams = Team::with('users:id,ulid,name,email')->active()->get();
$workflowService = app(\Modules\ProjectManagement\Services\ProjectWorkflowService::class);
$budget = $workflowService->getBudgetAnalysis($project);
@@ -452,6 +455,7 @@ class ProjectController extends Controller
'labors' => $labors,
'equipments' => $equipments,
'budget' => $budget,
'teams' => $teams,
]);
}
@@ -598,6 +602,10 @@ class ProjectController extends Controller
'labor.*.task_ulid' => 'required|string',
'labor.*.labor_ulid' => 'required|string',
'labor.*.estimated_hours' => 'required|numeric|min:0',
'team_ulids' => 'nullable|array',
'team_ulids.*' => 'string|exists:teams,ulid',
'user_ulids' => 'nullable|array',
'user_ulids.*' => 'string|exists:users,ulid',
]);
\DB::transaction(function () use ($project, $validated) {
@@ -621,6 +629,38 @@ class ProjectController extends Controller
->whereNotIn('id', $existingLaborIds)
->delete();
// Synchronize project personnel pool
$userIds = [];
// Add users from selected teams
if (!empty($validated['team_ulids'])) {
$teams = Team::whereIn('ulid', $validated['team_ulids'])->with('users')->get();
foreach ($teams as $team) {
foreach ($team->users as $user) {
$userIds[$user->id] = ['role' => 'member'];
}
}
}
// Add individual users
if (!empty($validated['user_ulids'])) {
$users = User::whereIn('ulid', $validated['user_ulids'])->get();
foreach ($users as $user) {
$userIds[$user->id] = ['role' => 'member'];
}
}
// Keep existing PM if present
$pm = $project->personnel()->wherePivot('role', 'pm')->first();
if ($pm) {
$userIds[$pm->id] = ['role' => 'pm'];
}
// Sync the project personnel
if (isset($validated['team_ulids']) || isset($validated['user_ulids'])) {
$project->personnel()->sync($userIds);
}
if ($project->current_wizard_step < 5) {
$project->update(['current_wizard_step' => 5]);
}