Bicycle/App/Repositories/AccountRateRepository.php
2026-08-15 19:40:29 +03:00

79 lines
3.5 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
/**
* @package Bicycle
* @author Egor Isaev
* @description AccountRateRepository.php
* @copyright (c) 11/08/2026
*/
namespace App\Repositories;
use DateTimeImmutable;
use System\Classes\MyException;
use System\Classes\Repository;
/**
* Репозиторий таблицы account_rates (история процентных ставок savings-счёта).
*/
class AccountRateRepository extends Repository
{
/**
* @param string|null $connection Имя подключения (Database::instance($connection)); null — по умолчанию
*/
public function __construct(?string $connection = null)
{
parent::__construct('account_rates', connection: $connection);
}
/**
* Текущая ставка счёта (запись с valid_to IS NULL — см. бюджет_текущий_план.md).
*
* @param int $account_id
* @return object|false|null Строка account_rates | false, если не найдено | null (не бывает — $where не пуст)
*/
public function getCurrentRate(int $account_id): mixed
{
return $this->getItemWhere("account_id = $account_id AND valid_to IS NULL");
}
/**
* Меняет ставку задним/будущим числом — не правит старую строку, а закрывает её
* (`valid_to` = день перед новым `valid_from`) и открывает новую, чтобы не потерять историю
* за уже прошедшие периоды (см. бюджет_текущий_план.md → Account_rates → «При изменении
* ставки»). Атомарно — `Repository::transaction()` (на вложенном уровне — SAVEPOINT).
*
* @param int $account_id
* @param float $rate_percent Новая ставка, % годовых
* @param string $valid_from Дата, с которой действует новая ставка (Y-m-d) — не обязательно
* «сегодня», банк мог прислать уведомление заранее/задним числом
* @return void
* @throws MyException Если $valid_from не позже даты начала текущей ставки — иначе закрытая
* строка получила бы valid_to раньше собственного valid_from
*/
public function setRate(int $account_id, float $rate_percent, string $valid_from): void
{
$this->transaction(function () use ($account_id, $rate_percent, $valid_from) {
$current = $this->getCurrentRate($account_id);
if ($current) {
if ($valid_from <= $current->valid_from) {
throw new MyException(
'Дата новой ставки (:new) должна быть позже даты начала текущей (:current)',
[':new' => $valid_from, ':current' => $current->valid_from]
);
}
$valid_to = (new DateTimeImmutable($valid_from))->modify('-1 day')->format('Y-m-d');
$this->update(['id' => $current->id, 'valid_to' => $valid_to]);
}
$this->create([
'account_id' => $account_id,
'rate_percent' => $rate_percent,
'valid_from' => $valid_from,
'valid_to' => null,
]);
});
}
}