UniformFlow/app/Http/Controllers/HandoverController.php

84 lines
3.8 KiB
PHP

<?php
namespace App\Http\Controllers;
use App\Models\Employee;
use App\Models\Handover;
use App\Models\StockMovement;
use App\Models\UniformIssue;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Validation\Rule;
use Illuminate\Validation\ValidationException;
class HandoverController extends Controller
{
public function index()
{
return view('handovers.index', [
'employees' => Employee::where('status', 'active')->whereHas('issues', fn ($q) => $q->where('status', 'issued'))->orderBy('name')->get(),
'handovers' => Handover::with(['employee', 'items.issue.variant.item'])->latest('handover_date')->get(),
]);
}
public function create(Employee $employee)
{
$employee->load(['issues' => fn ($q) => $q->where('status', 'issued')->with('variant.item')]);
abort_if($employee->status !== 'active', 422, 'This employee has already left.');
return view('handovers.create', compact('employee'));
}
public function store(Request $request, Employee $employee)
{
$data = $request->validate([
'handover_date' => ['required', 'date'],
'notes' => ['nullable', 'string', 'max:1000'],
'items' => ['required', 'array'],
'items.*.issue_id' => ['required', 'integer', 'distinct', 'exists:uniform_issues,id'],
'items.*.condition' => ['required', Rule::in(['reusable', 'damaged', 'not_returned'])],
]);
DB::transaction(function () use ($data, $employee) {
$lockedEmployee = Employee::lockForUpdate()->findOrFail($employee->id);
if ($lockedEmployee->status !== 'active') {
throw ValidationException::withMessages(['employee' => 'This employee has already completed handover.']);
}
$openIssues = UniformIssue::where('employee_id', $employee->id)->where('status', 'issued')->lockForUpdate()->get()->keyBy('id');
if ($openIssues->count() !== count($data['items'])) {
throw ValidationException::withMessages(['items' => 'Every outstanding uniform must be accounted for before handover is completed.']);
}
$handover = Handover::create(['employee_id' => $employee->id, 'handover_date' => $data['handover_date'], 'notes' => $data['notes'] ?? null]);
foreach ($data['items'] as $itemData) {
$issue = $openIssues->get($itemData['issue_id']);
if (! $issue) {
throw ValidationException::withMessages(['items' => 'An invalid issue was submitted.']);
}
$quantity = $issue->outstanding_quantity;
$handover->items()->create(['uniform_issue_id' => $issue->id, 'quantity' => $quantity, 'condition' => $itemData['condition']]);
if ($itemData['condition'] === 'reusable') {
$issue->variant()->lockForUpdate()->first()->increment('quantity', $quantity);
StockMovement::create([
'stock_variant_id' => $issue->stock_variant_id,
'employee_id' => $employee->id,
'uniform_issue_id' => $issue->id,
'type' => 'return',
'quantity_change' => $quantity,
'notes' => 'Reusable return during employee exit handover',
]);
}
$issue->update(['returned_quantity' => $issue->quantity, 'status' => $itemData['condition'] === 'not_returned' ? 'not_returned' : 'returned']);
}
$lockedEmployee->update(['status' => 'left', 'left_at' => $data['handover_date']]);
});
return redirect()->route('handovers.index')->with('success', 'Handover completed and employee marked as left.');
}
}