Files
portal/app/app/Repositories/PricingTierRepository.php
T
Дмитрий 1e0c0ab90a fix(billing): Plan 4 Task 2 code-review fixes (2 Important + 1 Minor)
- PricingTierResolver::resolveForCount — InvalidArgumentException на
  $leadOrdinal < 1 (closes I-1: defensive contract validation).
- PricingTierRepository::activeAt — explicit @var Collection<int,
  PricingTier> annotation для type narrowing (closes I-2; firstOrFail
  отвергнут — Stan ругается на Eloquent\Model return-type).
- PricingTierResolverTest — +1 unit test (8/8 PASS): throws на 0/-1.
- PricingTierRepositoryTest — +1 integration test (5/5 PASS): excludes
  inactive tiers (closes M-2 coverage gap).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-11 09:17:13 +03:00

45 lines
1.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
declare(strict_types=1);
namespace App\Repositories;
use App\Models\PricingTier;
use Carbon\CarbonInterface;
use Illuminate\Database\Eloquent\Collection;
/**
* DB-обёртка для текущей активной сетки pricing_tiers.
*
* Логика: для данной даты `$at` возвращаются все ступени с
* MAX(effective_from) WHERE effective_from <= $at AND is_active=true,
* сгруппированные по tier_no.
*
* Spec: docs/superpowers/specs/2026-05-11-plan4-billing-csv-admin-design.md §3.1
*/
final class PricingTierRepository
{
/**
* @return Collection<int, PricingTier>
*/
public function activeAt(CarbonInterface $at): Collection
{
// Для каждого tier_no берём строку с MAX(effective_from) <= $at
// (учёт сценария «новая сетка перекрывает старую»).
/** @var Collection<int, PricingTier> $result */
$result = PricingTier::query()
->where('is_active', true)
->where('effective_from', '<=', $at->toDateString())
->orderBy('tier_no')
->orderBy('effective_from', 'desc')
->get()
->groupBy('tier_no')
->map(fn (Collection $group) => $group->first())
->values()
->sortBy('tier_no')
->values();
return $result;
}
}