diff --git a/eform-client/cypress/e2e/plugins/time-planning-pn/b/dashboard-edit-b.spec.cy.ts b/eform-client/cypress/e2e/plugins/time-planning-pn/b/dashboard-edit-b.spec.cy.ts index 78def8ce1..1f7ec027c 100644 --- a/eform-client/cypress/e2e/plugins/time-planning-pn/b/dashboard-edit-b.spec.cy.ts +++ b/eform-client/cypress/e2e/plugins/time-planning-pn/b/dashboard-edit-b.spec.cy.ts @@ -113,13 +113,13 @@ const secondUpdatePlanTexts = [ ]; const secondUpdateActualTexts = [ - { date: nextWeekDates[0], start1StartedAt: '07:30', stop1StoppedAt: '15:30', pause1Id: '00:25', start2StartedAt: '00:00', stop2StoppedAt: '00:00', pause2Id: '00:00', plannedHours: '8:00', flexBalanceToDate: 'swap_vert97.03', flexToDate: '97.45', flexIncludingToday: '97.03', nettoHours: '7.58', todaysFlex: '-0.42', paidOutFlex: 0, calculatedHours: '8' }, - { date: nextWeekDates[1], start1StartedAt: '07:50', stop1StoppedAt: '16:00', pause1Id: '01:00', start2StartedAt: '00:00', stop2StoppedAt: '00:00', pause2Id: '00:00', plannedHours: '8:00', flexBalanceToDate: 'swap_vert97.03', flexToDate: '97.03', flexIncludingToday: '97.03', nettoHours: '7.17', todaysFlex: '0.00', paidOutFlex: 0, calculatedHours: '7.166666666666667' }, + { date: nextWeekDates[0], start1StartedAt: '07:30', stop1StoppedAt: '15:30', pause1Id: '00:25', start2StartedAt: '', stop2StoppedAt: '', pause2Id: '', plannedHours: '8:00', flexBalanceToDate: 'swap_vert97.03', flexToDate: '97.45', flexIncludingToday: '97.03', nettoHours: '7.58', todaysFlex: '-0.42', paidOutFlex: 0, calculatedHours: '8' }, + { date: nextWeekDates[1], start1StartedAt: '07:50', stop1StoppedAt: '16:00', pause1Id: '01:00', start2StartedAt: '', stop2StoppedAt: '', pause2Id: '', plannedHours: '8:00', flexBalanceToDate: 'swap_vert97.03', flexToDate: '97.03', flexIncludingToday: '97.03', nettoHours: '7.17', todaysFlex: '0.00', paidOutFlex: 0, calculatedHours: '7.166666666666667' }, { date: nextWeekDates[2], start1StartedAt: '07:15', stop1StoppedAt: '16:00', pause1Id: '01:00', start2StartedAt: '17:00', stop2StoppedAt: '20:00', pause2Id: '00:30', plannedHours: '8:00', flexBalanceToDate: 'swap_vert97.03', flexToDate: '97.03', flexIncludingToday: '97.03', nettoHours: '10.25', todaysFlex: '0.00', paidOutFlex: 0, calculatedHours: '10.25' }, { date: nextWeekDates[3], start1StartedAt: '06:00', stop1StoppedAt: '12:00', pause1Id: '00:30', start2StartedAt: '18:00', stop2StoppedAt: '20:00', pause2Id: '00:30', plannedHours: '8:00', flexBalanceToDate: 'swap_vert97.03', flexToDate: '97.03', flexIncludingToday: '97.03', nettoHours: '7.00', todaysFlex: '0.00', paidOutFlex: 0, calculatedHours: '7' }, { date: nextWeekDates[4], start1StartedAt: '06:00', stop1StoppedAt: '12:00' , pause1Id: '01:50' , start2StartedAt: '18:00' , stop2StoppedAt: '20:00' , pause2Id: '01:50' , plannedHours: '8.0' , flexBalanceToDate: 'swap_vert94.70' , flexToDate: '97.03' , flexIncludingToday: '94.70' , nettoHours: '4.33' , todaysFlex: '-2.33' , paidOutFlex : 0, calculatedHours : 6.666666666666667 }, - { date : nextWeekDates[5] , start1StartedAt : '00:00' , stop1StoppedAt : '00:00' , pause1Id : '00:00' , start2StartedAt : '00:00' , stop2StoppedAt : '00:00' , pause2Id : '00:00' , plannedHours : '' , flexBalanceToDate : 'swap_vert88.36' , flexToDate : '94.70' , flexIncludingToday : '88.36' , nettoHours : '0.00' , todaysFlex : '-6.33' , paidOutFlex : 0 , calculatedHours : 6.333333333333333 }, - { date : lastWeekDates[6] , start1StartedAt : '06:00' , stop1StoppedAt : '14:00' , pause1Id : '00:30' , start2StartedAt : '00:00' , stop2StoppedAt : '00:00' , pause2Id : '00:00' , plannedHours : '8:00' , flexBalanceToDate : 'swap_vert88.36' , flexToDate : '88.36' , flexIncludingToday : '88.36' , nettoHours : '7.50' , todaysFlex : '0.00' , paidOutFlex : 0 , calculatedHours : '7.5' } + { date : nextWeekDates[5] , start1StartedAt : '' , stop1StoppedAt : '' , pause1Id : '' , start2StartedAt : '' , stop2StoppedAt : '' , pause2Id : '' , plannedHours : '' , flexBalanceToDate : 'swap_vert88.36' , flexToDate : '94.70' , flexIncludingToday : '88.36' , nettoHours : '0.00' , todaysFlex : '-6.33' , paidOutFlex : 0 , calculatedHours : 6.333333333333333 }, + { date : lastWeekDates[6] , start1StartedAt : '06:00' , stop1StoppedAt : '14:00' , pause1Id : '00:30' , start2StartedAt : '' , stop2StoppedAt : '' , pause2Id : '' , plannedHours : '8:00' , flexBalanceToDate : 'swap_vert88.36' , flexToDate : '88.36' , flexIncludingToday : '88.36' , nettoHours : '7.50' , todaysFlex : '0.00' , paidOutFlex : 0 , calculatedHours : '7.5' } ]; describe('Dashboard edit values', () => { @@ -144,7 +144,7 @@ describe('Dashboard edit values', () => { cy.get(cellId).click(); cy.get('#planHours').should('be.visible'); - if (secondUpdateActualTexts[i].start1StartedAt !== '') { + if (secondUpdateActualTexts[i].start1StartedAt !== '' && secondUpdateActualTexts[i].start1StartedAt !== '00:00') { cy.get(`#start1StartedAt`).click(); // eslint-disable-next-line max-len let degrees0 = 360 / 12 * parseInt(secondUpdateActualTexts[i].start1StartedAt.split(':')[0]); @@ -165,7 +165,7 @@ describe('Dashboard edit values', () => { } cy.get('#start1StartedAt').should('have.value', secondUpdateActualTexts[i].start1StartedAt); - if (secondUpdateActualTexts[i].stop1StoppedAt !== '') { + if (secondUpdateActualTexts[i].stop1StoppedAt !== '' && secondUpdateActualTexts[i].stop1StoppedAt !== '00:00') { cy.get(`#stop1StoppedAt`).click(); // eslint-disable-next-line max-len let degrees1 = 360 / 12 * parseInt(secondUpdateActualTexts[i].stop1StoppedAt.split(':')[0]); @@ -189,7 +189,7 @@ describe('Dashboard edit values', () => { } cy.get('#stop1StoppedAt').should('have.value', secondUpdateActualTexts[i].stop1StoppedAt); - if (secondUpdateActualTexts[i].pause1Id !== '' || secondUpdateActualTexts[i].pause1Id !== '00:00') { + if (secondUpdateActualTexts[i].pause1Id !== '' && secondUpdateActualTexts[i].pause1Id !== '00:00') { cy.get(`#pause1Id`).click(); // eslint-disable-next-line max-len let degrees2 = 360 / 12 * parseInt(secondUpdateActualTexts[i].pause1Id.split(':')[0]); @@ -212,10 +212,10 @@ describe('Dashboard edit values', () => { cy.get('.timepicker-button span').contains('Ok').click(); cy.get('#pause1Id').should('have.value', secondUpdateActualTexts[i].pause1Id); } else { - cy.get('#pause1Id').should('have.value', '00:00'); + cy.get('#pause1Id').should('have.value', ''); } - if (secondUpdateActualTexts[i].start2StartedAt !== '' || secondUpdateActualTexts[i].start2StartedAt !== '00:00') { + if (secondUpdateActualTexts[i].start2StartedAt !== '' && secondUpdateActualTexts[i].start2StartedAt !== '00:00') { cy.get(`#start2StartedAt`).click(); // eslint-disable-next-line max-len let degrees3 = 360 / 12 * parseInt(secondUpdateActualTexts[i].start2StartedAt.split(':')[0]); @@ -239,7 +239,7 @@ describe('Dashboard edit values', () => { } cy.get('#start2StartedAt').should('have.value', secondUpdateActualTexts[i].start2StartedAt); - if (secondUpdateActualTexts[i].stop2StoppedAt !== '' || secondUpdateActualTexts[i].stop2StoppedAt !== '00:00' ) { + if (secondUpdateActualTexts[i].stop2StoppedAt !== '' && secondUpdateActualTexts[i].stop2StoppedAt !== '00:00' ) { cy.get(`#stop2StoppedAt`).click(); // eslint-disable-next-line max-len let degrees4 = 360 / 12 * parseInt(secondUpdateActualTexts[i].stop2StoppedAt.split(':')[0]); @@ -263,7 +263,7 @@ describe('Dashboard edit values', () => { } cy.get('#stop2StoppedAt').should('have.value', secondUpdateActualTexts[i].stop2StoppedAt); - if (secondUpdateActualTexts[i].pause2Id !== '' || secondUpdateActualTexts[i].pause2Id !== '00:00') { + if (secondUpdateActualTexts[i].pause2Id !== '' && secondUpdateActualTexts[i].pause2Id !== '00:00') { cy.get(`#pause2Id`).click(); // eslint-disable-next-line max-len let degrees5 = 360 / 12 * parseInt(secondUpdateActualTexts[i].pause2Id.split(':')[0]); diff --git a/eform-client/cypress/e2e/plugins/time-planning-pn/f/dashboard-edit-a.spec.cy.ts b/eform-client/cypress/e2e/plugins/time-planning-pn/f/dashboard-edit-a.spec.cy.ts index c7e1f4070..731510cf8 100644 --- a/eform-client/cypress/e2e/plugins/time-planning-pn/f/dashboard-edit-a.spec.cy.ts +++ b/eform-client/cypress/e2e/plugins/time-planning-pn/f/dashboard-edit-a.spec.cy.ts @@ -73,8 +73,8 @@ describe('Dashboard edit values', () => { it('should show an error when planned break is longer than the shift duration', () => { setTimepickerValue('#plannedStartOfShift1', '1', '00'); - setTimepickerValue('#plannedBreakOfShift1', '9', '00'); setTimepickerValue('#plannedEndOfShift1', '10', '00'); + setTimepickerValue('#plannedBreakOfShift1', '9', '00'); assertInputError('plannedBreakOfShift1-Error', 'Break cannot be equal or longer than shift duration'); }); diff --git a/eform-client/src/app/plugins/modules/time-planning-pn/components/plannings/time-planning-actions/workday-entity/workday-entity-dialog.component.html b/eform-client/src/app/plugins/modules/time-planning-pn/components/plannings/time-planning-actions/workday-entity/workday-entity-dialog.component.html index 463bd63a5..b1e05eaee 100644 --- a/eform-client/src/app/plugins/modules/time-planning-pn/components/plannings/time-planning-actions/workday-entity/workday-entity-dialog.component.html +++ b/eform-client/src/app/plugins/modules/time-planning-pn/components/plannings/time-planning-actions/workday-entity/workday-entity-dialog.component.html @@ -763,12 +763,13 @@ {{ 'Cancel' | translate }} + + diff --git a/eform-client/src/app/plugins/modules/time-planning-pn/components/plannings/time-planning-actions/workday-entity/workday-entity-dialog.component.ts b/eform-client/src/app/plugins/modules/time-planning-pn/components/plannings/time-planning-actions/workday-entity/workday-entity-dialog.component.ts index 98d2af2d7..20a3d5425 100644 --- a/eform-client/src/app/plugins/modules/time-planning-pn/components/plannings/time-planning-actions/workday-entity/workday-entity-dialog.component.ts +++ b/eform-client/src/app/plugins/modules/time-planning-pn/components/plannings/time-planning-actions/workday-entity/workday-entity-dialog.component.ts @@ -550,6 +550,14 @@ export class WorkdayEntityDialogComponent implements OnInit { } } + // Disallow pause = 00:00 + if (breakMin === 0) { + setError(pauseControl, 'invalidPause', 'Pause cannot be 00:00'); + } else { + removeError(pauseControl, 'invalidPause'); + } + + if (duration > 24 * 60) { setError(group, 'shiftTooLong', 'Shift duration cannot exceed 24 hours'); } else { @@ -655,6 +663,24 @@ export class WorkdayEntityDialogComponent implements OnInit { const prevEnd = this.parseTimeToMinutes(prevShift.get('stop')?.value); const currStart = this.parseTimeToMinutes(currShift.get('start')?.value); + // Disallow 00:00 as start for shifts > 1 + if (i > 0 && currStart === 0) { + currShift.get('start')?.setErrors({ + ...(currShift.get('start')?.errors || {}), + invalidStart: `Start time 00:00 is not allowed for ${label} Shift ${i + 1}`, + }); + + if (!formError) { + formError = `${label} Shift ${i + 1} cannot start at 00:00`; + } + } else { + const errors = currShift.get('start')?.errors; + if (errors && errors['invalidStart']) { + delete errors['invalidStart']; + currShift.get('start')?.setErrors(Object.keys(errors).length ? errors : null); + } + } + if (prevEnd !== null && (currStart !== null && currStart !== 0)) { if (currStart < prevEnd) { currShift.get('start')?.setErrors({ @@ -990,24 +1016,24 @@ export class WorkdayEntityDialogComponent implements OnInit { const s2 = this.workdayForm.get('planned.shift2') as FormGroup; switch (number) { case 1: - s1.patchValue({start: '00:00', break: '00:00', stop: '00:00'}); - s2.patchValue({start: '00:00', break: '00:00', stop: '00:00'}); + s1.patchValue({start: null, break: null, stop: null}); + s2.patchValue({start: null, break: null, stop: null}); break; case 2: - s1.patchValue({break: '00:00'}); + s1.patchValue({break: null}); break; case 3: - s1.patchValue({break: '00:00', stop: '00:00'}); - s2.patchValue({start: '00:00', break: '00:00', stop: '00:00'}); + s1.patchValue({break: null, stop: null}); + s2.patchValue({start: null, break: null, stop: null}); break; case 4: - s2.patchValue({start: '00:00', break: '00:00', stop: '00:00'}); + s2.patchValue({start: null, break: null, stop: null}); break; case 5: - s2.patchValue({break: '00:00'}); + s2.patchValue({break: null}); break; case 6: - s2.patchValue({break: '00:00', stop: '00:00'}); + s2.patchValue({break: null, stop: null}); break; } this.calculatePlanHours(); @@ -1053,8 +1079,8 @@ export class WorkdayEntityDialogComponent implements OnInit { const p4 = this.workdayForm.get('planned.shift4')?.value as { start: string; break: string; stop: string }; const p5 = this.workdayForm.get('planned.shift5')?.value as { start: string; break: string; stop: string }; - this.data.planningPrDayModels.plannedStartOfShift1 = this.convertTimeToMinutes(p1?.start); - this.data.planningPrDayModels.plannedEndOfShift1 = this.convertTimeToMinutes(p1?.stop); + this.data.planningPrDayModels.plannedStartOfShift1 = this.convertTimeToMinutes(p1?.start ?? '00:00'); + this.data.planningPrDayModels.plannedEndOfShift1 = this.convertTimeToMinutes(p1?.stop ?? '00:00'); this.data.planningPrDayModels.plannedBreakOfShift1 = this.convertTimeToMinutes(p1?.break ?? '00:00'); this.data.planningPrDayModels.plannedStartOfShift2 = this.convertTimeToMinutes(p2?.start ?? '00:00'); @@ -1124,7 +1150,6 @@ export class WorkdayEntityDialogComponent implements OnInit { // Rens paidOutFlex this.data.planningPrDayModels.paidOutFlex = this.data.planningPrDayModels.paidOutFlex === null ? 0 : this.data.planningPrDayModels.paidOutFlex; - this.data.planningPrDayModels.commentOffice = this.workdayForm.get('commentOffice')?.value; } private getPlannedShiftMinutes(