Ajout des notification + page employé (#6)
Some checks failed
Auto Tag Develop / tag (push) Has been cancelled

| Numéro du ticket | Titre du ticket |
|------------------|-----------------|
|                  |                 |

## Description de la PR

## Modification du .env

## Check list

- [ ] Pas de régression
- [ ] TU/TI/TF rédigée
- [ ] TU/TI/TF OK
- [ ] CHANGELOG modifié

Reviewed-on: #6
Co-authored-by: tristan <tristan@yuno.malio.fr>
Co-committed-by: tristan <tristan@yuno.malio.fr>
This commit was merged in pull request #6.
This commit is contained in:
2026-03-10 12:35:17 +00:00
committed by Autin
parent ae42c70d50
commit f493ea237b
126 changed files with 9215 additions and 935 deletions

View File

@@ -99,4 +99,29 @@ final class AbsenceRepository extends ServiceEntityRepository implements Absence
// @var list<Absence> $absences
return $qb->getQuery()->getResult();
}
/**
* @return list<Absence>
*/
public function findByEmployeeAndOverlappingDateRange(Employee $employee, DateTimeInterface $from, DateTimeInterface $to): array
{
$fromDate = DateTimeImmutable::createFromInterface($from);
$toDate = DateTimeImmutable::createFromInterface($to);
$qb = $this->createQueryBuilder('a')
->leftJoin('a.employee', 'e')
->leftJoin('a.type', 't')
->addSelect('e', 't')
->andWhere('a.employee = :employee')
->andWhere('a.startDate <= :to')
->andWhere('a.endDate >= :from')
->setParameter('employee', $employee)
->setParameter('from', $fromDate)
->setParameter('to', $toDate)
->orderBy('a.startDate', 'ASC')
;
// @var list<Absence> $absences
return $qb->getQuery()->getResult();
}
}

View File

@@ -0,0 +1,14 @@
<?php
declare(strict_types=1);
namespace App\Repository\Contract;
use App\Entity\Employee;
use App\Entity\EmployeeContractPeriod;
use DateTimeImmutable;
interface EmployeeContractPeriodReadRepositoryInterface
{
public function findOneCoveringDate(Employee $employee, DateTimeImmutable $date): ?EmployeeContractPeriod;
}

View File

@@ -6,6 +6,7 @@ namespace App\Repository;
use App\Entity\Employee;
use App\Entity\EmployeeContractPeriod;
use App\Repository\Contract\EmployeeContractPeriodReadRepositoryInterface;
use DateTimeImmutable;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\Persistence\ManagerRegistry;
@@ -13,7 +14,7 @@ use Doctrine\Persistence\ManagerRegistry;
/**
* @extends ServiceEntityRepository<EmployeeContractPeriod>
*/
final class EmployeeContractPeriodRepository extends ServiceEntityRepository
final class EmployeeContractPeriodRepository extends ServiceEntityRepository implements EmployeeContractPeriodReadRepositoryInterface
{
public function __construct(ManagerRegistry $registry)
{
@@ -72,4 +73,56 @@ final class EmployeeContractPeriodRepository extends ServiceEntityRepository
->execute()
;
}
public function hasPaidLeaveSettledClosureBetween(
Employee $employee,
DateTimeImmutable $from,
DateTimeImmutable $to
): bool {
$count = $this->createQueryBuilder('p')
->select('COUNT(p.id)')
->andWhere('p.employee = :employee')
->andWhere('p.paidLeaveSettled = :paidLeaveSettled')
->andWhere('p.endDate IS NOT NULL')
->andWhere('p.endDate >= :from')
->andWhere('p.endDate <= :to')
->setParameter('employee', $employee)
->setParameter('paidLeaveSettled', true)
->setParameter('from', $from)
->setParameter('to', $to)
->getQuery()
->getSingleScalarResult()
;
return (int) $count > 0;
}
public function findLatestPaidLeaveSettledClosureDateBetween(
Employee $employee,
DateTimeImmutable $from,
DateTimeImmutable $to
): ?DateTimeImmutable {
$result = $this->createQueryBuilder('p')
->select('p.endDate AS endDate')
->andWhere('p.employee = :employee')
->andWhere('p.paidLeaveSettled = :paidLeaveSettled')
->andWhere('p.endDate IS NOT NULL')
->andWhere('p.endDate >= :from')
->andWhere('p.endDate <= :to')
->setParameter('employee', $employee)
->setParameter('paidLeaveSettled', true)
->setParameter('from', $from)
->setParameter('to', $to)
->orderBy('p.endDate', 'DESC')
->setMaxResults(1)
->getQuery()
->getOneOrNullResult()
;
if (!is_array($result) || !isset($result['endDate']) || !$result['endDate'] instanceof DateTimeImmutable) {
return null;
}
return $result['endDate'];
}
}

View File

@@ -0,0 +1,59 @@
<?php
declare(strict_types=1);
namespace App\Repository;
use App\Entity\Employee;
use App\Entity\EmployeeLeaveBalance;
use App\Enum\LeaveRuleCode;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\Persistence\ManagerRegistry;
/**
* @extends ServiceEntityRepository<EmployeeLeaveBalance>
*/
final class EmployeeLeaveBalanceRepository extends ServiceEntityRepository
{
public function __construct(ManagerRegistry $registry)
{
parent::__construct($registry, EmployeeLeaveBalance::class);
}
public function findOneByEmployeeRuleAndYear(
Employee $employee,
LeaveRuleCode|string $ruleCode,
int $year
): ?EmployeeLeaveBalance {
$ruleCodeValue = $ruleCode instanceof LeaveRuleCode ? $ruleCode->value : $ruleCode;
return $this->createQueryBuilder('b')
->andWhere('b.employee = :employee')
->andWhere('b.ruleCode = :ruleCode')
->andWhere('b.year = :year')
->setParameter('employee', $employee)
->setParameter('ruleCode', $ruleCodeValue)
->setParameter('year', $year)
->setMaxResults(1)
->getQuery()
->getOneOrNullResult()
;
}
public function findEarliestYearForEmployee(Employee $employee): ?int
{
$result = $this->createQueryBuilder('b')
->select('MIN(b.year) AS year')
->andWhere('b.employee = :employee')
->setParameter('employee', $employee)
->getQuery()
->getOneOrNullResult()
;
if (!is_array($result) || !array_key_exists('year', $result) || null === $result['year']) {
return null;
}
return (int) $result['year'];
}
}

View File

@@ -0,0 +1,34 @@
<?php
declare(strict_types=1);
namespace App\Repository;
use App\Entity\Employee;
use App\Entity\EmployeeRttBalance;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\Persistence\ManagerRegistry;
/**
* @extends ServiceEntityRepository<EmployeeRttBalance>
*/
final class EmployeeRttBalanceRepository extends ServiceEntityRepository
{
public function __construct(ManagerRegistry $registry)
{
parent::__construct($registry, EmployeeRttBalance::class);
}
public function findOneByEmployeeAndYear(Employee $employee, int $year): ?EmployeeRttBalance
{
return $this->createQueryBuilder('b')
->andWhere('b.employee = :employee')
->andWhere('b.year = :year')
->setParameter('employee', $employee)
->setParameter('year', $year)
->setMaxResults(1)
->getQuery()
->getOneOrNullResult()
;
}
}

View File

@@ -0,0 +1,47 @@
<?php
declare(strict_types=1);
namespace App\Repository;
use App\Entity\Employee;
use App\Entity\EmployeeRttPayment;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\Persistence\ManagerRegistry;
/**
* @extends ServiceEntityRepository<EmployeeRttPayment>
*/
final class EmployeeRttPaymentRepository extends ServiceEntityRepository
{
public function __construct(ManagerRegistry $registry)
{
parent::__construct($registry, EmployeeRttPayment::class);
}
public function findOneByEmployeeYearMonthRate(Employee $employee, int $year, int $month, string $rate): ?EmployeeRttPayment
{
return $this->findOneBy([
'employee' => $employee,
'year' => $year,
'month' => $month,
'rate' => $rate,
]);
}
/**
* @return EmployeeRttPayment[]
*/
public function findByEmployeeAndYear(Employee $employee, int $year): array
{
return $this->createQueryBuilder('p')
->andWhere('p.employee = :employee')
->andWhere('p.year = :year')
->setParameter('employee', $employee)
->setParameter('year', $year)
->addOrderBy('p.month', 'ASC')
->getQuery()
->getResult()
;
}
}

View File

@@ -0,0 +1,87 @@
<?php
declare(strict_types=1);
namespace App\Repository;
use App\Entity\Notification;
use App\Entity\User;
use DateTimeImmutable;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\Persistence\ManagerRegistry;
/**
* @extends ServiceEntityRepository<Notification>
*/
final class NotificationRepository extends ServiceEntityRepository
{
public function __construct(ManagerRegistry $registry)
{
parent::__construct($registry, Notification::class);
}
/**
* @return list<Notification>
*/
public function findUnreadByRecipient(User $recipient): array
{
return $this->createQueryBuilder('n')
->andWhere('n.recipient = :recipient')
->andWhere('n.isRead = :isRead')
->setParameter('recipient', $recipient)
->setParameter('isRead', false)
->orderBy('n.createdAt', 'DESC')
->setMaxResults(50)
->getQuery()
->getResult()
;
}
/**
* @return list<Notification>
*/
public function findTodayByRecipient(User $recipient): array
{
$todayStart = new DateTimeImmutable('today 00:00:00');
return $this->createQueryBuilder('n')
->andWhere('n.recipient = :recipient')
->andWhere('n.createdAt >= :todayStart')
->setParameter('recipient', $recipient)
->setParameter('todayStart', $todayStart)
->orderBy('n.createdAt', 'DESC')
->getQuery()
->getResult()
;
}
/**
* @return list<Notification>
*/
public function findLatestByRecipient(User $recipient, int $limit = 10): array
{
return $this->createQueryBuilder('n')
->andWhere('n.recipient = :recipient')
->setParameter('recipient', $recipient)
->orderBy('n.createdAt', 'DESC')
->setMaxResults($limit)
->getQuery()
->getResult()
;
}
public function markAllReadByRecipient(User $recipient): int
{
return $this->createQueryBuilder('n')
->update()
->set('n.isRead', ':isRead')
->andWhere('n.recipient = :recipient')
->andWhere('n.isRead = :current')
->setParameter('isRead', true)
->setParameter('current', false)
->setParameter('recipient', $recipient)
->getQuery()
->execute()
;
}
}

View File

@@ -0,0 +1,38 @@
<?php
declare(strict_types=1);
namespace App\Repository;
use App\Entity\User;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\Persistence\ManagerRegistry;
/**
* @extends ServiceEntityRepository<User>
*/
final class UserRepository extends ServiceEntityRepository
{
public function __construct(ManagerRegistry $registry)
{
parent::__construct($registry, User::class);
}
/**
* @return list<User>
*/
public function findAllAdmins(): array
{
/** @var list<User> $users */
$users = $this->createQueryBuilder('u')
->orderBy('u.id', 'ASC')
->getQuery()
->getResult()
;
return array_values(array_filter(
$users,
static fn (User $user): bool => in_array('ROLE_ADMIN', $user->getRoles(), true)
));
}
}

View File

@@ -137,4 +137,23 @@ final class WorkHourRepository extends ServiceEntityRepository implements WorkHo
// @var null|WorkHour $workHour
return $qb->getQuery()->getOneOrNullResult();
}
public function hasPendingSiteValidationForSiteAndDate(int $siteId, DateTimeInterface $date): bool
{
$workDate = DateTimeImmutable::createFromInterface($date);
$qb = $this->createQueryBuilder('w')
->select('COUNT(w.id)')
->leftJoin('w.employee', 'e')
->leftJoin('e.site', 's')
->andWhere('s.id = :siteId')
->andWhere('w.workDate = :workDate')
->andWhere('w.isSiteValid = :isSiteValid')
->setParameter('siteId', $siteId)
->setParameter('workDate', $workDate)
->setParameter('isSiteValid', false)
;
return ((int) $qb->getQuery()->getSingleScalarResult()) > 0;
}
}