Snapshot of main at 9f39a6e1e (2026-11-02)
This commit is contained in:
commit
6ccf1792d7
2580 files changed
+1040202
No files matched your search
@@ -0,0 +1,87 @@
|
||||
<?php
|
||||
|
||||
namespace App\Console\Commands;
|
||||
|
||||
use App\Models\Organization;
|
||||
use App\Models\User;
|
||||
use Illuminate\Console\Command;
|
||||
|
||||
/**
|
||||
* One-off: give incomplete_at a plausible historical date.
|
||||
*
|
||||
* profiles:mark-incomplete stamps "now" the first time it runs, so every
|
||||
* profile that was already incomplete shares a single timestamp and the
|
||||
* statistics chart shows one vertical step instead of a history.
|
||||
*
|
||||
* IMPORTANT: the database records no history of profile completeness — the
|
||||
* fields the rule reads are mutable and carry no audit trail. Any backdated
|
||||
* date is therefore an estimate, not a fact. Registration date is used as the
|
||||
* best defensible approximation: a profile that is incomplete today and has
|
||||
* never been filled in was, in all likelihood, incomplete from the start. It
|
||||
* overstates history for the rarer case of a profile that was once complete
|
||||
* and later emptied.
|
||||
*
|
||||
* Only touches rows stamped by the initial bulk run (same day), so it cannot
|
||||
* overwrite a genuine timestamp recorded by a later nightly run.
|
||||
*/
|
||||
class BackdateIncompleteProfiles extends Command
|
||||
{
|
||||
protected $signature = 'profiles:backdate-incomplete
|
||||
{--dry-run : Report what would change without writing}
|
||||
{--on= : Only backdate rows stamped on this date (Y-m-d); defaults to today}';
|
||||
|
||||
protected $description = 'Estimate when each incomplete profile became incomplete, so the statistics show a history';
|
||||
|
||||
private const TYPES = [User::class, Organization::class];
|
||||
|
||||
public function handle(): int
|
||||
{
|
||||
$dryRun = (bool) $this->option('dry-run');
|
||||
$on = $this->option('on')
|
||||
? \Carbon\Carbon::parse($this->option('on'))->startOfDay()
|
||||
: now()->startOfDay();
|
||||
|
||||
$this->warn('Backdated dates are estimates: profile completeness has no recorded history.');
|
||||
$this->line('Only rows stamped on ' . $on->toDateString() . ' are touched.');
|
||||
|
||||
$changed = 0;
|
||||
$skipped = 0;
|
||||
|
||||
foreach (self::TYPES as $type) {
|
||||
$table = (new $type)->getTable();
|
||||
|
||||
if (!\Schema::hasColumn($table, 'incomplete_at')) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$type::query()
|
||||
->whereNotNull('incomplete_at')
|
||||
->whereBetween('incomplete_at', [$on, $on->copy()->endOfDay()])
|
||||
->chunkById(500, function ($profiles) use (&$changed, &$skipped, $dryRun) {
|
||||
foreach ($profiles as $profile) {
|
||||
$estimate = $profile->created_at;
|
||||
|
||||
// Nothing to move it to, or it would land in the
|
||||
// future: leave the bulk stamp alone.
|
||||
if (!$estimate || $estimate->gte($profile->incomplete_at)) {
|
||||
$skipped++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!$dryRun) {
|
||||
$profile->incomplete_at = $estimate;
|
||||
$profile->saveQuietly();
|
||||
}
|
||||
|
||||
$changed++;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
$this->info($dryRun
|
||||
? "Dry run: {$changed} profiles would be backdated, {$skipped} left as they are."
|
||||
: "Backdated {$changed} profiles, left {$skipped} as they are.");
|
||||
|
||||
return self::SUCCESS;
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user