Files
Investidor-V2/app/Services/ExistingBusinessDrafts.php
T
nala 59d108a576
tests / ci (push) Canceled after 0s
resolvemos o problema dos ZEE e ZFI
2026-10-07 09:08:43 +02:00

106 lines
6.2 KiB
PHP

<?php
namespace App\Services;
use App\Models\ExistingBusiness;
use App\Models\ExistingBusinessObject;
use App\Models\User;
use App\Services\Mne\BusinessRepository;
use Illuminate\Support\Facades\Crypt;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Gate;
use Illuminate\Support\Facades\Validator;
use Illuminate\Support\Str;
use Illuminate\Validation\Rule;
final class ExistingBusinessDrafts
{
public const MODALITIES = ['company_sale', 'company_purchase', 'participation_sale', 'capital_increase', 'financial_investor', 'strategic_partner', 'buyer_search', 'position_assignment', 'franchise', 'asset_sale', 'asset_lease', 'business_unit_transfer', 'joint_venture', 'succession', 'recovery', 'expansion', 'internationalization', 'real_estate', 'agricultural_investment', 'land_right', 'mining_license', 'forestry_license', 'investment_project', 'business_partnership', 'financing_request', 'concession_opportunity', 'supply_opportunity'];
/** @param array<string,mixed> $input */
public function save(User $actor, array $input, ?string $id = null): ExistingBusiness
{
$data = Validator::make($input, [
'modality' => ['required', 'in:'.implode(',', self::MODALITIES)],
'sector_id' => ['sometimes', 'nullable', 'integer', Rule::exists('sectors', 'id')->whereNull('deleted_at')->where('is_active', true)],
'public_title' => ['sometimes', 'nullable', 'string', 'max:180'],
'activity_code' => ['sometimes', 'nullable', 'string', 'max:60'],
'stage' => ['sometimes', 'nullable', 'string', 'max:40'],
'objective' => ['sometimes', 'nullable', 'string', 'max:5000'],
'currency' => ['sometimes', 'nullable', 'regex:/^[A-Z]{3}$/', 'required_with:amount_min,amount_max'],
'amount_min' => ['sometimes', 'nullable', 'numeric', 'min:0', 'max:999999999999999999.99'],
'amount_max' => ['sometimes', 'nullable', 'numeric', 'min:0', 'gte:amount_min', 'max:999999999999999999.99'],
'available_percentage' => ['sometimes', 'nullable', 'numeric', 'between:0,100'],
'funds_use' => ['sometimes', 'nullable', 'string', 'max:10000'],
'classification' => ['required', 'in:internal,confidential,restricted'],
'version_no' => [$id ? 'required' : 'prohibited', 'integer', 'min:1'],
'reason' => ['required', 'string', 'min:10', 'max:1000'],
'payload' => ['required', 'array:'.implode(',', [...array_keys(BusinessFormSchema::fields()), 'wizard_version', 'wizard_step'])],
'payload.title' => ['required', 'string', 'max:200'],
'payload.description' => ['nullable', 'string', 'max:10000'],
'payload.declared_reason' => ['nullable', 'string', 'max:2000'],
'payload.source_reference' => ['nullable', 'string', 'max:2000'],
'payload.valid_until' => ['nullable', 'date_format:Y-m-d'],
...BusinessFormSchema::rules(),
])->validate();
return DB::transaction(function () use ($actor, $id, $data) {
if ($id) {
$business = app(BusinessRepository::class)->find($id, true);
Gate::forUser($actor)->authorize('update', $business);
abort_unless($business->version_no === $data['version_no'], 409, 'O rascunho foi alterado. Recarregue antes de gravar.');
$business->version_no++;
} else {
Gate::forUser($actor)->authorize('create', ExistingBusiness::class);
if (! $actor->exists || $actor->id < 1) {
abort(403, 'A conta deve estar registada.');
}
$business = new ExistingBusiness;
$business->code = 'MNE-'.Str::uuid();
$business->owner_user_id = $actor->id;
$business->version_no = 1;
$business->status = 'draft';
}
$business->fill(['modality' => $data['modality'], 'classification' => $data['classification'], 'payload' => $data['payload']]);
foreach (['public_title', 'activity_code', 'stage', 'objective', 'currency', 'amount_min', 'amount_max', 'available_percentage', 'funds_use'] as $field) {
if (array_key_exists($field, $data)) {
$business->{$field} = $data[$field];
}
}
if (array_key_exists('sector_id', $data)) {
$business->sector_id = $data['sector_id'];
}
$business->save();
$this->snapshot($business, $actor, $id ? 'updated' : 'created', $data['reason']);
return $business;
});
}
public function archive(User $actor, string $id, int $version, string $reason): void
{
Validator::make(['reason' => $reason], ['reason' => ['required', 'string', 'min:10', 'max:1000']])->validate();
DB::transaction(function () use ($actor, $id, $version, $reason) {
$business = app(BusinessRepository::class)->find($id, true);
Gate::forUser($actor)->authorize('delete', $business);
abort_unless($business->version_no === $version, 409);
$business->version_no++;
$business->save();
$business->delete();
$this->snapshot($business, $actor, 'archived', $reason);
});
}
/** @param array<string,mixed> $context */
public function snapshot(ExistingBusiness $business, User $actor, string $action, string $reason, array $context = []): void
{
$snapshot = json_encode(['context' => $context, 'record' => $business->attributesToArray(), 'payload' => $business->payload,
'objects' => ExistingBusinessObject::where('business_id', $business->id)->orderBy('id')->get()
->map(fn ($object) => [...$object->attributesToArray(), 'payload' => $object->payload])->all(),
], JSON_THROW_ON_ERROR);
DB::table('existing_business_revisions')->insert(['id' => (string) Str::uuid(), 'business_id' => $business->id,
'version_no' => $business->version_no, 'actor_id' => $actor->id, 'action' => $action,
'reason' => Crypt::encryptString($reason), 'snapshot' => Crypt::encryptString($snapshot), 'sha256' => hash('sha256', $snapshot)]);
}
}