feat(ticket): add command to convert fixed_window validity times between local timezone and UTC
This commit is contained in:
@@ -10,68 +10,56 @@ 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
|
||||
public function run(array $ids, string $timezone, bool $apply = false, bool $all = false, bool $reverse = false): array
|
||||
{
|
||||
if (! in_array($timezone, DateTimeZone::listIdentifiers(DateTimeZone::ALL_WITH_BC), true)) {
|
||||
throw new InvalidArgumentException('Zona horaria de origen inválida.');
|
||||
throw new InvalidArgumentException('Zona horaria 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.');
|
||||
if ($all === ($ids !== [])) {
|
||||
throw new InvalidArgumentException('Indicar --all o --ids, exclusivamente una opción.');
|
||||
}
|
||||
|
||||
return DB::transaction(function () use ($ids, $timezone, $apply): array {
|
||||
return DB::transaction(function () use ($ids, $timezone, $apply, $all, $reverse): array {
|
||||
$query = DB::table('validity_times')->orderBy('id');
|
||||
if ($ids === []) {
|
||||
$query->where('type', 'fixed_window');
|
||||
} else {
|
||||
$query->whereIn('id', $ids);
|
||||
}
|
||||
$all ? $query->where('type', 'fixed_window') : $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 (! $all && $rows->count() !== count(array_unique($ids))) {
|
||||
throw new InvalidArgumentException('Uno o más IDs no existen.');
|
||||
}
|
||||
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.');
|
||||
throw new InvalidArgumentException('Sólo se admiten IDs de fixed_window.');
|
||||
}
|
||||
$source = $reverse ? 'UTC' : $timezone;
|
||||
$target = $reverse ? $timezone : 'UTC';
|
||||
$result = [];
|
||||
foreach ($rows as $row) {
|
||||
$start = $this->convert($row->fixed_starts_at, $timezone);
|
||||
$end = $this->convert($row->fixed_expires_at, $timezone);
|
||||
$convert = fn (?string $value): ?string => $value === null
|
||||
? null
|
||||
: CarbonImmutable::parse($value, $source)->setTimezone($target)->format('Y-m-d H:i:s');
|
||||
$start = $convert($row->fixed_starts_at);
|
||||
$end = $convert($row->fixed_expires_at);
|
||||
$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,
|
||||
'result_start' => $start,
|
||||
'result_end' => $end,
|
||||
];
|
||||
if (! $apply) {
|
||||
continue;
|
||||
if ($apply) {
|
||||
DB::table('validity_times')->where('id', $row->id)->update([
|
||||
'fixed_starts_at' => $start,
|
||||
'fixed_expires_at' => $end,
|
||||
]);
|
||||
}
|
||||
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');
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user