Adiciona dotacoes e reservas orcamentais por empresa
This commit is contained in:
@@ -0,0 +1,69 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Enums\PurchasingRole;
|
||||
use App\Models\Budget;
|
||||
use App\Models\BudgetEntry;
|
||||
use App\Models\CostCenter;
|
||||
use App\Services\ConflictGuard;
|
||||
use App\Services\RequisitionWorkflow;
|
||||
use Brick\Math\BigDecimal;
|
||||
use Illuminate\Http\RedirectResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Validation\Rule;
|
||||
use Inertia\Inertia;
|
||||
use Inertia\Response;
|
||||
|
||||
class BudgetController extends Controller
|
||||
{
|
||||
private function access(Request $request): void
|
||||
{
|
||||
abort_unless(in_array($request->user()->purchasing_role, [PurchasingRole::Admin, PurchasingRole::Finance]), 403);
|
||||
}
|
||||
|
||||
public function index(Request $request): Response
|
||||
{
|
||||
$this->access($request);
|
||||
|
||||
return Inertia::render('budgets/index', ['centers' => CostCenter::query()->orderBy('code')->get(), 'budgets' => Budget::query()->latest('id')->get()->map(function (Budget $budget) {
|
||||
$entries = BudgetEntry::query()->where('budget_id', $budget->id);
|
||||
$reserved = (int) (clone $entries)->sum('reserved_minor');
|
||||
$committed = (int) $entries->sum('committed_minor');
|
||||
|
||||
return [...$budget->toArray(), 'reserved_minor' => $reserved, 'committed_minor' => $committed, 'available_minor' => $budget->amount_minor - $reserved - $committed];
|
||||
})]);
|
||||
}
|
||||
|
||||
public function store(Request $request): RedirectResponse
|
||||
{
|
||||
$this->access($request);
|
||||
$data = $request->validate(['cost_center_id' => ['required', 'integer', Rule::exists('cost_centers', 'id')->where('tenant_id', $request->user()->tenant_id)], 'year' => 'required|integer|min:2026|max:2100', 'includes_tax' => 'required|boolean', 'amount' => ['required', 'regex:/^\d{1,12}(\.\d{1,2})?$/'], 'reason' => 'required|string|max:4000']);
|
||||
DB::transaction(function () use ($request, $data) {
|
||||
app(ConflictGuard::class)->lockCompany($request->user());
|
||||
abort_if(Budget::query()->where('cost_center_id', $data['cost_center_id'])->where('year', $data['year'])->exists(), 409, 'Já existe dotação para este centro e exercício.');
|
||||
$budget = Budget::query()->create(['tenant_id' => $request->user()->tenant_id, 'created_by' => $request->user()->id, 'cost_center_id' => $data['cost_center_id'], 'year' => $data['year'], 'includes_tax' => $data['includes_tax'], 'amount_minor' => BigDecimal::of($data['amount'])->multipliedBy(100)->toInt(), 'reason' => $data['reason']]);
|
||||
app(RequisitionWorkflow::class)->audit($request->user(), 'budget.created', null, null, $budget->toArray());
|
||||
});
|
||||
|
||||
return back();
|
||||
}
|
||||
|
||||
public function approve(Request $request, Budget $budget): RedirectResponse
|
||||
{
|
||||
$this->access($request);
|
||||
DB::transaction(function () use ($request, $budget) {
|
||||
app(ConflictGuard::class)->lockCompany($request->user());
|
||||
$budget = Budget::query()->lockForUpdate()->findOrFail($budget->id);
|
||||
abort_if($budget->created_by === $request->user()->id, 403);
|
||||
if ($budget->approved_by) {
|
||||
return;
|
||||
}
|
||||
$budget->update(['approved_by' => $request->user()->id, 'approved_at' => now()]);
|
||||
app(RequisitionWorkflow::class)->audit($request->user(), 'budget.approved', null, null, $budget->toArray());
|
||||
});
|
||||
|
||||
return back();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user