79 lines
3.5 KiB
PHP
79 lines
3.5 KiB
PHP
<?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,
|
||
]);
|
||
});
|
||
}
|
||
}
|