Files
Investidor-V2/app/Console/Commands/ReconcileInvestmentIdentity.php
nala 250ac35fd1
tests / ci (push) Canceled after 0s
first commit
2026-09-28 10:01:09 +02:00

48 lines
2.2 KiB
PHP

<?php
namespace App\Console\Commands;
use App\Models\Opportunity;
use App\Services\InvestmentIdentity;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Str;
class ReconcileInvestmentIdentity extends Command
{
protected $signature = 'investment:reconcile-identities {--apply : Apply direct opportunity-ID mappings after backup}';
protected $description = 'Dry-run or apply idempotent canonical mappings without changing legacy records or merging projects';
public function handle(InvestmentIdentity $identity): int
{
if (! app()->environment('local', 'testing')) {
$this->error('This migration command is restricted to local/testing environments.');
return self::FAILURE;
}
$report = DB::transaction(function () use ($identity) {
$ids = Opportunity::orderBy('id')->pluck('id');
$missing = $ids->diff(DB::table('investment_item_opportunities')->pluck('opportunity_id'))->values();
if ($this->option('apply')) {
foreach ($missing as $id) {
$identity->forOpportunity($id);
}
}
return ['generated_at' => now()->toIso8601String(), 'mode' => $this->option('apply') ? 'apply' : 'dry-run',
'opportunity_count' => $ids->count(), 'missing_before' => $missing->count(),
'missing_after' => $ids->diff(DB::table('investment_item_opportunities')->pluck('opportunity_id'))->count(),
'unmapped_project_count' => DB::table('projects')->whereNull('deleted_at')->whereNotIn('id', DB::table('investment_item_projects')->select('project_id'))->count(),
'changes_to_legacy_records' => 0, 'automatic_project_merges' => 0,
'rule' => 'Map stable opportunity primary keys only. Project correspondence requires documentary reconciliation.'];
});
$path = 'zone-reconciliation/'.now()->format('Ymd-His').'-'.Str::uuid().'.json';
Storage::disk('local')->put($path, json_encode($report, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR));
$this->line(json_encode([...$report, 'private_report' => $path], JSON_THROW_ON_ERROR));
return self::SUCCESS;
}
}