/
var
/
www
/
html
/
back
/
app
/
Domain
/
Article
/
Services
/
Upload File
HOME
<?php declare(strict_types=1); namespace App\Domain\Article\Services; use App\BaseClasses\BaseService; use App\Domain\Article\Requests\CreateArticleRequest; use App\Domain\Article\Requests\GetArticleListRequest; use App\Domain\Article\Requests\UpdateArticleRequest; use App\Models\Article; use App\Models\ArticleGroup; use App\Models\Payment; use App\Models\PaymentDistribution; use App\Models\Project; use App\Services\CashFlowService; use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\ModelNotFoundException; use Illuminate\Support\Facades\DB; class ArticleService extends BaseService { public function __construct(protected CashFlowService $cashFlowService) { } /** * Получить все статьи. * * @return Builder */ public function getAll(int $modelID, ?GetArticleListRequest $request): Builder { $query = Article::query() ->where('model_id', $modelID) ->with([ 'group', 'articleProjectLinks' ]); if ($request->has('search')) { $search = mb_convert_case($request->get('search'), MB_CASE_LOWER); $query->whereRaw('LOWER(name) LIKE ?', ["%{$search}%"]) ->orWhereHas('group', function ($q) use ($search, $modelID) { $q->where('model_id', $modelID); $q->whereRaw('LOWER(name) LIKE ?', ["%{$search}%"]); }); } if ($request->has('article_group_id')) { $query->where('article_group_id', $request->get('article_group_id')); } if ($request->has('article_type')) { $query->where('article_type', $request->get('article_type')); } if ($request->has('payment_id')) { /** @var Payment $payment */ $payment = Payment::find($request->get('payment_id')); $ids = []; foreach ($payment->distributions as $distribution) { $ids[] = $distribution->article->id; } $query->whereIn('id', $ids); } return $query; } /** * Создать новую статью. * * @param CreateArticleRequest $request * @return Article */ public function create(int $modelID, CreateArticleRequest $request): Article { return DB::transaction(function () use ($modelID, $request) { if (!empty($request->article_group_id)) { ArticleGroup::query() ->where('model_id', $modelID) ->where('id', $request->article_group_id) ->firstOrFail(); } $article = Article::create(array_merge($request->toArray(), ['model_id' => $modelID])); if ($request->sort) { $this->cashFlowService->moveArticleOrArticleGroupInCashFlow($article->id, $request->sort, $request->article_group_id); } return $article; }); } /** * Обновить существующую статью. * * @param int $id * @param UpdateArticleRequest $request * @return Article * @throws ModelNotFoundException */ public function update(int $id, UpdateArticleRequest $request): Article { $article = $this->findById($id); if (!empty($request->article_group_id)) { ArticleGroup::query() ->where('model_id', $article->model_id) ->where('id', $request->article_group_id)->firstOrFail(); } $article->update($request->toArray()); $article->fresh(['group']); return $article; } /** * Найти статью по ID. * * @param int $id * @return Article * @throws ModelNotFoundException */ public function findById(int $id): Article { return Article::query() ->with('group') ->with('projects') ->with('articleProjectLinks') ->findOrFail($id); } /** * Платежи по статье. * */ public function payments(int $id) { return PaymentDistribution::query()->where('article_id', $id)->sum('amount'); } /** * Удалить статью. * * @param int $id * @param int|null|string $newArticleId * @return bool */ public function delete(int $id, int|string $newArticleId = null): bool { return DB::transaction(function () use ($id, $newArticleId) { $article = $this->findById($id); if ($article->article_group_id) { $this->cashFlowService->sortArticleInGroupAfterDelete($article->article_group_id, $article->sort); } else { $this->cashFlowService->sortArticleWithoutGroupAfterDelete($article->sort); } $projectIds = $article->paymentDistributions->each(function (PaymentDistribution $pd) use ($newArticleId): void { $pd->update([ 'article_id' => $newArticleId, ]); }) ->map(fn (PaymentDistribution $pd) => $pd->project_id) ->filter()->unique()->values(); if (!empty($projectIds)) { $newArticle = $this->findById((int)$newArticleId); $this->attachToProjects($newArticle, $projectIds); } return $article->delete(); }); } public function setDefault(int $articleID, bool $isDefault): bool { $article = $this->findById($articleID); if ($isDefault) { $projects = $article->model->projects->pluck('id'); $this->attachToProjects($article, $projects); } else { $this->detachProjectsWithoutPayments($article); } return $article->update(['default_in_project' => $isDefault]); } private function attachToProjects(Article $article, iterable $projects): void { $projectIds = collect($projects) ->map(function (int|Project $project) { return $project instanceof Project ? $project->id : $project; }) ->unique() ->values() ->all(); if (empty($projectIds)) { return; } $article->projects()->syncWithoutDetaching($projectIds); } public function detachProjectsWithoutPayments(Article $article): void { $projectIds = $article->projects() ->whereDoesntHave('paymentDistributions', function ($query) use ($article) { $query->where('article_id', $article->id); }) ->pluck('projects.id') ->all(); if ($projectIds !== []) { $article->projects()->detach($projectIds); } } }