94 lines
3.4 KiB
PHP
94 lines
3.4 KiB
PHP
<?php
|
|
/**
|
|
* @package Bicycle
|
|
* @author Egor Isaev
|
|
* @description BudgetRepository.php
|
|
* @copyright (c) 11/08/2026
|
|
*/
|
|
|
|
namespace App\Repositories;
|
|
|
|
use PDO;
|
|
use System\Classes\Repository;
|
|
|
|
/**
|
|
* Репозиторий таблицы budgets (план по категории на месяц; факт считается на лету из transactions).
|
|
*/
|
|
class BudgetRepository extends Repository
|
|
{
|
|
/**
|
|
* @var string Таблица categories для JOIN в getYear() — вынесена в свойство (не хардкод в SQL),
|
|
* чтобы тесты могли подменить её на временную, не трогая боевую таблицу categories.
|
|
*/
|
|
protected string $categories_table = 'categories';
|
|
|
|
/**
|
|
* @param string|null $connection Имя подключения (Database::instance($connection)); null — по умолчанию
|
|
*/
|
|
public function __construct(?string $connection = null)
|
|
{
|
|
parent::__construct('budgets', connection: $connection);
|
|
}
|
|
|
|
/**
|
|
* План на год пользователя, сгруппированный по статье и месяцу — для сетки на странице плана.
|
|
*
|
|
* @param int $user_id
|
|
* @param int $year
|
|
* @return array<int,array<int,array{plan_summ:float,formula_pct_used:?float}>>
|
|
*/
|
|
public function getYear(int $user_id, int $year): array
|
|
{
|
|
$sql = "SELECT b.categorie_id, b.month, b.plan_summ, b.formula_pct_used
|
|
FROM $this->table b
|
|
INNER JOIN $this->categories_table c ON c.id = b.categorie_id
|
|
WHERE c.user_id = :user_id AND b.year = :year";
|
|
|
|
$stmt = $this->pdo->prepare($sql);
|
|
$stmt->execute(['user_id' => $user_id, 'year' => $year]);
|
|
|
|
$result = [];
|
|
|
|
foreach ($stmt->fetchAll(PDO::FETCH_ASSOC) as $row) {
|
|
$result[(int)$row['categorie_id']][(int)$row['month']] = [
|
|
'plan_summ' => (float)$row['plan_summ'],
|
|
'formula_pct_used' => $row['formula_pct_used'] !== null ? (float)$row['formula_pct_used'] : null,
|
|
];
|
|
}
|
|
|
|
return $result;
|
|
}
|
|
|
|
/**
|
|
* Создать или обновить план статьи на конкретный месяц (по UNIQUE categorie_id+year+month).
|
|
*
|
|
* @param int $categorie_id
|
|
* @param int $year
|
|
* @param int $month
|
|
* @param float $plan_summ
|
|
* @param string $type income|expense
|
|
* @param float|null $formula_pct_used Только для строк, посчитанных по формуле связанной статьи
|
|
* @return void
|
|
*/
|
|
public function upsert(int $categorie_id, int $year, int $month, float $plan_summ, string $type, ?float $formula_pct_used = null): void
|
|
{
|
|
$existing = $this->getItemWhere("categorie_id = $categorie_id AND year = $year AND month = $month");
|
|
|
|
$data = [
|
|
'categorie_id' => $categorie_id,
|
|
'plan_summ' => $plan_summ,
|
|
'year' => $year,
|
|
'month' => $month,
|
|
'type' => $type,
|
|
'formula_pct_used' => $formula_pct_used,
|
|
];
|
|
|
|
if ($existing) {
|
|
$data['id'] = $existing->id;
|
|
$this->update($data);
|
|
} else {
|
|
$this->create($data);
|
|
}
|
|
}
|
|
}
|