*/ public function getAll(?bool $active = null): Collection { $query = TeamMember::with('role'); if ($active !== null) { $query->where('active', $active); } return $query->get(); } /** * Find a team member by ID. * * @param string $id * @return TeamMember|null */ public function findById(string $id): ?TeamMember { return TeamMember::with('role')->find($id); } /** * Create a new team member. * * @param array $data * @return TeamMember * @throws ValidationException */ public function create(array $data): TeamMember { $validator = Validator::make($data, [ 'name' => 'required|string|max:255', 'role_id' => 'required|integer|exists:roles,id', 'hourly_rate' => 'required|numeric|gt:0', 'active' => 'boolean', ], [ 'hourly_rate.gt' => 'Hourly rate must be greater than 0', ]); if ($validator->fails()) { throw new ValidationException($validator); } $teamMember = TeamMember::create([ 'name' => $data['name'], 'role_id' => $data['role_id'], 'hourly_rate' => $data['hourly_rate'], 'active' => $data['active'] ?? true, ]); $teamMember->load('role'); return $teamMember; } /** * Update an existing team member. * * @param TeamMember $teamMember * @param array $data * @return TeamMember * @throws ValidationException */ public function update(TeamMember $teamMember, array $data): TeamMember { $validator = Validator::make($data, [ 'name' => 'sometimes|string|max:255', 'role_id' => 'sometimes|integer|exists:roles,id', 'hourly_rate' => 'sometimes|numeric|gt:0', 'active' => 'sometimes|boolean', ], [ 'hourly_rate.gt' => 'Hourly rate must be greater than 0', ]); if ($validator->fails()) { throw new ValidationException($validator); } $teamMember->update($data); $teamMember->load('role'); return $teamMember; } /** * Delete a team member. * * @param TeamMember $teamMember * @return void * @throws \RuntimeException */ public function delete(TeamMember $teamMember): void { // Check if team member has allocations if ($teamMember->allocations()->exists()) { throw new \RuntimeException( 'Cannot delete team member with active allocations', 422 ); } // Check if team member has actuals if ($teamMember->actuals()->exists()) { throw new \RuntimeException( 'Cannot delete team member with historical data', 422 ); } $teamMember->delete(); } /** * Check if a team member can be deleted. * * @param TeamMember $teamMember * @return array{canDelete: bool, reason?: string} */ public function canDelete(TeamMember $teamMember): array { if ($teamMember->allocations()->exists()) { return [ 'canDelete' => false, 'reason' => 'Team member has active allocations', ]; } if ($teamMember->actuals()->exists()) { return [ 'canDelete' => false, 'reason' => 'Team member has historical data', ]; } return ['canDelete' => true]; } }