Files
Investidor-V2/app/Services/PortalAudit.php
T
2026-09-29 08:41:57 +02:00

42 lines
2.2 KiB
PHP

<?php
namespace App\Services;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Str;
class PortalAudit
{
/** @param array<string, mixed> $data */
public static function save(Model $record, array $data, int $actor): void
{
DB::transaction(function () use ($record, $data, $actor) {
$created = ! $record->exists;
if (! $created) {
$locked = $record->newQuery()->where($record->getKeyName(), $record->getKey())->lockForUpdate()->firstOrFail();
$record->setRawAttributes($locked->getAttributes(), true);
}
// Exclude free text and personal data from the immutable event payload.
$fields = ['primary_territory_id', 'territory_version', 'version_no', 'status', 'is_active', 'is_featured', 'sort_order', 'sector_id', 'maturity_level',
'estimated_investment_amount', 'estimated_investment_currency', 'owner_user_id', 'assignee_user_id', 'due_at',
'cluster_id', 'project_id', 'corridor_id', 'dossier_id', 'interest_request_id', 'publication_status', 'editor_id', 'reviewer_id', 'role', 'stage', 'value_chain_id', 'from_value_chain_id', 'to_value_chain_id', 'link_type', 'deleted_at'];
$before = array_intersect_key($record->getAttributes(), array_flip($fields));
$record->fill($data);
$changed = array_keys($record->getDirty());
$record->save();
if (! $changed) {
return;
}
DB::table('audit_events')->insert([
'source_system' => 'portal-management', 'actor_user_id' => $actor,
'entity_type' => $record->getTable(), 'entity_id' => Str::isUuid((string) $record->getKey()) ? $record->getKey() : null,
'action' => $created ? 'created' : 'updated',
'before_data' => json_encode(['record_id' => $record->getKey(), 'values' => $before], JSON_THROW_ON_ERROR),
'after_data' => json_encode(['record_id' => $record->getKey(), 'changed_fields' => $changed,
'values' => array_intersect_key($record->getAttributes(), array_flip($fields))], JSON_THROW_ON_ERROR),
]);
});
}
}