63 lines
2.4 KiB
PHP
63 lines
2.4 KiB
PHP
<?php
|
|
|
|
namespace Modules\EcommerceFinance\Services;
|
|
|
|
use Illuminate\Database\ConnectionInterface;
|
|
use Illuminate\Database\DatabaseManager;
|
|
use Illuminate\Support\Str;
|
|
use Modules\EcommerceFinance\Repositories\StoreReportRepository;
|
|
|
|
/** Persistent invalidation by affected date, including dates removed by a period replacement. */
|
|
class StoreReportPaidSalesChanges
|
|
{
|
|
public const TABLE = 'store_report_paid_sales_dirty_dates';
|
|
public const VERSION = 'dates:v1:';
|
|
private readonly ConnectionInterface $connection;
|
|
|
|
public function __construct(DatabaseManager $database)
|
|
{
|
|
$this->connection = $database->connection((string) config('upstream_mirrors.connection', 'business_mirror'));
|
|
}
|
|
|
|
public function available(): bool
|
|
{
|
|
return $this->connection->getSchemaBuilder()->hasTable(self::TABLE);
|
|
}
|
|
|
|
public function markPeriod(string $reportMonth, string $platform): void
|
|
{
|
|
if (! $this->available()) return;
|
|
$dates = $this->connection->table(StoreReportRepository::PAID_SALES_SOURCE_TABLE)
|
|
->where('report_month', substr($reportMonth, 0, 7) . '-01')->where('platform', $platform)
|
|
->whereNotNull('occurred_date')->distinct()->pluck('occurred_date');
|
|
$this->markDates($dates->all());
|
|
}
|
|
|
|
public function markDates(array $dates): void
|
|
{
|
|
if (! $this->available()) return;
|
|
$revision = (string) Str::uuid();
|
|
$rows = array_map(fn ($date) => ['occurred_on' => $date, 'revision' => $revision], array_values(array_unique(array_filter($dates))));
|
|
foreach (array_chunk($rows, 500) as $chunk) {
|
|
$this->connection->table(self::TABLE)->upsert($chunk, ['occurred_on'], ['revision']);
|
|
}
|
|
}
|
|
|
|
public function pending(): array
|
|
{
|
|
return $this->connection->table(self::TABLE)->orderBy('occurred_on')->get()->map(fn ($row) => (array) $row)->all();
|
|
}
|
|
|
|
public function acknowledge(array $snapshot): void
|
|
{
|
|
foreach (array_chunk($snapshot, 100) as $chunk) {
|
|
// A write arriving during aggregation retains its newer revision for the next run.
|
|
$this->connection->table(self::TABLE)->where(function ($query) use ($chunk): void {
|
|
foreach ($chunk as $row) {
|
|
$query->orWhere(fn ($match) => $match->where('occurred_on', $row['occurred_on'])->where('revision', $row['revision']));
|
|
}
|
|
})->delete();
|
|
}
|
|
}
|
|
}
|