EscolaLMS/Consultations

View on GitHub
src/Repositories/ConsultationUserTermRepository.php

Summary

Maintainability
A
1 hr
Test Coverage
C
76%
<?php

namespace EscolaLms\Consultations\Repositories;

use EscolaLms\Consultations\Dto\ConsultationUserResourceDto;
use EscolaLms\Consultations\Dto\ConsultationUserTermResourceDto;
use EscolaLms\Consultations\Dto\FilterConsultationTermsListDto;
use EscolaLms\Consultations\Enum\ConsultationTermStatusEnum;
use EscolaLms\Consultations\Models\ConsultationUserPivot;
use EscolaLms\Consultations\Models\ConsultationUserTerm;
use EscolaLms\Consultations\Repositories\Contracts\ConsultationUserTermRepositoryContract;
use EscolaLms\Core\Repositories\BaseRepository;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Collection;

class ConsultationUserTermRepository extends BaseRepository implements ConsultationUserTermRepositoryContract
{
    protected $fieldSearchable = [];

    public function getFieldsSearchable(): array
    {
        return $this->fieldSearchable;
    }

    public function model()
    {
        return ConsultationUserTerm::class;
    }

    public function createUserTerm(ConsultationUserPivot $consultationUserPivot, array $data): ConsultationUserTerm
    {
        return $consultationUserPivot->userTerms()->create($data);
    }

    public function updateUserTermByExecutedAt(ConsultationUserPivot $consultationUserPivot, string $executedAt, array $data): ConsultationUserTerm
    {
        /** @var ConsultationUserTerm $userTerm */
        $userTerm = $consultationUserPivot->userTerms()->where('executed_at', '=', $executedAt)->firstOrFail();

        $userTerm->update($data);

        return $userTerm;
    }

    public function updateByConsultationUserIdAndExecutedAt(int $consultationUserId, string $executedAt, array $data): ConsultationUserTerm
    {
        /** @var ConsultationUserTerm $model */
        $model = $this->model->newQuery()
            ->where('consultation_user_id', '=', $consultationUserId)
            ->where('executed_at', '=', $executedAt)
            ->firstOrFail();

        $model->fill($data);
        $model->save();

        return $model;
    }

    public function allQueryBuilder(?FilterConsultationTermsListDto $filterConsultationTermsListDto = null): Collection
    {
        $query = $this->model->newQuery();

        if ($filterConsultationTermsListDto) {
            $criteria = $filterConsultationTermsListDto->getCriteria();
            if ($criteria) {
                $query = $this->applyCriteria($query, $criteria);
            }
        }

        return $this->applyPagination($query)->get();
    }

    /**
     * @return Collection<int, Model>
     */
    public function getBusyTerms(int $consultationId, ?string $date = null): Collection
    {
        $query = $this->model->newQuery();
        $query->whereHas('consultationUser', fn($query) => $query->where('consultation_id', '=', $consultationId));

        $query->whereNotNull('executed_at');

        if ($date) {
            $query->where([
                'executed_at' => $date
            ]);
        }
        $query->whereIn('executed_status', [ConsultationTermStatusEnum::APPROVED, ConsultationTermStatusEnum::REPORTED]);
        return $query->get();
    }

    public function getAllUserTermsByConsultationIdAndExecutedAt(int $consultationId, string $executedAt): Collection
    {
        return $this->model->newQuery()
            ->whereHas('consultationUser', fn($query) => $query->where('consultation_id', '=', $consultationId))
            ->where('executed_at', '=', $executedAt)
            ->get();
    }

    public function getUserTermByUserIdAndExecutedAt(int $userId, string $executedAt): ConsultationUserTerm
    {
        /** @var ConsultationUserTerm $model */
        $model = $this->model->newQuery()
            ->whereHas('consultationUser', fn (Builder $query) => $query->where('user_id', '=', $userId))
            ->where('executed_at', '=', $executedAt)
            ->firstOrFail();
        return $model;
    }

    public function updateModels(Collection $models, array $data): void
    {
        $this->model->newQuery()->whereIn('id', $models->pluck('id'))->update($data);
    }

    public function getByCurrentUserTutor(): Collection
    {
        $result = collect();
        $terms = $this->model->newQuery()
            ->whereHas('consultationUser', fn (Builder $query) => $query
                ->whereHas('consultation', fn (Builder $query) => $query
                    ->whereAuthorId(auth()->user()->getKey())
                    ->orWhereHas('teachers', fn (Builder $query) => $query->where('users.id', '=', auth()->user()->getKey()))
                )
            )
            ->get();

        /** @var ConsultationUserTerm $term */
        foreach ($terms as $term) {
            /** @var ConsultationUserTermResourceDto|null $userTerm */
            // @phpstan-ignore-next-line
            $userTerm = $result->first(fn (ConsultationUserTermResourceDto $dto) => $dto->consultation_id === $term->consultationUser->consultation_id && $term->executed_at === $dto->executed_at);

            $user = $term->consultationUser->user->toArray();
            $user['categories'] = $term->consultationUser->user->categories->toArray();
            $user['executed_status'] = $term->executed_status;
            if ($userTerm) {
                // @phpstan-ignore-next-line
                $userTerm->executed_status = $term->executed_status === ConsultationTermStatusEnum::APPROVED ? $term->executed_status : $userTerm->executed_status;
                $userTerm->users->push(new ConsultationUserResourceDto($user));
            } else {
                $result->push(new ConsultationUserTermResourceDto(
                    $term->consultation_user_id,
                    $term->consultationUser->consultation_id,
                    $term->executed_at,
                    $term->executed_status,
                    $term->consultationUser->consultation->getDuration(),
                    $term->consultationUser->consultation->author,
                    $term->finished_at,
                    collect([new ConsultationUserResourceDto($user)]),
                ));
            }
        }

        return $result;
    }

    public function updateModel(ConsultationUserTerm $userTerm, array $data): ConsultationUserTerm
    {
        $userTerm->fill($data);
        $userTerm->save();
        return $userTerm;
    }
}