mdn-backend / app /Domain /Analytics /AnalyticsFunnelRepository.php
internationalscholarsprogram's picture
feat(analytics): website analytics pipeline — ingestion, rollup, admin query
45dc401
Raw
History Blame Contribute Delete
3.17 kB
<?php
declare(strict_types=1);
namespace App\Domain\Analytics;
use App\Infrastructure\Database\BaseRepository;
use App\Infrastructure\Ids\UuidGenerator;
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\DB;
final class AnalyticsFunnelRepository extends BaseRepository
{
public function __construct(private readonly UuidGenerator $ids) {}
protected function table(): string
{
return 'analytics_funnel_progress';
}
protected function hasDeletedAtColumn(): bool
{
return false;
}
public function findByVisitorSessionModule(string $visitorId, string $sessionId, string $module): ?\stdClass
{
return DB::table($this->table())
->where('visitor_id', $visitorId)
->where('session_id', $sessionId)
->where('module', $module)
->first();
}
/**
* Idempotent: returns existing id if a row already exists for this triple.
*/
public function start(string $visitorId, string $sessionId, string $module): string
{
$existing = $this->findByVisitorSessionModule($visitorId, $sessionId, $module);
if ($existing) {
return $existing->id;
}
$id = $this->ids->generate();
$now = Carbon::now()->toDateTimeString();
DB::table($this->table())->insert([
'id' => $id,
'visitor_id' => $visitorId,
'session_id' => $sessionId,
'module' => $module,
'started_at' => $now,
'last_step_at' => $now,
'highest_step' => 0,
'submitted' => 0,
'abandoned' => 0,
'created_at' => $now,
'updated_at' => $now,
]);
return $id;
}
/**
* Advance highest_step monotonically. No-op if step is not higher than current value.
*/
public function advanceStep(string $id, int $step): void
{
$now = Carbon::now()->toDateTimeString();
DB::table($this->table())
->where('id', $id)
->where('highest_step', '<', $step)
->update([
'highest_step' => $step,
'last_step_at' => $now,
'updated_at' => $now,
]);
}
public function markSubmitted(string $id, string $applicationId, bool $feeWaived): void
{
$now = Carbon::now()->toDateTimeString();
DB::table($this->table())->where('id', $id)->update([
'submitted' => 1,
'submitted_at' => $now,
'application_id' => $applicationId,
'fee_waived' => $feeWaived ? 1 : 0,
'abandoned' => 0,
'abandoned_at' => null,
'updated_at' => $now,
]);
}
public function markAbandoned(string $id): void
{
$now = Carbon::now()->toDateTimeString();
DB::table($this->table())
->where('id', $id)
->where('submitted', 0)
->update([
'abandoned' => 1,
'abandoned_at' => $now,
'updated_at' => $now,
]);
}
}