<?php
declare(strict_types=1);
namespace App\Domain\Account;
use App\BaseClasses\BaseService;
use App\Domain\Account\Requests\CreateAccountRequest;
use App\Domain\Account\Requests\UpdateAccountRequest;
use App\Domain\Payment\PaymentService;
use App\Models\Account;
use App\Requests\SearchRequest;
use Exception;
use Illuminate\Contracts\Pagination\Paginator;
use Illuminate\Database\Eloquent\ModelNotFoundException;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
class AccountService extends BaseService
{
protected PaymentService $paymentService;
public function __construct(
PaymentService $paymentService,
)
{
$this->paymentService = $paymentService;
}
/**
* Получить список всех счетов.
*
* @param int $modelID
*/
public function getAllAccounts(int $modelID, SearchRequest $request): Paginator
{
$query = Account::query()
->where(['model_id' => $modelID, 'archived' => false])
->with('organization');
if ($request->get('search')) {
$search = mb_convert_case($request->get('search'), MB_CASE_LOWER);
$query
->whereRaw('LOWER(name) LIKE ?', "%{$search}%");
}
if($request->has('is_cash')) {
$query->where('is_cash', $request->get('is_cash'));
}
return $query->simplePaginate(1000);
}
/**
* Получить счет по ID.
*
* @param int $id
* @return Account
* @throws ModelNotFoundException
*/
public function getAccountById(int $id): Account
{
return Account::query()->with(['payments', 'organization'])->findOrFail($id);
}
/**
* Создать новый счет.
*
* @param int $modelID
* @param CreateAccountRequest $request
* @return Account
*/
public function createAccount(int $modelID, CreateAccountRequest $request): Account
{
return Account::create(array_merge(['model_id' => $modelID], $request->toArray()));
}
/**
* Обновить данные счета.
*
* @param int $id
* @param UpdateAccountRequest $request
* @return Account
* @throws ModelNotFoundException
*/
public function updateAccount(int $id, UpdateAccountRequest $request): Account
{
$account = Account::findOrFail($id);
$account->update($request->toArray());
return $account;
}
/**
* Удалить счет.
*
* @param int $id
* @return bool
* @throws ModelNotFoundException
*/
public function deleteAccount(int $id): bool
{
$account = Account::findOrFail($id);
return $account->delete();
}
/**
* Пополнить баланс счета.
*
* @param int $id
* @param float $amount
* @return Account
* @throws ModelNotFoundException
*/
public function deposit(int $id, float $amount): Account
{
return DB::transaction(function () use ($id, $amount) {
$account = Account::findOrFail($id);
$account->deposit += $amount;
$account->save();
return $account;
});
}
/**
* Списать средства со счета.
*
* @param int $id
* @param float $amount
* @return Account
* @throws ModelNotFoundException
* @throws Exception
*/
public function withdraw(int $id, float $amount): Account
{
return DB::transaction(function () use ($id, $amount) {
$account = Account::findOrFail($id);
if ($account->deposit < $amount) {
throw new Exception('Недостаточно средств на счете');
}
$account->deposit -= $amount;
$account->save();
return $account;
});
}
public function extendedUpdate(int $accountId, Request $request): Account
{
$account = Account::find($accountId);
$account->update($request->toArray());
return $account;
}
public function transferOrganizationsAccounts(int $fromId, int $toId): bool
{
return Account::where('organization_id', $fromId)->update(['organization_id' => $toId]) >= 0;
}
public function transferPayments(int $fromId, int $toId): bool
{
return $this->paymentService->transferPayments('account_id', $fromId, $toId) >= 0;
}
}