diff --git a/src/main/java/com/primefactorsolutions/model/Vacation.java b/src/main/java/com/primefactorsolutions/model/Vacation.java index 9f7de1c..7714c3e 100644 --- a/src/main/java/com/primefactorsolutions/model/Vacation.java +++ b/src/main/java/com/primefactorsolutions/model/Vacation.java @@ -8,8 +8,6 @@ import lombok.Data; import lombok.EqualsAndHashCode; import lombok.NoArgsConstructor; -import java.time.LocalDate; - @Data @Entity @AllArgsConstructor @@ -18,7 +16,8 @@ import java.time.LocalDate; public class Vacation extends BaseEntity { @Enumerated(EnumType.STRING) private TimeOffRequestType category; - private LocalDate vacationDate; + private Integer monthOfYear; + private Integer dayOfMonth; private Double duration; private Double expiration; @Enumerated(EnumType.STRING) diff --git a/src/main/java/com/primefactorsolutions/views/RequestEmployeeView.java b/src/main/java/com/primefactorsolutions/views/RequestEmployeeView.java index 1408b57..f1ca462 100644 --- a/src/main/java/com/primefactorsolutions/views/RequestEmployeeView.java +++ b/src/main/java/com/primefactorsolutions/views/RequestEmployeeView.java @@ -34,7 +34,6 @@ public class RequestEmployeeView extends Div implements HasUrlParameter private final TimeOffRequestService requestService; private final EmployeeService employeeService; private final Grid requestGrid = new Grid<>(TimeOffRequest.class); - private final Grid summaryGrid = new Grid<>(); private List requests = Collections.emptyList(); private ComboBox categoryFilter; private ComboBox stateFilter; @@ -49,8 +48,7 @@ public class RequestEmployeeView extends Div implements HasUrlParameter private void initializeView() { setupFilters(); setupGrid(); - setupSummaryGrid(); - add(requestGrid, createActionButtons(), summaryGrid); + add(requestGrid, createActionButtons()); refreshRequestGrid(null, null); } @@ -93,31 +91,6 @@ public class RequestEmployeeView extends Div implements HasUrlParameter }); } - private void setupSummaryGrid() { - summaryGrid.addColumn(this::getCategory).setHeader("Category"); - summaryGrid.addColumn(this::getStatus).setHeader("Available"); - summaryGrid.addColumn(this::getTotalRequests).setHeader("Expiration"); - summaryGrid.addColumn(this::getTotalDays).setHeader("Taken"); - summaryGrid.addColumn(this::getTotalDays).setHeader("Balance"); - summaryGrid.setAllRowsVisible(true); - } - - private Object getTotalDays(final Vacation vacation) { - return null; - } - - private Object getTotalRequests(final Vacation vacation) { - return null; - } - - private Object getStatus(final Vacation vacation) { - return null; - } - - private Object getCategory(final Vacation vacation) { - return vacation.getCategory(); - } - private HorizontalLayout createActionButtons() { Button viewButton = new Button("View", event -> { if (request != null) { diff --git a/src/main/java/com/primefactorsolutions/views/RequestRegisterView.java b/src/main/java/com/primefactorsolutions/views/RequestRegisterView.java index 8d50167..1176231 100644 --- a/src/main/java/com/primefactorsolutions/views/RequestRegisterView.java +++ b/src/main/java/com/primefactorsolutions/views/RequestRegisterView.java @@ -21,8 +21,10 @@ import org.springframework.context.annotation.Scope; import java.time.LocalDate; import java.time.temporal.ChronoUnit; import java.util.Arrays; +import java.util.Comparator; import java.util.List; import java.util.UUID; +import java.util.stream.Collectors; @SpringComponent @PermitAll @@ -122,36 +124,46 @@ public class RequestRegisterView extends VerticalLayout { private void filterCategories(final Employee employee) { List employeeRequests = requestService.findRequestsByEmployeeId(employee.getId()); - List requestedCategories = employeeRequests.stream() - .filter(request -> request.getDaysBalance() <= 0) - .map(TimeOffRequest::getCategory) - .toList(); - List availableCategories = Arrays.stream(TimeOffRequestType.values()) - .filter(category -> !requestedCategories.contains(category) - || employeeRequests.stream() - .anyMatch(req -> req.getCategory() == category - && req.getState() == TimeOffRequestStatus.EXPIRED)) - .filter(category -> { - if (employee.getGender() == Employee.Gender.MALE) { - return category != TimeOffRequestType.MATERNITY - && category != TimeOffRequestType.MOTHERS_DAY - && category != TimeOffRequestType.INTERNATIONAL_WOMENS_DAY - && category != TimeOffRequestType.NATIONAL_WOMENS_DAY; - } else { - return category != TimeOffRequestType.FATHERS_DAY - && category != TimeOffRequestType.PATERNITY; - } - }) + List allCategories = Arrays.asList(TimeOffRequestType.values()); + List availableCategories = allCategories.stream() + .filter(category -> isCategoryAvailable(employeeRequests, category)) + .filter(category -> isCategoryAllowedByGender(category, employee.getGender())) .toList(); categoryComboBox.setItems(availableCategories); } + private boolean isCategoryAvailable(List employeeRequests, TimeOffRequestType category) { + List requestsByCategory = employeeRequests.stream() + .filter(request -> request.getCategory() == category) + .toList(); + + if (requestsByCategory.isEmpty()) { + return true; + } + + TimeOffRequest latestRequest = requestsByCategory.stream() + .max(Comparator.comparing(TimeOffRequest::getStartDate)) + .orElse(null); + + return latestRequest.getState() == TimeOffRequestStatus.EXPIRED; + } + + private boolean isCategoryAllowedByGender(TimeOffRequestType category, Employee.Gender gender) { + if (gender == Employee.Gender.MALE) { + return category != TimeOffRequestType.MATERNITY + && category != TimeOffRequestType.MOTHERS_DAY + && category != TimeOffRequestType.INTERNATIONAL_WOMENS_DAY + && category != TimeOffRequestType.NATIONAL_WOMENS_DAY; + } else { + return category != TimeOffRequestType.FATHERS_DAY + && category != TimeOffRequestType.PATERNITY; + } + } + private void handleCategorySelection(final TimeOffRequestType selectedCategory) { - clearForm(); if (selectedCategory != null) { updateAvailableDays(selectedCategory); startDatePicker.setEnabled(true); - endDatePicker.setEnabled(true); } } @@ -184,8 +196,8 @@ public class RequestRegisterView extends VerticalLayout { private void setDatePickerLimits(final Vacation vacation) { LocalDate startDate; - if (vacation.getVacationDate() != null) { - startDate = vacation.getVacationDate(); + if (vacation.getMonthOfYear() != null && vacation.getDayOfMonth() != null) { + startDate = LocalDate.of(LocalDate.now().getYear(), vacation.getMonthOfYear(), vacation.getDayOfMonth()); endDate = startDate.plusDays(vacation.getExpiration().intValue() - 1); startDatePicker.setValue(startDate); endDatePicker.setValue(startDate.plusDays(vacation.getDuration().intValue() - 1)); @@ -209,19 +221,12 @@ public class RequestRegisterView extends VerticalLayout { private void updateDatePickerMinValues() { LocalDate startDate = startDatePicker.getValue(); - if (vacation.getVacationDate() == null) { - endDate = startDate.plusDays(vacation.getExpiration().intValue() - 1); - } - if (startDate != null) { - endDatePicker.setMin(startDate); - endDatePicker.setMax(startDate.plusDays(vacation.getExpiration().intValue() - 1)); - if (vacation.getDuration() == 0.5) { - endDatePicker.setValue(startDate.plusDays(0)); - } else { - endDatePicker.setValue(startDate.plusDays(vacation.getDuration().intValue() - 1)); - } - calculateDays(); + if (vacation.getDuration() == 0.5) { + endDatePicker.setValue(startDate.plusDays(0)); + } else { + endDatePicker.setValue(startDate.plusDays(vacation.getDuration().intValue() - 1)); } + calculateDays(); } private void calculateDays() { @@ -230,11 +235,6 @@ public class RequestRegisterView extends VerticalLayout { Double availableDays = availableDaysField.getValue(); if (startDate != null && endDate != null) { - if (startDate.isAfter(endDate)) { - endDatePicker.clear(); - return; - } - double daysToBeTaken = java.time.temporal.ChronoUnit.DAYS.between(startDate, endDate) + 1; if (daysToBeTaken == 1 && vacation.getDuration() == 0.5) { daysToBeTaken = 0.5; @@ -244,22 +244,8 @@ public class RequestRegisterView extends VerticalLayout { } else { daysToBeTakenField.setValue(daysToBeTaken); } - double balanceDays = availableDays - daysToBeTaken; - if (vacation.getCategory() == TimeOffRequestType.HEALTH_PERMIT && daysToBeTaken > 1) { - endDatePicker.clear(); - daysToBeTakenField.clear(); - balanceDaysField.clear(); - } else if (vacation.getCategory() == TimeOffRequestType.HEALTH_PERMIT && daysToBeTaken == 1) { - balanceDays = availableDays - 0.5; - balanceDaysField.setValue(balanceDays); - } else if (balanceDays < 0) { - endDatePicker.clear(); - daysToBeTakenField.clear(); - balanceDaysField.clear(); - } else { - balanceDaysField.setValue(balanceDays); - } + balanceDaysField.setValue(balanceDays); } } @@ -291,6 +277,12 @@ public class RequestRegisterView extends VerticalLayout { } else if (request.getExpiration() == null) { request.setExpiration(startDatePicker.getValue().plusDays(vacation.getExpiration().intValue() - 1)); } + List existingRequests = requestService.findByEmployeeAndCategory(employee.getId(), request.getCategory()); + + if (existingRequests.size() >= 2) { + existingRequests.stream().min(Comparator.comparing(TimeOffRequest::getStartDate)).ifPresent(oldestRequest -> requestService.deleteTimeOffRequest(oldestRequest.getId())); + + } request.setState(TimeOffRequestStatus.REQUESTED); updateBalanceForCategory(request); requestService.saveTimeOffRequest(request); diff --git a/src/main/java/com/primefactorsolutions/views/RequestsListView.java b/src/main/java/com/primefactorsolutions/views/RequestsListView.java index f111c59..d5c9136 100644 --- a/src/main/java/com/primefactorsolutions/views/RequestsListView.java +++ b/src/main/java/com/primefactorsolutions/views/RequestsListView.java @@ -70,8 +70,6 @@ public class RequestsListView extends Main { requestGrid.addColumn(this::getEmployeeStatus).setHeader("Employee State"); requestGrid.addColumn(this::getCategory).setHeader("Category"); requestGrid.addColumn(this::getState).setHeader("Request Status"); - requestGrid.addColumn(this::getStartDate).setHeader("Start Date"); - requestGrid.addColumn(this::getEndDate).setHeader("End Date"); requestGrid.addColumn(this::getDaysBalance).setHeader("Balance"); requestGrid.setPaginationBarMode(PagingGrid.PaginationBarMode.BOTTOM); @@ -179,14 +177,6 @@ public class RequestsListView extends Main { return request.getState().toString(); } - private String getStartDate(final TimeOffRequest request) { - return request.getStartDate().toString(); - } - - private String getEndDate(final TimeOffRequest request) { - return request.getEndDate().toString(); - } - private String getDaysBalance(final TimeOffRequest request) { return request.getDaysBalance().toString(); } diff --git a/src/main/resources/data.sql b/src/main/resources/data.sql index e783e3a..a09d9cd 100644 --- a/src/main/resources/data.sql +++ b/src/main/resources/data.sql @@ -16,30 +16,30 @@ INSERT INTO team (id, version, name) VALUES ('c3a8a7b1-f2d9-48c0-86ea-f215c2e6b3 INSERT INTO team (id, version, name) VALUES ('8f6b61e7-efb2-4de7-b8ed-7438c9d8babe', 1, 'GHI'); -INSERT INTO vacation (id, version, category, vacation_date, duration, expiration, type) VALUES ('123e4567-e89b-12d3-a456-426614174000', 1, 'NEW_YEAR', '2024-01-01', 1, 1, 'FIXED'); -INSERT INTO vacation (id, version, category, vacation_date, duration, expiration, type) VALUES ('223e4567-e89b-12d3-a456-426614174001', 1, 'MONDAY_CARNIVAL', '2024-02-12', 1, 1, 'FIXED'); -INSERT INTO vacation (id, version, category, vacation_date, duration, expiration, type) VALUES ('323e4567-e89b-12d3-a456-426614174002', 1, 'TUESDAY_CARNIVAL', '2024-02-13', 1, 1, 'FIXED'); -INSERT INTO vacation (id, version, category, vacation_date, duration, expiration, type) VALUES ('423e4567-e89b-12d3-a456-426614174003', 1, 'GOOD_FRIDAY', '2024-03-29', 1, 1, 'FIXED'); -INSERT INTO vacation (id, version, category, vacation_date, duration, expiration, type) VALUES ('523e4567-e89b-12d3-a456-426614174004', 1, 'LABOR_DAY', '2024-05-01', 1, 1, 'FIXED'); -INSERT INTO vacation (id, version, category, vacation_date, duration, expiration, type) VALUES ('623e4567-e89b-12d3-a456-426614174005', 1, 'INDEPENDENCE_DAY', '2024-08-06', 1, 1, 'FIXED'); -INSERT INTO vacation (id, version, category, vacation_date, duration, expiration, type) VALUES ('723e4567-e89b-12d3-a456-426614174006', 1, 'CHRISTMAS', '2024-12-25', 1, 1, 'FIXED'); +INSERT INTO vacation (id, version, category, month_of_year, day_of_month, duration, expiration, type) VALUES ('123e4567-e89b-12d3-a456-426614174000', 1, 'NEW_YEAR', 1, 1, 1, 1, 'FIXED'); +INSERT INTO vacation (id, version, category, month_of_year, day_of_month, duration, expiration, type) VALUES ('223e4567-e89b-12d3-a456-426614174001', 1, 'MONDAY_CARNIVAL', 2, 12, 1, 1, 'FIXED'); +INSERT INTO vacation (id, version, category, month_of_year, day_of_month, duration, expiration, type) VALUES ('323e4567-e89b-12d3-a456-426614174002', 1, 'TUESDAY_CARNIVAL', 2, 13, 1, 1, 'FIXED'); +INSERT INTO vacation (id, version, category, month_of_year, day_of_month, duration, expiration, type) VALUES ('423e4567-e89b-12d3-a456-426614174003', 1, 'GOOD_FRIDAY', 3, 29, 1, 1, 'FIXED'); +INSERT INTO vacation (id, version, category, month_of_year, day_of_month, duration, expiration, type) VALUES ('523e4567-e89b-12d3-a456-426614174004', 1, 'LABOR_DAY', 5, 1, 1, 1, 'FIXED'); +INSERT INTO vacation (id, version, category, month_of_year, day_of_month, duration, expiration, type) VALUES ('623e4567-e89b-12d3-a456-426614174005', 1, 'INDEPENDENCE_DAY', 8, 6, 1, 1, 'FIXED'); +INSERT INTO vacation (id, version, category, month_of_year, day_of_month, duration, expiration, type) VALUES ('723e4567-e89b-12d3-a456-426614174006', 1, 'CHRISTMAS', 12, 25, 1, 1, 'FIXED'); -INSERT INTO vacation (id, version, category, vacation_date, duration, expiration, type) VALUES ('823e4567-e89b-12d3-a456-426614174007', 1, 'PRURINATIONAL_STATE_DAY', '2024-01-21', 1, 30, 'MOVABLE'); -INSERT INTO vacation (id, version, category, vacation_date, duration, expiration, type) VALUES ('923e4567-e89b-12d3-a456-426614174008', 1, 'CORPUS_CHRISTI', '2024-05-30', 1, 30, 'MOVABLE'); -INSERT INTO vacation (id, version, category, vacation_date, duration, expiration, type) VALUES ('a23e4567-e89b-12d3-a456-426614174009', 1, 'ANDEAN_NEW_YEAR', '2024-06-21', 1, 30, 'MOVABLE'); -INSERT INTO vacation (id, version, category, vacation_date, duration, expiration, type) VALUES ('b23e4567-e89b-12d3-a456-42661417400a', 1, 'DEPARTMENTAL_ANNIVERSARY', '2024-09-14', 1, 30, 'MOVABLE'); -INSERT INTO vacation (id, version, category, vacation_date, duration, expiration, type) VALUES ('c23e4567-e89b-12d3-a456-42661417400b', 1, 'ALL_SOULS_DAY', '2024-11-02', 1, 30, 'MOVABLE'); +INSERT INTO vacation (id, version, category, month_of_year, day_of_month, duration, expiration, type) VALUES ('823e4567-e89b-12d3-a456-426614174007', 1, 'PRURINATIONAL_STATE_DAY', 1, 21, 1, 30, 'MOVABLE'); +INSERT INTO vacation (id, version, category, month_of_year, day_of_month, duration, expiration, type) VALUES ('923e4567-e89b-12d3-a456-426614174008', 1, 'CORPUS_CHRISTI', 5, 30, 1, 30, 'MOVABLE'); +INSERT INTO vacation (id, version, category, month_of_year, day_of_month, duration, expiration, type) VALUES ('a23e4567-e89b-12d3-a456-426614174009', 1, 'ANDEAN_NEW_YEAR', 6, 21, 1, 30, 'MOVABLE'); +INSERT INTO vacation (id, version, category, month_of_year, day_of_month, duration, expiration, type) VALUES ('b23e4567-e89b-12d3-a456-42661417400a', 1, 'DEPARTMENTAL_ANNIVERSARY', 9, 14, 1, 30, 'MOVABLE'); +INSERT INTO vacation (id, version, category, month_of_year, day_of_month, duration, expiration, type) VALUES ('c23e4567-e89b-12d3-a456-42661417400b', 1, 'ALL_SOULS_DAY', 11, 2, 1, 30, 'MOVABLE'); INSERT INTO vacation (id, version, category, duration, expiration, type) VALUES ('c23e4567-e89b-12d3-a456-42661417400c', 1, 'BIRTHDAY', 0.5, 365, 'OTHER'); INSERT INTO vacation (id, version, category, duration, expiration, type) VALUES ('c23e4567-e89b-12d3-a456-42661417400d', 1, 'MATERNITY', 90, 90, 'OTHER'); INSERT INTO vacation (id, version, category, duration, expiration, type) VALUES ('c23e4567-e89b-12d3-a456-42661417400e', 1, 'PATERNITY', 3, 3, 'OTHER'); INSERT INTO vacation (id, version, category, duration, expiration, type) VALUES ('c23e4567-e89b-12d3-a456-42661417400f', 1, 'MARRIAGE', 3, 3, 'OTHER'); -INSERT INTO vacation (id, version, category, vacation_date, duration, expiration, type) VALUES ('c23e4567-e89b-12d3-a456-42661417401a', 1, 'FATHERS_DAY', '2024-03-19', 0.5, 30, 'OTHER'); -INSERT INTO vacation (id, version, category, vacation_date, duration, expiration, type) VALUES ('c23e4567-e89b-12d3-a456-42661417401b', 1, 'MOTHERS_DAY', '2024-05-27', 0.5, 30, 'OTHER'); -INSERT INTO vacation (id, version, category, vacation_date, duration, expiration, type) VALUES ('c23e4567-e89b-12d3-a456-42661417401c', 1, 'INTERNATIONAL_WOMENS_DAY', '2024-03-08', 0.5, 30, 'OTHER'); -INSERT INTO vacation (id, version, category, vacation_date, duration, expiration, type) VALUES ('c23e4567-e89b-12d3-a456-42661417401d', 1, 'NATIONAL_WOMENS_DAY', '2024-10-11', 0.5, 30, 'OTHER'); +INSERT INTO vacation (id, version, category, month_of_year, day_of_month, duration, expiration, type) VALUES ('c23e4567-e89b-12d3-a456-42661417401a', 1, 'FATHERS_DAY', 3, 19, 0.5, 30, 'OTHER'); +INSERT INTO vacation (id, version, category, month_of_year, day_of_month, duration, expiration, type) VALUES ('c23e4567-e89b-12d3-a456-42661417401b', 1, 'MOTHERS_DAY', 5, 27, 0.5, 30, 'OTHER'); +INSERT INTO vacation (id, version, category, month_of_year, day_of_month, duration, expiration, type) VALUES ('c23e4567-e89b-12d3-a456-42661417401c', 1, 'INTERNATIONAL_WOMENS_DAY', 3, 8, 0.5, 30, 'OTHER'); +INSERT INTO vacation (id, version, category, month_of_year, day_of_month, duration, expiration, type) VALUES ('c23e4567-e89b-12d3-a456-42661417401d', 1, 'NATIONAL_WOMENS_DAY', 10, 11, 0.5, 30, 'OTHER'); INSERT INTO vacation (id, version, category, duration, type) VALUES ('c23e4567-e89b-12d3-a456-42661417401e', 1, 'HEALTH_PERMIT', 2, 'OTHER'); INSERT INTO vacation (id, version, category, expiration, type) VALUES ('490e5fbe-895b-42f8-b914-95437f7b39c0', 1, 'VACATION_CURRENT_MANAGEMENT', 730, 'OTHER'); INSERT INTO vacation (id, version, category, expiration, type) VALUES ('c23e4567-e89b-12d3-a456-4266141740ff', 1, 'VACATION_PREVIOUS_MANAGEMENT', 730, 'OTHER'); @@ -66,7 +66,18 @@ insert into employee (id, version, username, first_name, last_name, status, team insert into time_off_request (id, version, employee_id, category, state, available_days, expiration, start_date, end_date, days_to_be_take, days_balance) -values ('9d6f12ba-e341-4e7a-b8a6-cab0982bd8c1', 1, '5c6f11fe-c341-4be7-a9a6-bba0081ad7c6', 'PATERNITY', 'TAKEN', 15, '2025-12-31', '2024-10-01', '2024-10-10', 5, 10); +values ('9d6f12ba-e341-4e7a-b8a6-cab0982bd8c1', 1, '5c6f11fe-c341-4be7-a9a6-bba0081ad7c6', 'PATERNITY', 'TAKEN', 0.5, '2025-12-31', '2024-10-01', '2024-10-10', 0.5, 0); +insert into time_off_request (id, version, employee_id, category, state, available_days, expiration, start_date, end_date, days_to_be_take, days_balance) +values ('9a6f12ba-e111-4e7a-b8a6-caa0982bd8a1', 1, '5c6f11fe-c341-4be7-a9a6-bba0081ad7c6', 'NEW_YEAR', 'EXPIRED', 1, '2024-01-01', '2023-12-31', '2024-01-01', 1, 0); +insert into time_off_request (id, version, employee_id, category, state, available_days, expiration, start_date, end_date, days_to_be_take, days_balance) +values ('9b6f12ba-e222-4e7a-b8a6-caa0982bd8b2', 1, '5c6f11fe-c341-4be7-a9a6-bba0081ad7c6', 'MONDAY_CARNIVAL', 'APPROVED', 1, '2025-02-12', '2024-02-12', '2024-02-12', 1, 0); +insert into time_off_request (id, version, employee_id, category, state, available_days, expiration, start_date, end_date, days_to_be_take, days_balance) +values ('9c6f12ba-e333-4e7a-b8a6-caa0982bd8c3', 1, '5c6f11fe-c341-4be7-a9a6-bba0081ad7c6', 'TUESDAY_CARNIVAL', 'UNDER_REVIEW', 1, '2025-02-13', '2024-02-13', '2024-02-13', 1, 0); +insert into time_off_request (id, version, employee_id, category, state, available_days, expiration, start_date, end_date, days_to_be_take, days_balance) +values ('9d6f12ba-e444-4e7a-b8a6-caa0982bd8d4', 1, '5c6f11fe-c341-4be7-a9a6-bba0081ad7c6', 'GOOD_FRIDAY', 'COMPLETED', 1, '2024-03-29', '2024-03-28', '2024-03-29', 1, 0); +insert into time_off_request (id, version, employee_id, category, state, available_days, expiration, start_date, end_date, days_to_be_take, days_balance) +values ('9e6f12ba-e555-4e7a-b8a6-caa0982bd8e5', 1, '5c6f11fe-c341-4be7-a9a6-bba0081ad7c6', 'LABOR_DAY', 'REJECTED', 1, '2025-05-01', '2024-05-01', '2024-05-01', 1, 0); + insert into time_off_request (id, version, employee_id, category, state, available_days, expiration, start_date, end_date, days_to_be_take, days_balance) values ('2fa314bc-f547-4b12-a8b6-bb789feabc12', 1, '19b5a76e-d7b1-4b76-8b02-4d0748e85809', 'BIRTHDAY', 'APPROVED', 15, '2025-12-31', '2024-12-01', '2024-12-15', 7, 8); insert into time_off_request (id, version, employee_id, category, state, available_days, expiration, start_date, end_date, days_to_be_take, days_balance)