78 lines
3.0 KiB
PHP
78 lines
3.0 KiB
PHP
<?php
|
|
|
|
namespace App\Domains\Ticketing\Ticket\Services;
|
|
|
|
use Carbon\CarbonImmutable;
|
|
use DateTimeZone;
|
|
use Illuminate\Support\Facades\DB;
|
|
use InvalidArgumentException;
|
|
|
|
class ConvertValidityTimesToUtcService
|
|
{
|
|
/**
|
|
* IDs or the all flag select values the operator has confirmed are still local.
|
|
* UTC cannot be inferred reliably from a timezone-less database timestamp.
|
|
*
|
|
* @param array<int, int> $ids
|
|
* @return array<int, array<string, mixed>>
|
|
*/
|
|
public function run(array $ids, string $timezone, bool $apply = false, bool $all = false): array
|
|
{
|
|
if (! in_array($timezone, DateTimeZone::listIdentifiers(DateTimeZone::ALL_WITH_BC), true)) {
|
|
throw new InvalidArgumentException('Zona horaria de origen inválida.');
|
|
}
|
|
if ($all && $ids !== []) {
|
|
throw new InvalidArgumentException('Usar --all o --ids, no ambos.');
|
|
}
|
|
if (! $all && $ids === []) {
|
|
throw new InvalidArgumentException('Indicar --all para todos los fixed_window o --ids para una selección.');
|
|
}
|
|
|
|
return DB::transaction(function () use ($ids, $timezone, $apply): array {
|
|
$query = DB::table('validity_times')->orderBy('id');
|
|
if ($ids === []) {
|
|
$query->where('type', 'fixed_window');
|
|
} else {
|
|
$query->whereIn('id', $ids);
|
|
}
|
|
if ($apply) {
|
|
$query->lockForUpdate();
|
|
}
|
|
$rows = $query->get();
|
|
if ($ids !== [] && $rows->count() !== count(array_unique($ids))) {
|
|
throw new InvalidArgumentException('Uno o más IDs no existen. No se modificó ningún registro.');
|
|
}
|
|
if ($rows->contains(fn ($row): bool => $row->type !== 'fixed_window')) {
|
|
throw new InvalidArgumentException('Sólo se admiten IDs de fixed_window. No se modificó ningún registro.');
|
|
}
|
|
$result = [];
|
|
foreach ($rows as $row) {
|
|
$start = $this->convert($row->fixed_starts_at, $timezone);
|
|
$end = $this->convert($row->fixed_expires_at, $timezone);
|
|
$result[] = [
|
|
'id' => $row->id,
|
|
'status' => $apply ? 'convertido' : 'propuesta; verificar origen local',
|
|
'original_start' => $row->fixed_starts_at,
|
|
'original_end' => $row->fixed_expires_at,
|
|
'utc_start' => $start,
|
|
'utc_end' => $end,
|
|
];
|
|
if (! $apply) {
|
|
continue;
|
|
}
|
|
DB::table('validity_times')->where('id', $row->id)->update([
|
|
'fixed_starts_at' => $start,
|
|
'fixed_expires_at' => $end,
|
|
]);
|
|
}
|
|
|
|
return $result;
|
|
});
|
|
}
|
|
|
|
private function convert(?string $value, string $timezone): ?string
|
|
{
|
|
return $value === null ? null : CarbonImmutable::parse($value, $timezone)->utc()->format('Y-m-d H:i:s');
|
|
}
|
|
}
|