adasd
All checks were successful
Deploy / deploy-staging (push) Successful in 34s
Deploy / deploy-production (push) Has been skipped

This commit is contained in:
2026-08-22 00:09:13 +02:00
parent 49ea6bde76
commit c17566a7d2
5 changed files with 129 additions and 64 deletions

View File

@@ -700,7 +700,7 @@ final class AnalyticsService
continue;
}
$convertedDailyCost = $this->entryDailyCostInCurrency($entry, $runtimeMonths, $currency, $fxContext);
$convertedDailyCost = $this->entryDailyCostInCurrency($entry, $runtimeMonths, $currency, $fxContext, $startField);
if ($convertedDailyCost === null) {
continue;
}
@@ -712,9 +712,9 @@ final class AnalyticsService
return $matched ? $dailyTotal : null;
}
private function entryDailyCostInCurrency(array $entry, int $runtimeMonths, string $targetCurrency, ?array $fxContext = null): ?float
private function entryDailyCostInCurrency(array $entry, int $runtimeMonths, string $targetCurrency, ?array $fxContext = null, string $startField = 'starts_at'): ?float
{
$runtimeDays = $runtimeMonths * 30.4375;
$runtimeDays = $this->entryRuntimeDays($entry, $startField);
if ($runtimeDays <= 0) {
return null;
}
@@ -762,20 +762,16 @@ final class AnalyticsService
return null;
}
$storedDailyCost = is_numeric($entry['daily_cost_amount'] ?? null) ? (float) $entry['daily_cost_amount'] : null;
$entryCurrency = strtoupper(trim((string) ($entry['daily_cost_currency'] ?? $entry['currency'] ?? '')));
if ($entryCurrency === '') {
return null;
}
$dailyAmount = $storedDailyCost;
if ($dailyAmount === null || $dailyAmount <= 0) {
$amount = is_numeric($entry['total_cost_amount'] ?? null) ? (float) $entry['total_cost_amount'] : null;
if ($amount === null || $amount <= 0) {
return null;
}
$dailyAmount = $amount / $runtimeDays;
$amount = is_numeric($entry['total_cost_amount'] ?? null) ? (float) $entry['total_cost_amount'] : null;
if ($amount === null || $amount <= 0) {
return null;
}
$dailyAmount = $amount / $runtimeDays;
return $this->convertAmount($dailyAmount, $entryCurrency, $targetCurrency, $fxContext);
}
@@ -1094,8 +1090,10 @@ final class AnalyticsService
return false;
}
$runtimeDays = $runtimeMonths * 30.4375;
$endTs = (int) round($startTs + ($runtimeDays * 86400));
$endTs = $this->entryCoverageEndTimestamp($entry, $startField);
if ($endTs === null) {
return true;
}
return $this->entryAutoRenewEnabled($entry) || $checkTs <= $endTs;
}
@@ -1586,7 +1584,10 @@ final class AnalyticsService
$runtimeMonths = (int) ($plan['runtime_months'] ?? 0);
if ($runtimeMonths > 0 && is_numeric($plan['total_cost_amount'] ?? null)) {
$runtimeDays = $runtimeMonths * 30.4375;
$runtimeDays = $this->entryRuntimeDays($plan);
if ($runtimeDays <= 0) {
continue;
}
$dailyCost = $this->convertAmount((float) $plan['total_cost_amount'] / $runtimeDays, (string) ($plan['currency'] ?? ''), $currency, $latest);
if ($dailyCost !== null) {
$cost += $dailyCost * $coveredDays;
@@ -1610,7 +1611,10 @@ final class AnalyticsService
$runtimeMonths = (int) ($miner['runtime_months'] ?? 0);
if ($runtimeMonths > 0 && is_numeric($miner['total_cost_amount'] ?? null)) {
$runtimeDays = $runtimeMonths * 30.4375;
$runtimeDays = $this->entryRuntimeDays($miner, 'purchased_at');
if ($runtimeDays <= 0) {
continue;
}
$dailyCost = $this->convertAmount((float) $miner['total_cost_amount'] / $runtimeDays, (string) ($miner['currency'] ?? ''), $currency, $latest);
if ($dailyCost !== null) {
$cost += $dailyCost * $coveredDays;
@@ -1649,8 +1653,10 @@ final class AnalyticsService
return $days - $startIndex;
}
$runtimeDays = $runtimeMonths * 30.4375;
$endTs = (int) round($startTs + ($runtimeDays * 86400));
$endTs = $this->entryCoverageEndTimestamp($entry, $startField);
if ($endTs === null) {
return $days - $startIndex;
}
$endIndex = (int) floor(($endTs - $baseTs) / 86400);
$endIndex = min($days - 1, $endIndex);
if ($endIndex < $startIndex) {
@@ -2178,8 +2184,31 @@ final class AnalyticsService
return null;
}
$runtimeDays = $runtimeMonths * 30.4375;
return (int) round($startTs + ($runtimeDays * 86400));
return $this->calendarMonthEndTimestamp($startTs, $runtimeMonths);
}
private function entryRuntimeDays(array $entry, string $startField = 'starts_at'): float
{
$startTs = $this->utcTimestamp((string) ($entry[$startField] ?? ''));
$runtimeMonths = (int) ($entry['runtime_months'] ?? 0);
if ($startTs <= 0 || $runtimeMonths <= 0) {
return 0.0;
}
$endTs = $this->calendarMonthEndTimestamp($startTs, $runtimeMonths);
return $endTs > $startTs ? ($endTs - $startTs) / 86400 : 0.0;
}
private function calendarMonthEndTimestamp(int $startTs, int $runtimeMonths): int
{
$utc = new \DateTimeZone('UTC');
$start = (new \DateTimeImmutable('@' . $startTs))->setTimezone($utc);
$monthIndex = (((int) $start->format('Y')) * 12) + ((int) $start->format('n')) - 1 + $runtimeMonths;
$year = intdiv($monthIndex, 12);
$month = ($monthIndex % 12) + 1;
$day = min((int) $start->format('j'), cal_days_in_month(CAL_GREGORIAN, $month, $year));
return $start->setDate($year, $month, $day)->getTimestamp();
}
private function utcTimestamp(?string $value): int