feat: import work hours from SaaS and exchange signed time sheet
This commit is contained in:
1 parent
7cf39850e6
commit
1a7c272414
73 files changed
+10488
-72
No files matched your search
@@ -0,0 +1,134 @@
|
||||
<?php
|
||||
|
||||
namespace App\Repository;
|
||||
|
||||
use App\Entity\Teamer;
|
||||
use App\Entity\TeamerWorkMonth;
|
||||
use App\Enum\WorkMonthStatus;
|
||||
use App\Model\WorkMonthFilterDto;
|
||||
use App\Repository\Traits\QueryHelperTrait;
|
||||
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
|
||||
use Doctrine\ORM\Query;
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
use Doctrine\Persistence\ManagerRegistry;
|
||||
|
||||
/**
|
||||
* @extends ServiceEntityRepository<TeamerWorkMonth>
|
||||
*
|
||||
* @method TeamerWorkMonth|null find($id, $lockMode = null, $lockVersion = null)
|
||||
* @method TeamerWorkMonth|null findOneBy(array $criteria, array $orderBy = null)
|
||||
* @method TeamerWorkMonth[] findAll()
|
||||
* @method TeamerWorkMonth[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
|
||||
*/
|
||||
class TeamerWorkMonthRepository extends ServiceEntityRepository
|
||||
{
|
||||
use QueryHelperTrait;
|
||||
|
||||
public function __construct(ManagerRegistry $registry)
|
||||
{
|
||||
parent::__construct($registry, TeamerWorkMonth::class);
|
||||
}
|
||||
|
||||
public function findOneForTeamerAndMonth(Teamer $teamer, int $year, int $month): ?TeamerWorkMonth
|
||||
{
|
||||
return $this->findOneBy(['teamer' => $teamer, 'year' => $year, 'month' => $month]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return TeamerWorkMonth[]
|
||||
*/
|
||||
public function findForTeamer(Teamer $teamer): array
|
||||
{
|
||||
return $this->findBy(
|
||||
['teamer' => $teamer],
|
||||
['year' => \SortDirection::Descending, 'month' => \SortDirection::Descending],
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* The admin list.
|
||||
*
|
||||
* Deliberately over TeamerWorkMonth rather than over Upload: UploadRepository's list
|
||||
* queries inner-join a disposition, which structurally excludes every document hanging
|
||||
* off anything else, and it is the month that carries the status anyway.
|
||||
*/
|
||||
public function getListQuery(WorkMonthFilterDto $filterDto): Query
|
||||
{
|
||||
$qb = $this->createQueryBuilder('work_month');
|
||||
|
||||
$qb
|
||||
->select('work_month', 'teamer')
|
||||
->innerJoin('work_month.teamer', 'teamer')
|
||||
;
|
||||
|
||||
$this->applyFilterSettings($filterDto, $qb);
|
||||
|
||||
return $qb
|
||||
->addOrderBy('work_month.year', \SortDirection::Descending)
|
||||
->addOrderBy('work_month.month', \SortDirection::Descending)
|
||||
->addOrderBy('teamer.lastName', \SortDirection::Ascending)
|
||||
->getQuery()
|
||||
;
|
||||
}
|
||||
|
||||
/**
|
||||
* Months still waiting for a signed copy, for the reminder.
|
||||
*
|
||||
* @return TeamerWorkMonth[]
|
||||
*/
|
||||
public function findAwaitingDocument(\DateTimeImmutable $importedBefore): array
|
||||
{
|
||||
return $this
|
||||
->createQueryBuilder('work_month')
|
||||
->select('work_month', 'teamer')
|
||||
->innerJoin('work_month.teamer', 'teamer')
|
||||
->andWhere('work_month.status IN (:awaiting)')
|
||||
->andWhere('work_month.syncedAt <= :importedBefore')
|
||||
->andWhere('teamer.deletedAt IS NULL')
|
||||
->setParameter('awaiting', [WorkMonthStatus::OPEN, WorkMonthStatus::REJECTED])
|
||||
->setParameter('importedBefore', $importedBefore)
|
||||
->addOrderBy('teamer.lastName', \SortDirection::Ascending)
|
||||
->getQuery()
|
||||
->getResult()
|
||||
;
|
||||
}
|
||||
|
||||
private function applyFilterSettings(WorkMonthFilterDto $filterDto, QueryBuilder $qb): void
|
||||
{
|
||||
if (null !== $filterDto->getTeamerName()) {
|
||||
$qb
|
||||
->andWhere($qb->expr()->orX(
|
||||
$qb->expr()->like('teamer.firstName', ':teamerName'),
|
||||
$qb->expr()->like('teamer.lastName', ':teamerName')
|
||||
))
|
||||
->setParameter('teamerName', '%'.$this->escapeLikeWildcards($filterDto->getTeamerName()).'%')
|
||||
;
|
||||
}
|
||||
|
||||
if (null !== $period = $filterDto->getPeriod()) {
|
||||
$qb
|
||||
->andWhere('work_month.year = :year')
|
||||
->andWhere('work_month.month = :month')
|
||||
->setParameter('year', (int) $period->format('Y'))
|
||||
->setParameter('month', (int) $period->format('n'))
|
||||
;
|
||||
}
|
||||
|
||||
if (0 < count($filterDto->getStatuses())) {
|
||||
$qb
|
||||
->andWhere('work_month.status IN (:statuses)')
|
||||
->setParameter('statuses', $filterDto->getStatuses())
|
||||
;
|
||||
} elseif (!$filterDto->isIncludeApproved()) {
|
||||
// Only a default, so an explicit status choice still wins.
|
||||
$qb
|
||||
->andWhere('work_month.status != :approved')
|
||||
->setParameter('approved', WorkMonthStatus::APPROVED)
|
||||
;
|
||||
}
|
||||
|
||||
if ($filterDto->isIncludeMismatchedOnly()) {
|
||||
$qb->andWhere('work_month.mismatchDetectedAt IS NOT NULL');
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user