Files
api/services/nginx/app/classes/invoicing_period_utils.php
T

108 lines
3.6 KiB
PHP

<?php
namespace classes;
use InvalidArgumentException;
class invoicing_period_utils
{
/**
* Normalize date range for invoicing endpoints to full-day timestamps.
*
* @return array{dateFrom:string,dateTo:string}
*/
public static function normalizeDateRange(string $dateFrom, string $dateTo): array
{
if (!self::isValidDate($dateFrom)) {
throw new InvalidArgumentException('Invalid date format. Expected: Y-m-d Got: ' . $dateFrom);
}
if (!self::isValidDate($dateTo)) {
throw new InvalidArgumentException('Invalid date format. Expected: Y-m-d Got: ' . $dateTo);
}
if (strtotime($dateFrom) === false || strtotime($dateTo) === false) {
throw new InvalidArgumentException('Invalid date range provided');
}
if (strtotime($dateFrom) > strtotime($dateTo)) {
throw new InvalidArgumentException('Invalid date range. dateFrom must be before or equal to dateTo');
}
return [
'dateFrom' => date('Y-m-d 00:00:00', strtotime($dateFrom)),
'dateTo' => date('Y-m-d 23:59:59', strtotime($dateTo)),
];
}
/**
* Filter grouped orders down to orders that have at least one neighbor within the time window.
*
* @param array<string, array<int, array<string,mixed>>> $ordersByRegistration
* @return array<string, array<int, array<string,mixed>>>
*/
public static function filterPossibleDuplicates(array $ordersByRegistration, int $windowSeconds = 86400): array
{
$possibleDuplicates = [];
foreach ( $ordersByRegistration as $registration => $orderList ) {
if (count($orderList) < 2) {
continue;
}
$normalizedOrders = [];
foreach ( $orderList as $order ) {
$createdAt = (string)($order['created_at'] ?? '');
$timestamp = strtotime($createdAt);
if ($timestamp === false) {
continue;
}
$order['_timestamp'] = $timestamp;
$normalizedOrders[] = $order;
}
if (count($normalizedOrders) < 2) {
continue;
}
usort($normalizedOrders, function (array $a, array $b) {
return (int)$a['_timestamp'] <=> (int)$b['_timestamp'];
});
$duplicateIndexes = [];
$count = count($normalizedOrders);
for ( $i = 0; $i < $count; $i++ ) {
$currentTimestamp = (int)$normalizedOrders[$i]['_timestamp'];
for ( $j = $i - 1; $j >= 0; $j-- ) {
$delta = $currentTimestamp - (int)$normalizedOrders[$j]['_timestamp'];
if ($delta > $windowSeconds) {
break;
}
$duplicateIndexes[$i] = true;
$duplicateIndexes[$j] = true;
}
}
if (count($duplicateIndexes) < 2) {
continue;
}
$possibleDuplicates[$registration] = [];
$indexes = array_keys($duplicateIndexes);
sort($indexes);
foreach ( $indexes as $index ) {
$order = $normalizedOrders[$index];
unset($order['_timestamp']);
$possibleDuplicates[$registration][] = $order;
}
}
return $possibleDuplicates;
}
private static function isValidDate(string $date): bool
{
$parsed = \DateTime::createFromFormat('Y-m-d', $date);
return $parsed !== false && $parsed->format('Y-m-d') === $date;
}
}