CaiWuXiTong/app/Support/CourierQuotePeriods.php

78 lines
3.4 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
namespace App\Support;
use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\ValidationException;
/** A temporary quotation may execute during several separate, inclusive periods. */
final class CourierQuotePeriods
{
public static function rules(): array
{
return [
'execution_mode' => ['nullable', 'in:permanent,temporary'],
'periods' => ['nullable', 'array', 'min:1', 'max:20'],
'periods.*.effective_date' => ['required', 'date_format:Y-m-d'],
'periods.*.end_date' => ['required', 'date_format:Y-m-d'],
];
}
public static function normalize(array $data, string $start = 'effective_date', string $end = 'end_date'): array
{
Validator::make($data, self::rules())->validate();
if (empty($data['periods']) || ($data['execution_mode'] ?? null) === 'permanent') {
Validator::make($data, [$start => ['required', 'date_format:Y-m-d'], $end => ['nullable', 'date_format:Y-m-d']])->validate();
}
$mode = $data['execution_mode'] ?? (isset($data['periods']) || filled($data[$end] ?? null) ? 'temporary' : 'permanent');
if ($mode === 'permanent') {
$data[$end] = null;
$data['execution_periods'] = [];
return $data;
}
$periods = $data['periods'] ?? [['effective_date' => $data[$start] ?? null, 'end_date' => $data[$end] ?? null]];
Validator::make(['periods' => $periods], self::rules())->validate();
usort($periods, static fn ($a, $b) => strcmp($a['effective_date'], $b['effective_date']));
$previous = null;
foreach ($periods as $index => $period) {
if ($period['end_date'] < $period['effective_date']) {
throw ValidationException::withMessages([isset($data['periods']) ? 'periods' : $end => '截止日期不能早于开始日期。']);
}
if ($previous !== null && $period['effective_date'] <= $previous) {
throw ValidationException::withMessages(['periods' => '执行区间不能重叠或重复,开始和截止日期均包含当天。']);
}
$periods[$index] = array_intersect_key($period, array_flip(['effective_date', 'end_date']));
$previous = $period['end_date'];
}
$data[$start] = $periods[0]['effective_date'];
$data[$end] = $periods[count($periods) - 1]['end_date'];
$data['execution_periods'] = $periods;
return $data;
}
public static function payload(?array $payload, array $periods): ?array
{
$payload = $payload ?? [];
unset($payload['execution_periods']);
if ($periods !== []) $payload['execution_periods'] = $periods;
return $payload ?: null;
}
public static function label(array $periods, bool $temporary = true): string
{
return implode(';', array_map(static fn ($period) => $period['effective_date']
. (filled($period['end_date'] ?? null) ? ' 至 ' . $period['end_date'] : ' 起'), $periods))
. ($temporary ? '(临时)' : '');
}
public static function overlaps(array $a, array $b): bool
{
foreach ($a as $left) foreach ($b as $right) {
if ($left['effective_date'] <= ($right['end_date'] ?? '9999-12-31')
&& $right['effective_date'] <= ($left['end_date'] ?? '9999-12-31')) return true;
}
return false;
}
}