1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34 package fr.paris.lutece.plugins.appointment.service;
35
36 import java.time.DayOfWeek;
37 import java.time.LocalDate;
38 import java.time.LocalDateTime;
39 import java.time.LocalTime;
40 import java.util.ArrayList;
41 import java.util.List;
42 import java.util.Map;
43
44 import fr.paris.lutece.plugins.appointment.business.planning.TimeSlot;
45 import fr.paris.lutece.plugins.appointment.business.planning.WeekDefinition;
46 import fr.paris.lutece.plugins.appointment.business.planning.WorkingDay;
47 import fr.paris.lutece.plugins.appointment.business.rule.ReservationRule;
48 import fr.paris.lutece.plugins.appointment.business.slot.Period;
49 import fr.paris.lutece.plugins.appointment.business.slot.Slot;
50
51 public class CalendarBuilder
52 {
53
54
55
56 private CalendarBuilder( )
57 {
58
59 }
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74 public static List<Slot> buildListSlot( int nIdForm, Map<WeekDefinition, ReservationRule> mapReservationRule, LocalDate startingDate, LocalDate endingDate )
75 {
76 List<Slot> listSlot = new ArrayList<>( );
77 final List<WeekDefinition> listDateReservationRule = new ArrayList<>( mapReservationRule.keySet( ) );
78 WeekDefinition closestweeDef;
79 ReservationRule reservationRuleToApply = null;
80 LocalDate dateTemp = startingDate;
81 int nMaxCapacity;
82 DayOfWeek dayOfWeek;
83 WorkingDay workingDay;
84 LocalTime minTimeForThisDay;
85 LocalTime maxTimeForThisDay;
86 LocalTime timeTemp;
87 LocalDateTime dateTimeTemp;
88 Slot slotToAdd;
89 TimeSlot timeSlot;
90 LocalDate dateToCompare;
91
92 WeekDefinition firsWeek = listDateReservationRule.stream( ).sorted( ( week1, week2 ) -> week1.getDateOfApply( ).compareTo( week2.getDateOfApply( ) ) )
93 .findFirst( ).orElse( null );
94 final LocalDate firstDateOfReservationRule = firsWeek.getDateOfApply( );
95 LocalDate startingDateToUse = startingDate;
96 if ( firstDateOfReservationRule != null && startingDate.isBefore( firstDateOfReservationRule ) )
97 {
98 startingDateToUse = firstDateOfReservationRule;
99 }
100
101 List<LocalDate> listDateOfClosingDay = ClosingDayService.findListDateOfClosingDayByIdFormAndDateRange( nIdForm, startingDateToUse, endingDate );
102
103 Map<LocalDateTime, Slot> mapSlot = SlotService.buildMapSlotsByIdFormAndDateRangeWithDateForKey( nIdForm, startingDateToUse.atStartOfDay( ),
104 endingDate.atTime( LocalTime.MAX ) );
105
106
107 while ( !dateTemp.isAfter( endingDate ) )
108 {
109 dateToCompare = dateTemp;
110
111
112 reservationRuleToApply = null;
113 closestweeDef = Utilities.getClosestWeekDefinitionInPast( listDateReservationRule, dateToCompare );
114 if ( closestweeDef != null )
115 {
116
117 reservationRuleToApply = mapReservationRule.get( closestweeDef );
118
119 }
120 nMaxCapacity = 0;
121
122 dayOfWeek = dateTemp.getDayOfWeek( );
123
124 workingDay = null;
125 if ( reservationRuleToApply != null )
126 {
127 nMaxCapacity = reservationRuleToApply.getMaxCapacityPerSlot( );
128 workingDay = WorkingDayService.getWorkingDayOfDayOfWeek( reservationRuleToApply.getListWorkingDay( ), dayOfWeek );
129
130 }
131 if ( workingDay != null )
132 {
133 minTimeForThisDay = WorkingDayService.getMinStartingTimeOfAWorkingDay( workingDay );
134 maxTimeForThisDay = WorkingDayService.getMaxEndingTimeOfAWorkingDay( workingDay );
135
136 if ( listDateOfClosingDay.contains( dateTemp ) )
137 {
138 listSlot.add( SlotService.buildSlot( nIdForm, new Period( dateTemp.atTime( minTimeForThisDay ), dateTemp.atTime( maxTimeForThisDay ) ),
139 nMaxCapacity, nMaxCapacity, nMaxCapacity, 0, Boolean.FALSE, Boolean.FALSE ) );
140 }
141 else
142 {
143 timeTemp = minTimeForThisDay;
144
145 while ( timeTemp.isBefore( maxTimeForThisDay ) || !timeTemp.equals( maxTimeForThisDay ) )
146 {
147
148 dateTimeTemp = dateTemp.atTime( timeTemp );
149
150 if ( mapSlot.containsKey( dateTimeTemp ) )
151 {
152 slotToAdd = mapSlot.get( dateTimeTemp );
153 timeTemp = slotToAdd.getEndingDateTime( ).toLocalTime( );
154 listSlot.add( slotToAdd );
155 }
156 else
157 {
158
159 timeSlot = TimeSlotService.getTimeSlotInListOfTimeSlotWithStartingTime( workingDay.getListTimeSlot( ), timeTemp );
160 if ( timeSlot != null )
161 {
162 timeTemp = timeSlot.getEndingTime( );
163 int nMaxCapacityToPut = timeSlot.getMaxCapacity( );
164 slotToAdd = SlotService.buildSlot( nIdForm, new Period( dateTimeTemp, dateTemp.atTime( timeTemp ) ), nMaxCapacityToPut,
165 nMaxCapacityToPut, nMaxCapacityToPut, 0, timeSlot.getIsOpen( ), Boolean.FALSE );
166 listSlot.add( slotToAdd );
167 }
168 else
169 {
170 break;
171 }
172 }
173 }
174 }
175 }
176 else
177 {
178
179
180 if ( reservationRuleToApply != null )
181 {
182 minTimeForThisDay = WorkingDayService.getMinStartingTimeOfAListOfWorkingDay( reservationRuleToApply.getListWorkingDay( ) );
183 maxTimeForThisDay = WorkingDayService.getMaxEndingTimeOfAListOfWorkingDay( reservationRuleToApply.getListWorkingDay( ) );
184 int nDuration = reservationRuleToApply.getDurationAppointments( );
185 if ( minTimeForThisDay != null && maxTimeForThisDay != null )
186 {
187 timeTemp = minTimeForThisDay;
188
189 while ( timeTemp.isBefore( maxTimeForThisDay ) || !timeTemp.equals( maxTimeForThisDay ) )
190 {
191
192 dateTimeTemp = dateTemp.atTime( timeTemp );
193
194 if ( mapSlot.containsKey( dateTimeTemp ) )
195 {
196 slotToAdd = mapSlot.get( dateTimeTemp );
197 timeTemp = slotToAdd.getEndingDateTime( ).toLocalTime( );
198 listSlot.add( slotToAdd );
199 }
200 else
201 {
202 timeTemp = timeTemp.plusMinutes( nDuration );
203 if ( timeTemp.isAfter( maxTimeForThisDay ) )
204 {
205 timeTemp = maxTimeForThisDay;
206 }
207 slotToAdd = SlotService.buildSlot( nIdForm, new Period( dateTimeTemp, dateTemp.atTime( timeTemp ) ), nMaxCapacity, nMaxCapacity,
208 nMaxCapacity, 0, Boolean.FALSE, Boolean.FALSE );
209 listSlot.add( slotToAdd );
210 }
211 }
212 }
213 }
214 }
215 dateTemp = dateTemp.plusDays( 1 );
216 }
217 return listSlot;
218 }
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237 public static List<Slot> buildListSlot( int nIdForm, Map<WeekDefinition, ReservationRule> mapReservationRule, LocalDate startingDate, LocalDate endingDate,
238 int nNbPlaces, boolean isAllOpenSlot )
239 {
240 List<Slot> listSlotToShow = new ArrayList<>( );
241
242 final List<WeekDefinition> listDateReservationRule = new ArrayList<>( mapReservationRule.keySet( ) );
243 WeekDefinition closestweeDef;
244 ReservationRule reservationRuleToApply = null;
245 LocalDate dateTemp = startingDate;
246 DayOfWeek dayOfWeek;
247 WorkingDay workingDay;
248 LocalTime minTimeForThisDay;
249 LocalTime maxTimeForThisDay;
250 LocalTime timeTemp;
251 LocalDateTime dateTimeTemp;
252 LocalDateTime endingDateTime;
253 LocalDateTime startingDateTime = null;
254 LocalTime tempEndingDateTime = null;
255 LocalDateTime localDateTimeNow = LocalDateTime.now( );
256
257 boolean isChanged = true;
258 boolean isfull = false;
259 int sumNbPotentialRemainingPlaces;
260 int sumNbRemainingPlaces;
261 int nbSlot;
262
263 Slot slotToAdd;
264 TimeSlot timeSlot;
265 LocalDate dateToCompare;
266
267 WeekDefinition firsWeek = listDateReservationRule.stream( ).sorted( ( week1, week2 ) -> week1.getDateOfApply( ).compareTo( week2.getDateOfApply( ) ) )
268 .findFirst( ).orElse( null );
269 final LocalDate firstDateOfReservationRule = firsWeek.getDateOfApply( );
270 LocalDate startingDateToUse = startingDate;
271 if ( firstDateOfReservationRule != null && startingDate.isBefore( firstDateOfReservationRule ) )
272 {
273 startingDateToUse = firstDateOfReservationRule;
274 }
275
276 List<LocalDate> listDateOfClosingDay = ClosingDayService.findListDateOfClosingDayByIdFormAndDateRange( nIdForm, startingDateToUse, endingDate );
277
278 Map<LocalDateTime, Slot> mapSlot = SlotService.buildMapSlotsByIdFormAndDateRangeWithDateForKey( nIdForm, startingDateToUse.atStartOfDay( ),
279 endingDate.atTime( LocalTime.MAX ) );
280
281
282 while ( !dateTemp.isAfter( endingDate ) )
283 {
284 dateToCompare = dateTemp;
285
286
287 reservationRuleToApply = null;
288 closestweeDef = Utilities.getClosestWeekDefinitionInPast( listDateReservationRule, dateToCompare );
289 if ( closestweeDef != null )
290 {
291
292 reservationRuleToApply = mapReservationRule.get( closestweeDef );
293
294 }
295
296 dayOfWeek = dateTemp.getDayOfWeek( );
297
298 workingDay = null;
299 if ( reservationRuleToApply != null )
300 {
301 workingDay = WorkingDayService.getWorkingDayOfDayOfWeek( reservationRuleToApply.getListWorkingDay( ), dayOfWeek );
302
303 }
304
305 if ( workingDay != null )
306 {
307 minTimeForThisDay = WorkingDayService.getMinStartingTimeOfAWorkingDay( workingDay );
308 maxTimeForThisDay = WorkingDayService.getMaxEndingTimeOfAWorkingDay( workingDay );
309
310 if ( !listDateOfClosingDay.contains( dateTemp ) )
311 {
312 timeTemp = minTimeForThisDay;
313 sumNbPotentialRemainingPlaces = 0;
314 sumNbRemainingPlaces = 0;
315 nbSlot = 0;
316 isChanged = true;
317 tempEndingDateTime = timeTemp;
318
319 while ( timeTemp.isBefore( maxTimeForThisDay ) || !timeTemp.equals( maxTimeForThisDay ) )
320 {
321
322
323 dateTimeTemp = dateTemp.atTime( timeTemp );
324
325 if ( isChanged )
326 {
327
328 startingDateTime = dateTimeTemp;
329 isChanged = false;
330 }
331 if ( mapSlot.containsKey( dateTimeTemp ) )
332 {
333 slotToAdd = mapSlot.get( dateTimeTemp );
334 timeTemp = slotToAdd.getEndingDateTime( ).toLocalTime( );
335
336 }
337 else
338 {
339
340 timeSlot = TimeSlotService.getTimeSlotInListOfTimeSlotWithStartingTime( workingDay.getListTimeSlot( ), timeTemp );
341 if ( timeSlot != null )
342 {
343 timeTemp = timeSlot.getEndingTime( );
344 int nMaxCapacityToPut = timeSlot.getMaxCapacity( );
345 slotToAdd = SlotService.buildSlot( nIdForm, new Period( dateTimeTemp, dateTemp.atTime( timeTemp ) ), nMaxCapacityToPut,
346 nMaxCapacityToPut, nMaxCapacityToPut, 0, timeSlot.getIsOpen( ), Boolean.FALSE );
347
348 }
349 else
350 {
351 break;
352 }
353 }
354
355 if ( isNewSlot( sumNbPotentialRemainingPlaces, nNbPlaces, slotToAdd, localDateTimeNow, isAllOpenSlot, nbSlot ) )
356 {
357
358 sumNbPotentialRemainingPlaces = 0;
359 nbSlot = 0;
360 sumNbRemainingPlaces = 0;
361 startingDateTime = slotToAdd.getEndingDateTime( );
362 tempEndingDateTime = slotToAdd.getEndingTime( );
363 }
364 else
365 {
366 if ( slotToAdd.getNbPotentialRemainingPlaces( ) <= 0 )
367 {
368 isfull = true;
369 }
370 sumNbPotentialRemainingPlaces = sumNbPotentialRemainingPlaces + 1;
371 nbSlot = nbSlot + 1;
372 sumNbRemainingPlaces = sumNbRemainingPlaces + 1;
373 }
374
375 if ( buildNewSlot( sumNbPotentialRemainingPlaces, nNbPlaces, isAllOpenSlot, nbSlot ) )
376 {
377
378 endingDateTime = slotToAdd.getEndingDateTime( );
379 Slotlugins/appointment/business/slot/Slot.html#Slot">Slot slt = new Slot( );
380 slt.setStartingDateTime( startingDateTime );
381 slt.setEndingDateTime( endingDateTime );
382 slt.setIsOpen( true );
383 slt.setNbPotentialRemainingPlaces( sumNbPotentialRemainingPlaces );
384 slt.setNbRemainingPlaces( sumNbRemainingPlaces );
385 slt.setDate( slotToAdd.getDate( ) );
386 slt.setIdForm( slotToAdd.getIdForm( ) );
387 slt.setIsFull( isfull ? 1 : 0 );
388 listSlotToShow.add( slt );
389 isChanged = true;
390 isfull = false;
391 timeTemp = tempEndingDateTime;
392 }
393
394 }
395 }
396 }
397
398 dateTemp = dateTemp.plusDays( 1 );
399 }
400 return listSlotToShow;
401
402 }
403
404 private static boolean isNewSlot( int sumNbPotentialRemainingPlaces, int nNbPlaces, Slot slotToAdd, LocalDateTime localDateTimeNow, boolean isAllOpenSlot,
405 int nbSlot )
406 {
407
408 if ( isAllOpenSlot )
409 {
410
411 return nbSlot == nNbPlaces || !slotToAdd.getIsOpen( ) || slotToAdd.getEndingDateTime( ).isBefore( localDateTimeNow );
412 }
413
414 return sumNbPotentialRemainingPlaces >= nNbPlaces || !slotToAdd.getIsOpen( ) || slotToAdd.getNbPotentialRemainingPlaces( ) <= 0
415 || slotToAdd.getEndingDateTime( ).isBefore( localDateTimeNow );
416 }
417
418 private static boolean buildNewSlot( int sumNbPotentialRemainingPlaces, int nNbPlaces, boolean isAllOpenSlot, int nbSlot )
419 {
420 if ( isAllOpenSlot )
421 {
422
423 return nbSlot == nNbPlaces;
424 }
425
426 return sumNbPotentialRemainingPlaces >= nNbPlaces;
427 }
428 }