Files
Investidor-V2/app/Http/Controllers/EducationInvestmentController.php
T
2026-09-30 12:59:28 +02:00

72 lines
3.8 KiB
PHP

<?php
namespace App\Http\Controllers;
use App\Models\EducationInvestmentProposal;
use App\Models\LabourDemand;
use App\Models\Opportunity;
use App\Services\InvestmentGeography;
use App\Services\PortalAudit;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Str;
use Illuminate\Validation\Rule;
class EducationInvestmentController extends Controller
{
public function store(Request $request, string $id): RedirectResponse
{
$data = $request->validate([
'demand_version' => ['required', 'integer', 'min:1'],
'sector_id' => ['required', 'integer', Rule::exists('sectors', 'id')->whereNull('deleted_at')],
'title' => ['required', 'string', 'max:200'],
'intervention' => ['required', 'string', 'min:20', 'max:10000'],
'equipment_needs' => ['nullable', 'string', 'max:5000'],
'trainer_needs' => ['nullable', 'string', 'max:5000'],
'funding_plan' => ['nullable', 'string', 'max:5000'],
'risks' => ['required', 'string', 'min:10', 'max:5000'],
'source' => ['required', 'string', 'min:10', 'max:5000'],
'currency' => ['required', Rule::in(['MZN', 'USD', 'EUR', 'ZAR'])],
'province_id' => ['required', 'uuid'],
'district_id' => ['nullable', 'uuid'],
'admin_post_id' => ['nullable', 'uuid'],
'locality_id' => ['nullable', 'uuid'],
]);
DB::transaction(function () use ($request, $id, $data): void {
$demand = LabourDemand::whereKey($id)->lockForUpdate()->firstOrFail();
abort_unless((int) $demand->getAttribute('version_no') === $data['demand_version'], 409, 'A procura foi alterada. Recarregue a análise.');
abort_unless($demand->getAttribute('status') === 'reviewed' && $demand->getAttribute('valid_until') >= now()->toDateString(),
422, 'A proposta exige procura revista e fonte vigente.');
// Serialising on the demand and unique FKs make repeated submissions safe.
if (EducationInvestmentProposal::withTrashed()->where('labour_demand_id', $id)->exists()) {
return;
}
$territory = app(InvestmentGeography::class)->selection($data, true);
$province = $territory[0];
$district = $territory[1] ?? null;
$primaryTerritory = $territory[array_key_last($territory)];
$reference = 'EDU-'.Str::uuid();
$opportunity = new Opportunity;
PortalAudit::save($opportunity, [
'sector_id' => $data['sector_id'], 'reference' => $reference,
'slug' => strtolower($reference), 'title' => $data['title'],
'summary' => 'Proposta educativa em preparação. Lacuna e viabilidade pendentes de validação institucional.',
'description' => $data['intervention'], 'estimated_investment_currency' => $data['currency'],
'province' => $province->name, 'district' => $district?->name,
'primary_territory_id' => $primaryTerritory->id, 'territory_version' => 1,
'status' => 'draft', 'is_featured' => false,
], $request->user()->id);
PortalAudit::save(new EducationInvestmentProposal, [
'labour_demand_id' => $id, 'demand_version' => $data['demand_version'],
'opportunity_id' => $opportunity->id, 'created_by' => $request->user()->id,
...array_intersect_key($data, array_flip(['intervention', 'equipment_needs', 'trainer_needs', 'funding_plan', 'risks', 'source'])),
], $request->user()->id);
});
return redirect('/management/education/demands/'.$id.'/analysis')
->with('success', 'Ficha educativa guardada em rascunho. Publicação sujeita a validação institucional.');
}
}