currentUser(); $validation = $this->buildValidation($request->post()); if (!$validation->check()) { return $this->json(['success' => false, 'errors' => $validation->errors()], 422); } $summa = (float)$request->post('summa'); if ($summa < 0) { return $this->json(['success' => false, 'errors' => ['summa' => 'Сумма не может быть отрицательной']], 422); } $type_acc = $request->post('type_acc'); $rate_percent = $request->post('rate_percent'); $data = [ 'user_id' => $user->id, 'type_acc' => $type_acc, 'title' => $request->post('title'), 'summa' => $summa, 'currency' => strtoupper((string)$request->post('currency')), 'description' => $request->post('description') !== '' ? $request->post('description') : null, 'include_in_total' => $request->post('include_in_total') !== null, 'is_delete' => false, 'order' => 0, ]; $account_repo = new AccountRepository(); $account_repo->transaction(static function () use ($account_repo, $data, $type_acc, $rate_percent) { $account_id = $account_repo->create($data); if ($type_acc === 'savings' && $rate_percent !== null && $rate_percent !== '') { (new AccountRateRepository())->create([ 'account_id' => $account_id, 'rate_percent' => (float)$rate_percent, 'valid_from' => date('Y-m-d'), 'valid_to' => null, ]); } return $account_id; }); return $this->json(['success' => true]); } /** * @return string JSON * @throws HTTPException|MyException */ public function editAction(): string { $request = Request::$current; $account_repo = new AccountRepository(); $account = $this->ownAccount($account_repo, (int)$request->param(0)); $validation = $this->buildValidation($request->post()); if (!$validation->check()) { return $this->json(['success' => false, 'errors' => $validation->errors()], 422); } $summa = (float)$request->post('summa'); if ($summa < 0) { return $this->json(['success' => false, 'errors' => ['summa' => 'Сумма не может быть отрицательной']], 422); } $account_repo->update([ 'id' => $account->id, 'type_acc' => $request->post('type_acc'), 'title' => $request->post('title'), 'summa' => $summa, 'currency' => strtoupper((string)$request->post('currency')), 'description' => $request->post('description') !== '' ? $request->post('description') : null, 'include_in_total' => $request->post('include_in_total') !== null, ]); return $this->json(['success' => true]); } /** * Архивация (is_delete = 1), не физическое удаление — см. бюджет_текущий_план.md → Accounts. * * @return string JSON * @throws HTTPException|MyException */ public function deleteAction(): string { $request = Request::$current; $account_repo = new AccountRepository(); $account = $this->ownAccount($account_repo, (int)$request->param(0)); $account_repo->update(['id' => $account->id, 'is_delete' => true]); return $this->json(['success' => true]); } /** * Возврат из архива (is_delete = 0). * * @return string JSON * @throws HTTPException|MyException */ public function restoreAction(): string { $request = Request::$current; $account_repo = new AccountRepository(); $account = $this->ownAccount($account_repo, (int)$request->param(0)); $account_repo->update(['id' => $account->id, 'is_delete' => false]); return $this->json(['success' => true]); } /** * Общие правила валидации формы счёта (create/edit). * * @param array $data * @return Validation */ protected function buildValidation(array $data): Validation { return Validation::factory($data) ->label('title', 'Название') ->label('type_acc', 'Тип') ->label('summa', 'Сумма') ->label('currency', 'Валюта') ->rule('title', 'required') ->rule('title', 'max_length', [128]) ->rule('type_acc', 'required') ->rule('type_acc', 'in', [['cash', 'bank', 'savings']]) ->rule('summa', 'required') ->rule('summa', 'numeric') ->rule('currency', 'required') ->rule('currency', 'in', [array_keys(Currency::LIST)]) ->rule('description', 'max_length', [255]); } /** * Бюджетный пользователь (App\Repositories\UserRepository), связанный с текущим логином * Services\Auth — см. App\Controller\IndexController за тем же паттерном. * * @return object * @throws HTTPException|MyException */ protected function currentUser(): object { $auth_user = Auth::instance()->getUser(); $user = (new UserRepository())->getByLogin($auth_user['login']); if (!$user) { throw HTTPException::factory(404); } return $user; } /** * Счёт по id, принадлежащий текущему пользователю — иначе 404 (не 403, чтобы не подтверждать * чужому пользователю сам факт существования id). * * @param AccountRepository $account_repo * @param int $id * @return object * @throws HTTPException|MyException */ protected function ownAccount(AccountRepository $account_repo, int $id): object { $user = $this->currentUser(); $account = $account_repo->get($id); if (!$account || (int)$account->user_id !== (int)$user->id) { throw HTTPException::factory(404); } return $account; } }