Skip to content
Merged

Dev #3145

Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
74 changes: 50 additions & 24 deletions app/Console/Commands/ExportCertificatesProof.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ public function handle()
// ---- Window normalize
$start = $this->option('start') ?: now()->subYear()->startOfDay()->toDateTimeString();
$end = $this->option('end') ?: now()->endOfDay()->toDateTimeString();

if (preg_match('/^\d{4}-\d{2}-\d{2}$/', $start)) $start .= ' 00:00:00';
if (preg_match('/^\d{4}-\d{2}-\d{2}$/', $end)) $end .= ' 23:59:59';

Expand All @@ -41,25 +42,24 @@ public function handle()

$path = $this->option('path') ?: $defaultPath;

// Build rows ensuring SuperOrganiser is appended last
// ---- Build rows (SuperOrganiser appended last)
$rows = collect();

if ($family === 'participations' || $family === 'both') {
$rows = $rows->merge($this->exportParticipations($start, $end, $inclusive, $datePref));
}

$soRows = collect();
$soRows = collect(); // will be appended at end
if ($family === 'excellence' || $family === 'both') {
[$exRows, $soRows] = $this->exportExcellenceSplit($start, $end, $inclusive, $datePref);
$rows = $rows->merge($exRows);
}

// Append SuperOrganiser rows at the END
if ($soRows->isNotEmpty()) {
$rows = $rows->merge($soRows);
}

// Write CSV
// ---- Write CSV
$stream = fopen('php://temp', 'w+');
fputcsv($stream, [
'family', 'record_id', 'issued_at', 'event_date',
Expand Down Expand Up @@ -92,39 +92,48 @@ public function handle()

$this->info("Wrote {$rows->count()} rows to storage/app/{$path}");
$this->line('Breakdown:');

// Monthly breakdowns for all three "families"
$this->printMonthlyParticipations($start, $end, $inclusive, $datePref);
$this->printMonthlyExcellenceSplit($start, $end, $inclusive, $datePref);

// Totals by family (for quick reconciliation)
$this->line('Totals:');
$totPart = $rows->where('family','participations')->count();
$totEx = $rows->where('family','excellence')->count();
$totSO = $rows->where('family','superorganiser')->count();
$this->line(" participations: $totPart");
$this->line(" excellence: $totEx");
$this->line(" superorganiser: $totSO");
$this->line(" ALL: ".($totPart+$totEx+$totSO));

return self::SUCCESS;
}

// ---------- Helpers ----------

protected function pickDateColumn(string $table, string $preferred): ?string
{
// Respect requested preference first
if ($preferred === 'event_date' && Schema::hasColumn($table, 'event_date')) return 'event_date';
if ($preferred === 'issued_at' && Schema::hasColumn($table, 'issued_at')) return 'issued_at';
if ($preferred === 'created_at' && Schema::hasColumn($table, 'created_at')) return 'created_at';
// Fallbacks
foreach (['created_at','issued_at','event_date','date'] as $c) {
if (Schema::hasColumn($table, $c)) return $c;
}
return null;
}

/**
* Resolve the excellence table name on this server (case/variant safe).
*/
protected function excellenceTable(): ?string
{
if (Schema::hasTable('excellences')) return 'excellences';
if (Schema::hasTable('CertificatesOfExcellence')) return 'CertificatesOfExcellence';
return null;
}

protected function normalizeType(?string $t): ?string
{
if ($t === null) return null;
return strtolower(str_replace('-', '', $t));
}
// ---------- Participations ----------

protected function exportParticipations(string $start, string $end, bool $inclusive, string $datePref)
{
Expand Down Expand Up @@ -188,6 +197,8 @@ protected function exportParticipations(string $start, string $end, bool $inclus
});
}

// ---------- Excellence + SuperOrganiser (split) ----------

/**
* Returns [Collection $excellenceWithoutSO, Collection $superOrganiser]
*/
Expand All @@ -201,6 +212,10 @@ protected function exportExcellenceSplit(string $start, string $end, bool $inclu
$dateExpr = "$alias.$dateCol";

$q = DB::table("$exTable as $alias")
// join users if we have user_id, to recover email when absent on the table
->when(Schema::hasColumn($exTable,'user_id'), function($q) use ($alias) {
$q->leftJoin('users as u', 'u.id', '=', "$alias.user_id");
})
->whereBetween($dateExpr, [$start, $end])
->orderBy("$alias.id");

Expand All @@ -214,13 +229,23 @@ protected function exportExcellenceSplit(string $start, string $end, bool $inclu
}

// Build select list defensively
$select = ["$alias.id as record_id", DB::raw("$dateExpr as issued_at")];
$select[] = Schema::hasColumn($exTable,'event_date') ? "$alias.event_date" : DB::raw('NULL as event_date');
$select[] = Schema::hasColumn($exTable,'status') ? "$alias.status" : DB::raw('NULL as status');
$select = [
"$alias.id as record_id",
DB::raw("$dateExpr as issued_at"),
Schema::hasColumn($exTable,'event_date') ? "$alias.event_date" : DB::raw('NULL as event_date'),
Schema::hasColumn($exTable,'status') ? "$alias.status" : DB::raw('NULL as status'),
];

if (Schema::hasColumn($exTable,'email')) $select[] = "$alias.email as owner_email";
elseif (Schema::hasColumn($exTable,'user_email')) $select[] = "$alias.user_email as owner_email";
else $select[] = DB::raw('NULL as owner_email');
// owner_email: prefer table email columns, else users.email
if (Schema::hasColumn($exTable, 'email')) {
$select[] = DB::raw("COALESCE($alias.email, NULL) as owner_email");
} elseif (Schema::hasColumn($exTable, 'user_email')) {
$select[] = DB::raw("COALESCE($alias.user_email, NULL) as owner_email");
} elseif (Schema::hasColumn($exTable, 'user_id')) {
$select[] = DB::raw("COALESCE(u.email, NULL) as owner_email");
} else {
$select[] = DB::raw('NULL as owner_email');
}

$select[] = Schema::hasColumn($exTable,'event_id') ? "$alias.event_id" : DB::raw('NULL as event_id');
$select[] = Schema::hasColumn($exTable,'title') ? "$alias.title" : DB::raw('NULL as title');
Expand All @@ -229,7 +254,6 @@ protected function exportExcellenceSplit(string $start, string $end, bool $inclu
elseif (Schema::hasColumn($exTable,'url')) $select[] = "$alias.url as certificate_url";
else $select[] = DB::raw('NULL as certificate_url');

// Excellence type (raw + normalized)
if (Schema::hasColumn($exTable,'type')) {
$select[] = "$alias.type as excellence_type";
$select[] = DB::raw("LOWER(REPLACE($alias.type,'-','')) as excellence_type_norm");
Expand Down Expand Up @@ -270,6 +294,8 @@ protected function exportExcellenceSplit(string $start, string $end, bool $inclu
return [$ex, $so];
}

// ---------- Monthly printers ----------

protected function printMonthlyParticipations(string $start, string $end, bool $inclusive, string $datePref): void
{
$table = 'participations';
Expand Down Expand Up @@ -304,22 +330,22 @@ protected function printMonthlyExcellenceSplit(string $start, string $end, bool
$dateCol = $this->pickDateColumn($table, $datePref) ?? 'created_at';
$dateExpr = "$alias.$dateCol";

// Base query builder
$base = DB::table("$table as $alias")->whereBetween($dateExpr, [$start, $end]);

if (!$inclusive && Schema::hasColumn($table, 'status')) {
$base->where("$alias.status",'DONE');
}
if (!$inclusive) {
$urlCol = Schema::hasColumn($table, 'certificate_url') ? 'certificate_url'
: (Schema::hasColumn($table, 'url') ? 'url' : null);
$urlCol = Schema::hasColumn($table,'certificate_url') ? 'certificate_url'
: (Schema::hasColumn($table,'url') ? 'url' : null);
if ($urlCol) $base->whereNotNull("$alias.$urlCol");
}

// Excellence (excluding SO)
$exQ = clone $base;
$exQ->when(Schema::hasColumn($table,'type'), function($q) use($alias){
$q->whereRaw("LOWER(REPLACE($alias.type,'-','')) <> 'superorganiser'");
});
if (Schema::hasColumn($table,'type')) {
$exQ->whereRaw("LOWER(REPLACE($alias.type,'-','')) <> 'superorganiser'");
}
$exMonthly = $exQ->selectRaw('DATE_FORMAT('.$dateExpr.', "%Y-%m") as yyyymm, COUNT(*) as cnt')
->groupBy('yyyymm')->orderBy('yyyymm')->get();

Expand Down
Loading