Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
443ed1e003 | ||
| cef364fcec |
@@ -1,2 +1,2 @@
|
|||||||
parameters:
|
parameters:
|
||||||
app.version: '0.1.41'
|
app.version: '0.1.42'
|
||||||
|
|||||||
@@ -40,6 +40,10 @@ Documents complementaires:
|
|||||||
|
|
||||||
## 3) Heures (vue jour)
|
## 3) Heures (vue jour)
|
||||||
|
|
||||||
|
- Visibilité des employés:
|
||||||
|
- vue jour: un employé sans contrat à la date sélectionnée est masqué
|
||||||
|
- vue semaine: un employé sans contrat sur aucun jour de la semaine est masqué
|
||||||
|
- même règle pour les heures classiques et les heures conducteurs
|
||||||
- Saisie par salarié et par date:
|
- Saisie par salarié et par date:
|
||||||
- matin / après-midi / soir
|
- matin / après-midi / soir
|
||||||
- pour `PRESENCE`: demi-journées matin/après-midi
|
- pour `PRESENCE`: demi-journées matin/après-midi
|
||||||
@@ -134,9 +138,11 @@ Documents complementaires:
|
|||||||
- `dayHoursMinutes`, `nightHoursMinutes` et `workshopHoursMinutes` (entiers, minutes) sur `WorkHour`
|
- `dayHoursMinutes`, `nightHoursMinutes` et `workshopHoursMinutes` (entiers, minutes) sur `WorkHour`
|
||||||
- `hasBreakfast`, `hasLunch`, `hasDinner`, `hasOvernight` (booleans) sur `WorkHour`
|
- `hasBreakfast`, `hasLunch`, `hasDinner`, `hasOvernight` (booleans) sur `WorkHour`
|
||||||
- les champs time classiques (morning/afternoon/evening) sont mis à null pour les chauffeurs
|
- les champs time classiques (morning/afternoon/evening) sont mis à null pour les chauffeurs
|
||||||
|
- Absences `countAsWorkedHours=true`: les minutes créditées sont ajoutées aux heures de jour (vue jour et vue semaine), même logique que les employés classiques
|
||||||
- Validation: même logique que les heures classiques (`isValid`, `isSiteValid`, bulk)
|
- Validation: même logique que les heures classiques (`isValid`, `isSiteValid`, bulk)
|
||||||
- Vue semaine:
|
- Vue semaine:
|
||||||
- jour/nuit/atelier par jour + indicateurs repas/dîner/nuitée
|
- jour/nuit/atelier par jour + indicateurs repas/dîner/nuitée
|
||||||
|
- panier de nuit (PN): affiché par jour si nightMinutes > dayMinutes, et total hebdo dans la colonne Jour/Nuit sem.
|
||||||
- totaux hebdo: jour, nuit, atelier, total, compteurs petit déj/déjeuner/dîner/nuitée
|
- totaux hebdo: jour, nuit, atelier, total, compteurs petit déj/déjeuner/dîner/nuitée
|
||||||
- pas de calcul d'heures supplémentaires pour les conducteurs
|
- pas de calcul d'heures supplémentaires pour les conducteurs
|
||||||
- Le flag `isDriver` est sur `EmployeeContractPeriod` (un employé peut changer de statut chauffeur selon la période)
|
- Le flag `isDriver` est sur `EmployeeContractPeriod` (un employé peut changer de statut chauffeur selon la période)
|
||||||
@@ -170,6 +176,11 @@ Tous les filtres checkbox sont cochés par défaut à l'ouverture du drawer.
|
|||||||
- Modification employé:
|
- Modification employé:
|
||||||
- uniquement prénom, nom, site
|
- uniquement prénom, nom, site
|
||||||
- pas de modification de contrat depuis ce drawer
|
- pas de modification de contrat depuis ce drawer
|
||||||
|
- Liste employés — filtre par statut de contrat:
|
||||||
|
- 3 options: "Avec contrat" (défaut), "Sans contrat", "Tous"
|
||||||
|
- "Avec contrat": employés ayant une période de contrat active à la date du jour
|
||||||
|
- "Sans contrat": employés sans période de contrat active
|
||||||
|
- "Tous": aucun filtrage sur le contrat
|
||||||
- Détail employé:
|
- Détail employé:
|
||||||
- onglet `Suivi contrat` avec affichage de l'historique des périodes de contrat
|
- onglet `Suivi contrat` avec affichage de l'historique des périodes de contrat
|
||||||
- chaque ligne expose: nature (`CDI`/`CDD`/`INTERIM`), contrat/temps de travail, date de début, date de fin (ou "En cours")
|
- chaque ligne expose: nature (`CDI`/`CDD`/`INTERIM`), contrat/temps de travail, date de début, date de fin (ou "En cours")
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
<span>+25%</span>
|
<span>+25%</span>
|
||||||
<span>+50%</span>
|
<span>+50%</span>
|
||||||
<span>Total <br>récup.</span>
|
<span>Total <br>récup.</span>
|
||||||
|
<span>Panier <br>nuit</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="border-x border-b border-primary-500 rounded-b-md">
|
<div class="border-x border-b border-primary-500 rounded-b-md">
|
||||||
@@ -68,6 +69,9 @@
|
|||||||
<div class="font-semibold">
|
<div class="font-semibold">
|
||||||
{{ row.trackingMode === 'PRESENCE' || isInterimContract(row.contractType) ? '-' : formatMinutes(row.weeklyRecoveryMinutes ?? 0) }}
|
{{ row.trackingMode === 'PRESENCE' || isInterimContract(row.contractType) ? '-' : formatMinutes(row.weeklyRecoveryMinutes ?? 0) }}
|
||||||
</div>
|
</div>
|
||||||
|
<div class="font-semibold">
|
||||||
|
{{ (row.weeklyNightBasketCount ?? 0) > 0 ? row.weeklyNightBasketCount : '-' }}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -107,13 +107,19 @@ export const useDriverHoursPage = () => {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const displayedEmployees = computed(() => {
|
||||||
|
return visibleEmployees.value.filter((employee) => hasContractAtSelectedDate(employee.id))
|
||||||
|
})
|
||||||
|
|
||||||
const visibleEmployeeIdSet = computed(() => new Set(visibleEmployees.value.map((employee) => employee.id)))
|
const visibleEmployeeIdSet = computed(() => new Set(visibleEmployees.value.map((employee) => employee.id)))
|
||||||
|
|
||||||
const filteredWeeklySummary = computed<WeeklyWorkHourSummary | null>(() => {
|
const filteredWeeklySummary = computed<WeeklyWorkHourSummary | null>(() => {
|
||||||
if (!weeklySummary.value) return null
|
if (!weeklySummary.value) return null
|
||||||
return {
|
return {
|
||||||
...weeklySummary.value,
|
...weeklySummary.value,
|
||||||
rows: weeklySummary.value.rows.filter((row) => visibleEmployeeIdSet.value.has(row.employeeId))
|
rows: weeklySummary.value.rows.filter((row) =>
|
||||||
|
visibleEmployeeIdSet.value.has(row.employeeId) && row.hasContractForWeek !== false
|
||||||
|
)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -362,7 +368,8 @@ export const useDriverHoursPage = () => {
|
|||||||
|
|
||||||
const getRowMetrics = (employeeId: number) => {
|
const getRowMetrics = (employeeId: number) => {
|
||||||
const row = rows.value[employeeId] ?? emptyRow()
|
const row = rows.value[employeeId] ?? emptyRow()
|
||||||
const dayMinutes = toMinutes(row.dayHours)
|
const credited = dayContextByEmployeeId.value.get(employeeId)?.creditedMinutes ?? 0
|
||||||
|
const dayMinutes = toMinutes(row.dayHours) + credited
|
||||||
const nightMinutes = toMinutes(row.nightHours)
|
const nightMinutes = toMinutes(row.nightHours)
|
||||||
const workshopMinutes = toMinutes(row.workshopHours)
|
const workshopMinutes = toMinutes(row.workshopHours)
|
||||||
const totalMinutes = dayMinutes + nightMinutes + workshopMinutes
|
const totalMinutes = dayMinutes + nightMinutes + workshopMinutes
|
||||||
@@ -917,6 +924,7 @@ export const useDriverHoursPage = () => {
|
|||||||
selectedSiteIds,
|
selectedSiteIds,
|
||||||
employees,
|
employees,
|
||||||
visibleEmployees,
|
visibleEmployees,
|
||||||
|
displayedEmployees,
|
||||||
rows,
|
rows,
|
||||||
absenceTypes,
|
absenceTypes,
|
||||||
absenceForm,
|
absenceForm,
|
||||||
|
|||||||
@@ -77,7 +77,7 @@ export const useHoursPage = () => {
|
|||||||
return `1.2fr 0.6fr repeat(6, 0.8fr) ${metricCol} ${metricCol} ${metricCol} ${validationCols}`
|
return `1.2fr 0.6fr repeat(6, 0.8fr) ${metricCol} ${metricCol} ${metricCol} ${validationCols}`
|
||||||
})
|
})
|
||||||
|
|
||||||
const weekGridCols = '1.6fr repeat(7, 1fr) repeat(6, 0.6fr)'
|
const weekGridCols = '1.6fr repeat(7, 1fr) repeat(6, 0.6fr) 0.3fr'
|
||||||
|
|
||||||
const sites = computed<Site[]>(() => {
|
const sites = computed<Site[]>(() => {
|
||||||
const siteMap = new Map<number, Site>()
|
const siteMap = new Map<number, Site>()
|
||||||
@@ -109,13 +109,19 @@ export const useHoursPage = () => {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const displayedEmployees = computed(() => {
|
||||||
|
return visibleEmployees.value.filter((employee) => hasContractAtSelectedDate(employee.id))
|
||||||
|
})
|
||||||
|
|
||||||
const visibleEmployeeIdSet = computed(() => new Set(visibleEmployees.value.map((employee) => employee.id)))
|
const visibleEmployeeIdSet = computed(() => new Set(visibleEmployees.value.map((employee) => employee.id)))
|
||||||
|
|
||||||
const filteredWeeklySummary = computed<WeeklyWorkHourSummary | null>(() => {
|
const filteredWeeklySummary = computed<WeeklyWorkHourSummary | null>(() => {
|
||||||
if (!weeklySummary.value) return null
|
if (!weeklySummary.value) return null
|
||||||
return {
|
return {
|
||||||
...weeklySummary.value,
|
...weeklySummary.value,
|
||||||
rows: weeklySummary.value.rows.filter((row) => visibleEmployeeIdSet.value.has(row.employeeId))
|
rows: weeklySummary.value.rows.filter((row) =>
|
||||||
|
visibleEmployeeIdSet.value.has(row.employeeId) && row.hasContractForWeek !== false
|
||||||
|
)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -1096,6 +1102,7 @@ export const useHoursPage = () => {
|
|||||||
selectedSiteIds,
|
selectedSiteIds,
|
||||||
employees,
|
employees,
|
||||||
visibleEmployees,
|
visibleEmployees,
|
||||||
|
displayedEmployees,
|
||||||
rows,
|
rows,
|
||||||
absenceTypes,
|
absenceTypes,
|
||||||
absenceForm,
|
absenceForm,
|
||||||
|
|||||||
@@ -38,7 +38,7 @@
|
|||||||
<DriverHoursDayView
|
<DriverHoursDayView
|
||||||
v-if="viewMode === 'day'"
|
v-if="viewMode === 'day'"
|
||||||
v-model:rows="rows"
|
v-model:rows="rows"
|
||||||
:employees="visibleEmployees"
|
:employees="displayedEmployees"
|
||||||
:is-admin="isAdmin"
|
:is-admin="isAdmin"
|
||||||
:is-site-manager="isSiteManager"
|
:is-site-manager="isSiteManager"
|
||||||
:day-grid-cols="dayGridCols"
|
:day-grid-cols="dayGridCols"
|
||||||
@@ -121,6 +121,7 @@ const {
|
|||||||
selectedSiteIds,
|
selectedSiteIds,
|
||||||
employees,
|
employees,
|
||||||
visibleEmployees,
|
visibleEmployees,
|
||||||
|
displayedEmployees,
|
||||||
rows,
|
rows,
|
||||||
absenceTypes,
|
absenceTypes,
|
||||||
absenceForm,
|
absenceForm,
|
||||||
|
|||||||
@@ -20,11 +20,19 @@
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex gap-10 py-7">
|
<div class="flex gap-3 py-7">
|
||||||
<div class="w-80">
|
<div class="w-80">
|
||||||
<EmployeeNameFilterInput v-model="employeeFilter"/>
|
<EmployeeNameFilterInput v-model="employeeFilter"/>
|
||||||
</div>
|
</div>
|
||||||
<SiteFilterSelector v-if="sites.length > 0" v-model="selectedSiteIds" :sites="sites"/>
|
<SiteFilterSelector v-if="sites.length > 0" v-model="selectedSiteIds" :sites="sites"/>
|
||||||
|
<select
|
||||||
|
v-model="contractStatusFilter"
|
||||||
|
class="rounded-md border border-primary-500 bg-white px-3 py-2 text-md font-semibold text-primary-500"
|
||||||
|
>
|
||||||
|
<option value="active">Avec contrat</option>
|
||||||
|
<option value="inactive">Sans contrat</option>
|
||||||
|
<option value="all">Tous</option>
|
||||||
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -49,7 +57,7 @@
|
|||||||
<div class="text-center text-[20px]">
|
<div class="text-center text-[20px]">
|
||||||
<p class="text-primary-500 font-bold">{{ employee.firstName }} {{ employee.lastName }}</p>
|
<p class="text-primary-500 font-bold">{{ employee.firstName }} {{ employee.lastName }}</p>
|
||||||
<p>Nom du poste occupé</p>
|
<p>Nom du poste occupé</p>
|
||||||
<p>Site ({{ employee.site?.name ?? '-' }})</p>
|
<p>{{ employee.site?.name ?? '-' }}</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -248,20 +256,21 @@ const employees = ref<Employee[]>([])
|
|||||||
const sites = ref<Site[]>([])
|
const sites = ref<Site[]>([])
|
||||||
const contracts = ref<Contract[]>([])
|
const contracts = ref<Contract[]>([])
|
||||||
const employeeFilter = ref('')
|
const employeeFilter = ref('')
|
||||||
|
const contractStatusFilter = ref<'active' | 'inactive' | 'all'>('active')
|
||||||
const selectedSiteIds = ref<number[]>([])
|
const selectedSiteIds = ref<number[]>([])
|
||||||
|
|
||||||
const filteredEmployees = computed<Employee[]>(() => {
|
const filteredEmployees = computed<Employee[]>(() => {
|
||||||
if (selectedSiteIds.value.length === 0) return []
|
if (selectedSiteIds.value.length === 0) return []
|
||||||
|
|
||||||
const filter = employeeFilter.value.trim().toLowerCase()
|
const filter = employeeFilter.value.trim().toLowerCase()
|
||||||
const bySite = employees.value.filter((employee) => {
|
return employees.value.filter((employee) => {
|
||||||
const siteId = employee.site?.id
|
const siteId = employee.site?.id
|
||||||
return !!siteId && selectedSiteIds.value.includes(siteId)
|
if (!siteId || !selectedSiteIds.value.includes(siteId)) return false
|
||||||
})
|
|
||||||
|
|
||||||
if (!filter) return bySite
|
if (contractStatusFilter.value === 'active' && !employee.hasActiveContract) return false
|
||||||
|
if (contractStatusFilter.value === 'inactive' && employee.hasActiveContract) return false
|
||||||
|
|
||||||
return bySite.filter((employee) => {
|
if (!filter) return true
|
||||||
const firstName = employee.firstName?.toLowerCase() ?? ''
|
const firstName = employee.firstName?.toLowerCase() ?? ''
|
||||||
const lastName = employee.lastName?.toLowerCase() ?? ''
|
const lastName = employee.lastName?.toLowerCase() ?? ''
|
||||||
return firstName.includes(filter) || lastName.includes(filter)
|
return firstName.includes(filter) || lastName.includes(filter)
|
||||||
|
|||||||
@@ -38,7 +38,7 @@
|
|||||||
<HoursDayView
|
<HoursDayView
|
||||||
v-if="viewMode === 'day'"
|
v-if="viewMode === 'day'"
|
||||||
v-model:rows="rows"
|
v-model:rows="rows"
|
||||||
:employees="visibleEmployees"
|
:employees="displayedEmployees"
|
||||||
:is-admin="isAdmin"
|
:is-admin="isAdmin"
|
||||||
:is-site-manager="isSiteManager"
|
:is-site-manager="isSiteManager"
|
||||||
:day-grid-cols="dayGridCols"
|
:day-grid-cols="dayGridCols"
|
||||||
@@ -126,6 +126,7 @@ const {
|
|||||||
selectedSiteIds,
|
selectedSiteIds,
|
||||||
employees,
|
employees,
|
||||||
visibleEmployees,
|
visibleEmployees,
|
||||||
|
displayedEmployees,
|
||||||
rows,
|
rows,
|
||||||
absenceTypes,
|
absenceTypes,
|
||||||
absenceForm,
|
absenceForm,
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ export type Employee = {
|
|||||||
lastName: string
|
lastName: string
|
||||||
site: Site
|
site: Site
|
||||||
contract?: Contract | null
|
contract?: Contract | null
|
||||||
|
hasActiveContract?: boolean
|
||||||
isDriver?: boolean
|
isDriver?: boolean
|
||||||
currentContractNature?: 'CDI' | 'CDD' | 'INTERIM'
|
currentContractNature?: 'CDI' | 'CDD' | 'INTERIM'
|
||||||
currentContractStartDate?: string | null
|
currentContractStartDate?: string | null
|
||||||
|
|||||||
@@ -54,6 +54,7 @@ export type WeeklyWorkHourDailySummary = {
|
|||||||
hasAbsence?: boolean
|
hasAbsence?: boolean
|
||||||
absenceLabel?: string | null
|
absenceLabel?: string | null
|
||||||
absenceColor?: string | null
|
absenceColor?: string | null
|
||||||
|
hasNightBasket?: boolean
|
||||||
hasBreakfast?: boolean
|
hasBreakfast?: boolean
|
||||||
hasLunch?: boolean
|
hasLunch?: boolean
|
||||||
hasDinner?: boolean
|
hasDinner?: boolean
|
||||||
@@ -78,11 +79,13 @@ export type WeeklyWorkHourRowSummary = {
|
|||||||
weeklyOvertime25Minutes?: number
|
weeklyOvertime25Minutes?: number
|
||||||
weeklyOvertime50Minutes?: number
|
weeklyOvertime50Minutes?: number
|
||||||
weeklyRecoveryMinutes?: number
|
weeklyRecoveryMinutes?: number
|
||||||
|
weeklyNightBasketCount?: number
|
||||||
isDriver?: boolean
|
isDriver?: boolean
|
||||||
weeklyBreakfastCount?: number
|
weeklyBreakfastCount?: number
|
||||||
weeklyLunchCount?: number
|
weeklyLunchCount?: number
|
||||||
weeklyDinnerCount?: number
|
weeklyDinnerCount?: number
|
||||||
weeklyOvernightCount?: number
|
weeklyOvernightCount?: number
|
||||||
|
hasContractForWeek?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
export type WeeklyWorkHourSummary = {
|
export type WeeklyWorkHourSummary = {
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ final class WeeklyDaySummary
|
|||||||
public bool $hasAbsence = false,
|
public bool $hasAbsence = false,
|
||||||
public ?string $absenceLabel = null,
|
public ?string $absenceLabel = null,
|
||||||
public ?string $absenceColor = null,
|
public ?string $absenceColor = null,
|
||||||
|
public bool $hasNightBasket = false,
|
||||||
public bool $hasBreakfast = false,
|
public bool $hasBreakfast = false,
|
||||||
public bool $hasLunch = false,
|
public bool $hasLunch = false,
|
||||||
public bool $hasDinner = false,
|
public bool $hasDinner = false,
|
||||||
|
|||||||
@@ -27,10 +27,12 @@ final class WeeklySummaryRow
|
|||||||
public int $weeklyOvertime25Minutes,
|
public int $weeklyOvertime25Minutes,
|
||||||
public int $weeklyOvertime50Minutes,
|
public int $weeklyOvertime50Minutes,
|
||||||
public int $weeklyRecoveryMinutes,
|
public int $weeklyRecoveryMinutes,
|
||||||
|
public int $weeklyNightBasketCount = 0,
|
||||||
public bool $isDriver = false,
|
public bool $isDriver = false,
|
||||||
public int $weeklyBreakfastCount = 0,
|
public int $weeklyBreakfastCount = 0,
|
||||||
public int $weeklyLunchCount = 0,
|
public int $weeklyLunchCount = 0,
|
||||||
public int $weeklyDinnerCount = 0,
|
public int $weeklyDinnerCount = 0,
|
||||||
public int $weeklyOvernightCount = 0,
|
public int $weeklyOvernightCount = 0,
|
||||||
|
public bool $hasContractForWeek = true,
|
||||||
) {}
|
) {}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -260,6 +260,12 @@ class Employee
|
|||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[Groups(['employee:read'])]
|
||||||
|
public function getHasActiveContract(): bool
|
||||||
|
{
|
||||||
|
return null !== $this->resolveCurrentContractPeriod();
|
||||||
|
}
|
||||||
|
|
||||||
#[Groups(['employee:read'])]
|
#[Groups(['employee:read'])]
|
||||||
public function getIsDriver(): bool
|
public function getIsDriver(): bool
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -187,16 +187,17 @@ final readonly class WorkHourWeeklySummaryProvider implements ProviderInterface
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
$weeklyDayMinutes = 0;
|
$weeklyDayMinutes = 0;
|
||||||
$weeklyNightMinutes = 0;
|
$weeklyNightMinutes = 0;
|
||||||
$weeklyWorkshopMinutes = 0;
|
$weeklyWorkshopMinutes = 0;
|
||||||
$weeklyTotalMinutes = 0;
|
$weeklyTotalMinutes = 0;
|
||||||
$weeklyPresenceCount = 0.0;
|
$weeklyPresenceCount = 0.0;
|
||||||
$weeklyBreakfastCount = 0;
|
$weeklyNightBasketCount = 0;
|
||||||
$weeklyLunchCount = 0;
|
$weeklyBreakfastCount = 0;
|
||||||
$weeklyDinnerCount = 0;
|
$weeklyLunchCount = 0;
|
||||||
$weeklyOvernightCount = 0;
|
$weeklyDinnerCount = 0;
|
||||||
$daily = [];
|
$weeklyOvernightCount = 0;
|
||||||
|
$daily = [];
|
||||||
// Les contrats au suivi "présence" ne manipulent pas les heures, mais des demi-journées.
|
// Les contrats au suivi "présence" ne manipulent pas les heures, mais des demi-journées.
|
||||||
$weekAnchorContract = $contractsByEmployeeDate[$employeeId][$anchorDateYmd]
|
$weekAnchorContract = $contractsByEmployeeDate[$employeeId][$anchorDateYmd]
|
||||||
?? $contractsByEmployeeDate[$employeeId][$days[0]]
|
?? $contractsByEmployeeDate[$employeeId][$days[0]]
|
||||||
@@ -208,8 +209,12 @@ final readonly class WorkHourWeeklySummaryProvider implements ProviderInterface
|
|||||||
?? $contractNaturesByEmployeeDate[$employeeId][$days[0]]
|
?? $contractNaturesByEmployeeDate[$employeeId][$days[0]]
|
||||||
?? ContractNature::CDI;
|
?? ContractNature::CDI;
|
||||||
$employeeContractsByDate = [];
|
$employeeContractsByDate = [];
|
||||||
|
$hasContractForWeek = false;
|
||||||
foreach ($days as $date) {
|
foreach ($days as $date) {
|
||||||
$employeeContractsByDate[$date] = $contractsByEmployeeDate[$employeeId][$date] ?? null;
|
$employeeContractsByDate[$date] = $contractsByEmployeeDate[$employeeId][$date] ?? null;
|
||||||
|
if (null !== $employeeContractsByDate[$date]) {
|
||||||
|
$hasContractForWeek = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach ($days as $date) {
|
foreach ($days as $date) {
|
||||||
@@ -228,11 +233,12 @@ final readonly class WorkHourWeeklySummaryProvider implements ProviderInterface
|
|||||||
$dayMinutes = ($entry['dayHoursMinutes'] ?? 0);
|
$dayMinutes = ($entry['dayHoursMinutes'] ?? 0);
|
||||||
$nightMinutes = ($entry['nightHoursMinutes'] ?? 0);
|
$nightMinutes = ($entry['nightHoursMinutes'] ?? 0);
|
||||||
$workshopMinutes = ($entry['workshopHoursMinutes'] ?? 0);
|
$workshopMinutes = ($entry['workshopHoursMinutes'] ?? 0);
|
||||||
$totalMinutes = $dayMinutes + $nightMinutes + $workshopMinutes;
|
$totalMinutes = $dayMinutes + $nightMinutes + $workshopMinutes + $creditedMinutes;
|
||||||
$hasBreakfast = $entry['hasBreakfast'] ?? false;
|
$dayMinutes += $creditedMinutes;
|
||||||
$hasLunch = $entry['hasLunch'] ?? false;
|
$hasBreakfast = $entry['hasBreakfast'] ?? false;
|
||||||
$hasDinner = $entry['hasDinner'] ?? false;
|
$hasLunch = $entry['hasLunch'] ?? false;
|
||||||
$hasOvernight = $entry['hasOvernight'] ?? false;
|
$hasDinner = $entry['hasDinner'] ?? false;
|
||||||
|
$hasOvernight = $entry['hasOvernight'] ?? false;
|
||||||
if ($hasBreakfast) {
|
if ($hasBreakfast) {
|
||||||
++$weeklyBreakfastCount;
|
++$weeklyBreakfastCount;
|
||||||
}
|
}
|
||||||
@@ -265,6 +271,11 @@ final readonly class WorkHourWeeklySummaryProvider implements ProviderInterface
|
|||||||
$present = min(1.0, $morning + $afternoon + $creditedPresence);
|
$present = min(1.0, $morning + $afternoon + $creditedPresence);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$hasNightBasket = $nightMinutes > $dayMinutes && $nightMinutes > 0;
|
||||||
|
if ($hasNightBasket) {
|
||||||
|
++$weeklyNightBasketCount;
|
||||||
|
}
|
||||||
|
|
||||||
$weeklyDayMinutes += $dayMinutes;
|
$weeklyDayMinutes += $dayMinutes;
|
||||||
$weeklyNightMinutes += $nightMinutes;
|
$weeklyNightMinutes += $nightMinutes;
|
||||||
$weeklyWorkshopMinutes += $workshopMinutes;
|
$weeklyWorkshopMinutes += $workshopMinutes;
|
||||||
@@ -283,6 +294,7 @@ final readonly class WorkHourWeeklySummaryProvider implements ProviderInterface
|
|||||||
hasAbsence: $absenceByEmployeeDate[$employeeId][$date] ?? false,
|
hasAbsence: $absenceByEmployeeDate[$employeeId][$date] ?? false,
|
||||||
absenceLabel: $absenceLabelByEmployeeDate[$employeeId][$date] ?? null,
|
absenceLabel: $absenceLabelByEmployeeDate[$employeeId][$date] ?? null,
|
||||||
absenceColor: $absenceColorByEmployeeDate[$employeeId][$date] ?? null,
|
absenceColor: $absenceColorByEmployeeDate[$employeeId][$date] ?? null,
|
||||||
|
hasNightBasket: $hasNightBasket,
|
||||||
hasBreakfast: $hasBreakfast,
|
hasBreakfast: $hasBreakfast,
|
||||||
hasLunch: $hasLunch,
|
hasLunch: $hasLunch,
|
||||||
hasDinner: $hasDinner,
|
hasDinner: $hasDinner,
|
||||||
@@ -325,11 +337,13 @@ final readonly class WorkHourWeeklySummaryProvider implements ProviderInterface
|
|||||||
weeklyOvertime25Minutes: $weeklyOvertime25Minutes,
|
weeklyOvertime25Minutes: $weeklyOvertime25Minutes,
|
||||||
weeklyOvertime50Minutes: $weeklyOvertime50Minutes,
|
weeklyOvertime50Minutes: $weeklyOvertime50Minutes,
|
||||||
weeklyRecoveryMinutes: $weeklyRecoveryMinutes,
|
weeklyRecoveryMinutes: $weeklyRecoveryMinutes,
|
||||||
|
weeklyNightBasketCount: $weeklyNightBasketCount,
|
||||||
isDriver: $isDriver,
|
isDriver: $isDriver,
|
||||||
weeklyBreakfastCount: $weeklyBreakfastCount,
|
weeklyBreakfastCount: $weeklyBreakfastCount,
|
||||||
weeklyLunchCount: $weeklyLunchCount,
|
weeklyLunchCount: $weeklyLunchCount,
|
||||||
weeklyDinnerCount: $weeklyDinnerCount,
|
weeklyDinnerCount: $weeklyDinnerCount,
|
||||||
weeklyOvernightCount: $weeklyOvernightCount,
|
weeklyOvernightCount: $weeklyOvernightCount,
|
||||||
|
hasContractForWeek: $hasContractForWeek,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -60,7 +60,7 @@
|
|||||||
thead th {
|
thead th {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
font-size: 11px;
|
font-size: 10px;
|
||||||
white-space: normal;
|
white-space: normal;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -78,7 +78,7 @@
|
|||||||
}
|
}
|
||||||
td.obs { }
|
td.obs { }
|
||||||
|
|
||||||
tbody td { font-size: 12px; }
|
tbody td { font-size: 10px; }
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
|||||||
Reference in New Issue
Block a user