feat : ajout de log pour les cron

This commit is contained in:
2026-03-10 13:34:00 +01:00
parent 53255dba43
commit 84bffc645a
6 changed files with 310 additions and 242 deletions

View File

@@ -1,14 +1,19 @@
monolog: monolog:
channels: [deprecation] channels: [deprecation, cron]
when@dev: when@dev:
monolog: monolog:
handlers: handlers:
cron:
type: stream
path: "%kernel.logs_dir%/cron.log"
level: info
channels: [cron]
main: main:
type: stream type: stream
path: "%kernel.logs_dir%/%kernel.environment%.log" path: "%kernel.logs_dir%/%kernel.environment%.log"
level: debug level: debug
channels: ["!event"] channels: ["!event", "!cron"]
console: console:
type: console type: console
process_psr_3_messages: false process_psr_3_messages: false
@@ -17,11 +22,16 @@ when@dev:
when@prod: when@prod:
monolog: monolog:
handlers: handlers:
cron:
type: stream
path: "%kernel.logs_dir%/cron.log"
level: info
channels: [cron]
main: main:
type: stream type: stream
path: "%kernel.logs_dir%/%kernel.environment%.log" path: "%kernel.logs_dir%/%kernel.environment%.log"
level: debug level: debug
channels: ["!deprecation"] channels: ["!deprecation", "!cron"]
deprecation: deprecation:
type: stream type: stream
channels: [deprecation] channels: [deprecation]

View File

@@ -168,11 +168,11 @@ employee_id;rule_code;year;opening_days;opening_saturdays;source_date;comment
Exemple cron (tous les jours a 02:10): Exemple cron (tous les jours a 02:10):
Dev Dev
```cron ```cron
10 2 * * * cd /var/www/html && php bin/console app:leave:rollover --no-interaction >> var/log/leave-rollover.log 2>&1 10 2 * * * cd /var/www/html && php bin/console app:leave:rollover --no-interaction 2>&1
``` ```
Prod Prod
```cron ```cron
10 2 * * * cd /var/www/sirh && php bin/console app:leave:rollover --no-interaction >> var/log/leave-rollover.log 2>&1 10 2 * * * cd /var/www/sirh && php bin/console app:leave:rollover --no-interaction 2>&1
``` ```
Explication de la ligne cron: Explication de la ligne cron:
- `10 2 * * *`: planification - `10 2 * * *`: planification

View File

@@ -133,11 +133,11 @@ Conversion rapide: `1260 minutes = 21h00 = 3.00 jours` (1 jour = 420 min = 7h)
Exemple cron (tous les jours a 02:15, juste apres le rollover conges): Exemple cron (tous les jours a 02:15, juste apres le rollover conges):
Dev Dev
```cron ```cron
15 2 * * * cd /var/www/html && php bin/console app:rtt:rollover --no-interaction >> var/log/rtt-rollover.log 2>&1 15 2 * * * cd /var/www/html && php bin/console app:rtt:rollover --no-interaction 2>&1
``` ```
Prod Prod
```cron ```cron
15 2 * * * cd /var/www/sirh && php bin/console app:rtt:rollover --no-interaction >> var/log/rtt-rollover.log 2>&1 10 2 * * * cd /var/www/sirh && php bin/console app:rtt:rollover --no-interaction 2>&1
``` ```
Explication de la ligne cron: Explication de la ligne cron:
- `15 2 * * *`: tous les jours a 02:15 - `15 2 * * *`: tous les jours a 02:15

View File

@@ -143,13 +143,22 @@
/> />
</div> </div>
<div class="pl-2 text-sm font-semibold text-neutral-700"> <div class="pl-2 text-sm font-semibold text-neutral-700">
<div v-if="isTimeTracking(employee)">{{ formatMinutes(getRowMetrics(employee.id).dayMinutes) }}</div> <div v-if="isTimeTracking(employee)">{{
formatMinutes(getRowMetrics(employee.id).dayMinutes)
}}
</div>
</div> </div>
<div class="text-sm font-semibold text-neutral-700"> <div class="text-sm font-semibold text-neutral-700">
<div v-if="isTimeTracking(employee)">{{ formatMinutes(getRowMetrics(employee.id).nightMinutes) }}</div> <div v-if="isTimeTracking(employee)">{{
formatMinutes(getRowMetrics(employee.id).nightMinutes)
}}
</div>
</div> </div>
<div class="text-sm font-semibold text-neutral-700"> <div class="text-sm font-semibold text-neutral-700">
<div v-if="isTimeTracking(employee)">{{ formatMinutes(getRowMetrics(employee.id).totalMinutes) }}</div> <div v-if="isTimeTracking(employee)">{{
formatMinutes(getRowMetrics(employee.id).totalMinutes)
}}
</div>
<div v-else>{{ getPresenceDayValue(employee.id) }}</div> <div v-else>{{ getPresenceDayValue(employee.id) }}</div>
</div> </div>
<div v-if="isAdmin" class="text-right"> <div v-if="isAdmin" class="text-right">

View File

@@ -13,12 +13,15 @@ use App\Repository\EmployeeRepository;
use App\Service\Leave\LeaveBalanceComputationService; use App\Service\Leave\LeaveBalanceComputationService;
use DateTimeImmutable; use DateTimeImmutable;
use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\EntityManagerInterface;
use Psr\Log\LoggerInterface;
use Symfony\Component\Console\Attribute\AsCommand; use Symfony\Component\Console\Attribute\AsCommand;
use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle; use Symfony\Component\Console\Style\SymfonyStyle;
use Symfony\Component\DependencyInjection\Attribute\Autowire;
use Throwable;
#[AsCommand( #[AsCommand(
name: 'app:leave:rollover', name: 'app:leave:rollover',
@@ -31,6 +34,8 @@ final class LeaveRolloverCommand extends Command
private readonly EmployeeLeaveBalanceRepository $leaveBalanceRepository, private readonly EmployeeLeaveBalanceRepository $leaveBalanceRepository,
private readonly LeaveBalanceComputationService $leaveBalanceComputationService, private readonly LeaveBalanceComputationService $leaveBalanceComputationService,
private readonly EntityManagerInterface $entityManager, private readonly EntityManagerInterface $entityManager,
#[Autowire(service: 'monolog.logger.cron')]
private readonly LoggerInterface $logger,
) { ) {
parent::__construct(); parent::__construct();
} }
@@ -51,8 +56,12 @@ final class LeaveRolloverCommand extends Command
$today = new DateTimeImmutable('today'); $today = new DateTimeImmutable('today');
$force = (bool) $input->getOption('force'); $force = (bool) $input->getOption('force');
$this->logger->info('app:leave:rollover started.', ['date' => $today->format('Y-m-d'), 'force' => $force]);
if (!$force && !$this->isBusinessRolloverDate($today)) { if (!$force && !$this->isBusinessRolloverDate($today)) {
$io->success('No rollover today: business date is neither 01/01 nor 01/06.'); $message = 'No rollover today: business date is neither 01/01 nor 01/06.';
$this->logger->info($message, ['date' => $today->format('Y-m-d')]);
$io->success($message);
return Command::SUCCESS; return Command::SUCCESS;
} }
@@ -67,6 +76,7 @@ final class LeaveRolloverCommand extends Command
$ruleCode = $this->resolveRuleCode($employee); $ruleCode = $this->resolveRuleCode($employee);
if (null === $ruleCode) { if (null === $ruleCode) {
$this->logger->info('Employee skipped: no eligible rule.', ['employeeId' => $employee->getId()]);
++$skipped; ++$skipped;
continue; continue;
@@ -80,12 +90,21 @@ final class LeaveRolloverCommand extends Command
$targetYear = $this->resolveTargetYear($ruleCode, $today); $targetYear = $this->resolveTargetYear($ruleCode, $today);
$existing = $this->leaveBalanceRepository->findOneByEmployeeRuleAndYear($employee, $ruleCode, $targetYear); $existing = $this->leaveBalanceRepository->findOneByEmployeeRuleAndYear($employee, $ruleCode, $targetYear);
if (null !== $existing) { if (null !== $existing) {
$this->logger->info('Employee skipped: balance already exists.', ['employeeId' => $employee->getId(), 'year' => $targetYear, 'rule' => $ruleCode->value]);
++$skipped; ++$skipped;
continue; continue;
} }
try {
[$carryDays, $carrySaturdays] = $this->resolveCarry($employee, $ruleCode, $targetYear); [$carryDays, $carrySaturdays] = $this->resolveCarry($employee, $ruleCode, $targetYear);
} catch (Throwable $e) {
$this->logger->error('Error computing carry for employee.', ['employeeId' => $employee->getId(), 'error' => $e->getMessage()]);
++$skipped;
continue;
}
$balance = new EmployeeLeaveBalance() $balance = new EmployeeLeaveBalance()
->setEmployee($employee) ->setEmployee($employee)
->setRuleCode($ruleCode) ->setRuleCode($ruleCode)
@@ -102,16 +121,22 @@ final class LeaveRolloverCommand extends Command
; ;
$this->entityManager->persist($balance); $this->entityManager->persist($balance);
$this->logger->info('Balance created.', ['employeeId' => $employee->getId(), 'year' => $targetYear, 'rule' => $ruleCode->value, 'carryDays' => $carryDays, 'carrySaturdays' => $carrySaturdays]);
++$created; ++$created;
} }
try {
$this->entityManager->flush(); $this->entityManager->flush();
} catch (Throwable $e) {
$this->logger->error('Error flushing leave balances.', ['error' => $e->getMessage()]);
$io->error('Leave rollover failed: '.$e->getMessage());
$io->success(sprintf( return Command::FAILURE;
'Leave rollover done: %d created, %d skipped.', }
$created,
$skipped $message = sprintf('Leave rollover done: %d created, %d skipped.', $created, $skipped);
)); $this->logger->info($message);
$io->success($message);
return Command::SUCCESS; return Command::SUCCESS;
} }

View File

@@ -13,12 +13,15 @@ use App\Repository\EmployeeRttBalanceRepository;
use App\Service\Rtt\RttRecoveryComputationService; use App\Service\Rtt\RttRecoveryComputationService;
use DateTimeImmutable; use DateTimeImmutable;
use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\EntityManagerInterface;
use Psr\Log\LoggerInterface;
use Symfony\Component\Console\Attribute\AsCommand; use Symfony\Component\Console\Attribute\AsCommand;
use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle; use Symfony\Component\Console\Style\SymfonyStyle;
use Symfony\Component\DependencyInjection\Attribute\Autowire;
use Throwable;
#[AsCommand( #[AsCommand(
name: 'app:rtt:rollover', name: 'app:rtt:rollover',
@@ -31,6 +34,8 @@ final class RttRolloverCommand extends Command
private readonly EmployeeRttBalanceRepository $rttBalanceRepository, private readonly EmployeeRttBalanceRepository $rttBalanceRepository,
private readonly RttRecoveryComputationService $rttRecoveryService, private readonly RttRecoveryComputationService $rttRecoveryService,
private readonly EntityManagerInterface $entityManager, private readonly EntityManagerInterface $entityManager,
#[Autowire(service: 'monolog.logger.cron')]
private readonly LoggerInterface $logger,
) { ) {
parent::__construct(); parent::__construct();
} }
@@ -51,8 +56,12 @@ final class RttRolloverCommand extends Command
$today = new DateTimeImmutable('today'); $today = new DateTimeImmutable('today');
$force = (bool) $input->getOption('force'); $force = (bool) $input->getOption('force');
$this->logger->info('app:rtt:rollover started.', ['date' => $today->format('Y-m-d'), 'force' => $force]);
if (!$force && '06-01' !== $today->format('m-d')) { if (!$force && '06-01' !== $today->format('m-d')) {
$io->success('No RTT rollover today: business date is not 01/06.'); $message = 'No RTT rollover today: business date is not 01/06.';
$this->logger->info($message, ['date' => $today->format('Y-m-d')]);
$io->success($message);
return Command::SUCCESS; return Command::SUCCESS;
} }
@@ -67,6 +76,7 @@ final class RttRolloverCommand extends Command
} }
if (!$this->isEligible($employee)) { if (!$this->isEligible($employee)) {
$this->logger->info('Employee skipped: not eligible.', ['employeeId' => $employee->getId()]);
++$skipped; ++$skipped;
continue; continue;
@@ -74,13 +84,21 @@ final class RttRolloverCommand extends Command
$existing = $this->rttBalanceRepository->findOneByEmployeeAndYear($employee, $targetYear); $existing = $this->rttBalanceRepository->findOneByEmployeeAndYear($employee, $targetYear);
if (null !== $existing) { if (null !== $existing) {
$this->logger->info('Employee skipped: balance already exists.', ['employeeId' => $employee->getId(), 'year' => $targetYear]);
++$skipped; ++$skipped;
continue; continue;
} }
try {
$previousYear = $targetYear - 1; $previousYear = $targetYear - 1;
$carryMinutes = $this->rttRecoveryService->computeTotalRecoveryForExercise($employee, $previousYear); $carryMinutes = $this->rttRecoveryService->computeTotalRecoveryForExercise($employee, $previousYear);
} catch (Throwable $e) {
$this->logger->error('Error computing carry for employee.', ['employeeId' => $employee->getId(), 'error' => $e->getMessage()]);
++$skipped;
continue;
}
$balance = new EmployeeRttBalance() $balance = new EmployeeRttBalance()
->setEmployee($employee) ->setEmployee($employee)
@@ -90,16 +108,22 @@ final class RttRolloverCommand extends Command
; ;
$this->entityManager->persist($balance); $this->entityManager->persist($balance);
$this->logger->info('Balance created.', ['employeeId' => $employee->getId(), 'year' => $targetYear, 'carryMinutes' => $carryMinutes]);
++$created; ++$created;
} }
try {
$this->entityManager->flush(); $this->entityManager->flush();
} catch (Throwable $e) {
$this->logger->error('Error flushing RTT balances.', ['error' => $e->getMessage()]);
$io->error('RTT rollover failed: '.$e->getMessage());
$io->success(sprintf( return Command::FAILURE;
'RTT rollover done: %d created, %d skipped.', }
$created,
$skipped $message = sprintf('RTT rollover done: %d created, %d skipped.', $created, $skipped);
)); $this->logger->info($message);
$io->success($message);
return Command::SUCCESS; return Command::SUCCESS;
} }