Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b5e7395760 | ||
| 380c72c242 | |||
|
|
107417a571 | ||
| 5ff7e356be |
@@ -1,2 +1,2 @@
|
|||||||
parameters:
|
parameters:
|
||||||
app.version: '0.1.14'
|
app.version: '0.1.16'
|
||||||
|
|||||||
@@ -427,8 +427,11 @@ export const useHoursPage = () => {
|
|||||||
|
|
||||||
const getPresenceDayValue = (employeeId: number) => {
|
const getPresenceDayValue = (employeeId: number) => {
|
||||||
const row = rows.value[employeeId]
|
const row = rows.value[employeeId]
|
||||||
const basePresence = (row?.isPresentMorning ? 0.5 : 0) + (row?.isPresentAfternoon ? 0.5 : 0)
|
const dayRow = dayContextByEmployeeId.value.get(employeeId)
|
||||||
const creditedPresence = dayContextByEmployeeId.value.get(employeeId)?.creditedPresenceUnits ?? 0
|
const absentMorning = dayRow?.absentMorning ?? false
|
||||||
|
const absentAfternoon = dayRow?.absentAfternoon ?? false
|
||||||
|
const basePresence = ((row?.isPresentMorning && !absentMorning) ? 0.5 : 0) + ((row?.isPresentAfternoon && !absentAfternoon) ? 0.5 : 0)
|
||||||
|
const creditedPresence = dayRow?.creditedPresenceUnits ?? 0
|
||||||
const total = Math.min(1, basePresence + creditedPresence)
|
const total = Math.min(1, basePresence + creditedPresence)
|
||||||
return Number.isInteger(total) ? String(total) : total.toFixed(1)
|
return Number.isInteger(total) ? String(total) : total.toFixed(1)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -60,11 +60,6 @@ final readonly class WorkedHoursCreditPolicy
|
|||||||
bool $absentMorning,
|
bool $absentMorning,
|
||||||
bool $absentAfternoon
|
bool $absentAfternoon
|
||||||
): float {
|
): float {
|
||||||
$type = $absence->getType();
|
|
||||||
if (!$type?->getCountAsWorkedHours()) {
|
|
||||||
return 0.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
$employee = $absence->getEmployee();
|
$employee = $absence->getEmployee();
|
||||||
if (null === $employee) {
|
if (null === $employee) {
|
||||||
return 0.0;
|
return 0.0;
|
||||||
@@ -74,9 +69,14 @@ final readonly class WorkedHoursCreditPolicy
|
|||||||
return 0.0;
|
return 0.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
$halfUnits = ($absentMorning ? 1 : 0) + ($absentAfternoon ? 1 : 0);
|
// Règle forfait:
|
||||||
|
// - demi-journée d'absence => 0.5 travaillé
|
||||||
|
// - journée complète d'absence => 0 travaillé
|
||||||
|
if ($absentMorning xor $absentAfternoon) {
|
||||||
|
return 0.5;
|
||||||
|
}
|
||||||
|
|
||||||
return $halfUnits * 0.5;
|
return 0.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function resolveContractDayMinutes(?int $weeklyHours, int $isoWeekDay): int
|
public function resolveContractDayMinutes(?int $weeklyHours, int $isoWeekDay): int
|
||||||
|
|||||||
@@ -125,6 +125,14 @@ final readonly class WorkHourBulkUpsertProcessor implements ProcessorInterface
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Si aucune donnée n'a changé, on ne touche pas la ligne:
|
||||||
|
// cela évite de perdre les validations existantes (site/RH) sur un simple enregistrement.
|
||||||
|
if (null !== $existing && $this->isSameAsExisting($existing, $normalized)) {
|
||||||
|
++$result->processed;
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if ($this->isEntryEmpty($normalized)) {
|
if ($this->isEntryEmpty($normalized)) {
|
||||||
// Convention choisie: une ligne vide supprime l'enregistrement existant.
|
// Convention choisie: une ligne vide supprime l'enregistrement existant.
|
||||||
if ($existing) {
|
if ($existing) {
|
||||||
|
|||||||
@@ -135,6 +135,8 @@ final readonly class WorkHourWeeklySummaryProvider implements ProviderInterface
|
|||||||
$creditedByEmployeeDate = [];
|
$creditedByEmployeeDate = [];
|
||||||
$creditedPresenceByEmployeeDate = [];
|
$creditedPresenceByEmployeeDate = [];
|
||||||
$absenceByEmployeeDate = [];
|
$absenceByEmployeeDate = [];
|
||||||
|
$absentMorningByEmployeeDate = [];
|
||||||
|
$absentAfternoonByEmployeeDate = [];
|
||||||
$absenceLabelByEmployeeDate = [];
|
$absenceLabelByEmployeeDate = [];
|
||||||
$absenceColorByEmployeeDate = [];
|
$absenceColorByEmployeeDate = [];
|
||||||
foreach ($absences as $absence) {
|
foreach ($absences as $absence) {
|
||||||
@@ -153,7 +155,9 @@ final readonly class WorkHourWeeklySummaryProvider implements ProviderInterface
|
|||||||
|
|
||||||
[$absentMorning, $absentAfternoon] = $this->absenceSegmentsResolver->resolveForDate($absence, $date);
|
[$absentMorning, $absentAfternoon] = $this->absenceSegmentsResolver->resolveForDate($absence, $date);
|
||||||
if ($absentMorning || $absentAfternoon) {
|
if ($absentMorning || $absentAfternoon) {
|
||||||
$absenceByEmployeeDate[$employeeId][$date] = true;
|
$absenceByEmployeeDate[$employeeId][$date] = true;
|
||||||
|
$absentMorningByEmployeeDate[$employeeId][$date] = ($absentMorningByEmployeeDate[$employeeId][$date] ?? false) || $absentMorning;
|
||||||
|
$absentAfternoonByEmployeeDate[$employeeId][$date] = ($absentAfternoonByEmployeeDate[$employeeId][$date] ?? false) || $absentAfternoon;
|
||||||
if (!isset($absenceLabelByEmployeeDate[$employeeId][$date])) {
|
if (!isset($absenceLabelByEmployeeDate[$employeeId][$date])) {
|
||||||
$absenceLabelByEmployeeDate[$employeeId][$date] = $absence->getType()?->getLabel();
|
$absenceLabelByEmployeeDate[$employeeId][$date] = $absence->getType()?->getLabel();
|
||||||
}
|
}
|
||||||
@@ -202,8 +206,10 @@ final readonly class WorkHourWeeklySummaryProvider implements ProviderInterface
|
|||||||
$metrics->addCreditedMinutes($creditedMinutes);
|
$metrics->addCreditedMinutes($creditedMinutes);
|
||||||
$present = null;
|
$present = null;
|
||||||
if ($isPresenceTracking) {
|
if ($isPresenceTracking) {
|
||||||
$morning = ($entry['isPresentMorning'] ?? false) ? 0.5 : 0.0;
|
$absentMorning = $absentMorningByEmployeeDate[$employeeId][$date] ?? false;
|
||||||
$afternoon = ($entry['isPresentAfternoon'] ?? false) ? 0.5 : 0.0;
|
$absentAfternoon = $absentAfternoonByEmployeeDate[$employeeId][$date] ?? false;
|
||||||
|
$morning = (($entry['isPresentMorning'] ?? false) && !$absentMorning) ? 0.5 : 0.0;
|
||||||
|
$afternoon = (($entry['isPresentAfternoon'] ?? false) && !$absentAfternoon) ? 0.5 : 0.0;
|
||||||
$creditedPresence = $creditedPresenceByEmployeeDate[$employeeId][$date] ?? 0.0;
|
$creditedPresence = $creditedPresenceByEmployeeDate[$employeeId][$date] ?? 0.0;
|
||||||
$present = min(1.0, $morning + $afternoon + $creditedPresence);
|
$present = min(1.0, $morning + $afternoon + $creditedPresence);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -135,7 +135,7 @@ final class WorkHourWeeklySummaryProviderTest extends TestCase
|
|||||||
self::assertSame(210, $result->rows[0]->weeklyOvertime50Minutes);
|
self::assertSame(210, $result->rows[0]->weeklyOvertime50Minutes);
|
||||||
self::assertSame(1230, $result->rows[0]->weeklyRecoveryMinutes);
|
self::assertSame(1230, $result->rows[0]->weeklyRecoveryMinutes);
|
||||||
|
|
||||||
self::assertSame(1.0, $result->rows[1]->weeklyPresenceCount);
|
self::assertSame(0.0, $result->rows[1]->weeklyPresenceCount);
|
||||||
self::assertTrue($result->rows[1]->daily[0]->hasAbsence);
|
self::assertTrue($result->rows[1]->daily[0]->hasAbsence);
|
||||||
self::assertSame('Congé', $result->rows[1]->daily[0]->absenceLabel);
|
self::assertSame('Congé', $result->rows[1]->daily[0]->absenceLabel);
|
||||||
self::assertSame('#000', $result->rows[1]->daily[0]->absenceColor);
|
self::assertSame('#000', $result->rows[1]->daily[0]->absenceColor);
|
||||||
|
|||||||
Reference in New Issue
Block a user