From 9ef70ffee27247a9ea6ce3dc2b249d2d391b8f4d Mon Sep 17 00:00:00 2001 From: Muhimbura Brian Mart Date: Fri, 24 Nov 2023 18:24:57 +0300 Subject: [PATCH 1/2] Check meeting time when creating or editing a group --- .../GroupingTypesDataValidator.java | 3 ++ ...WritePlatformServiceJpaRepositoryImpl.java | 39 ++++++++++++++++++- 2 files changed, 41 insertions(+), 1 deletion(-) diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/group/serialization/GroupingTypesDataValidator.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/group/serialization/GroupingTypesDataValidator.java index 2222ae1bd20..7877cb2a696 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/group/serialization/GroupingTypesDataValidator.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/group/serialization/GroupingTypesDataValidator.java @@ -223,6 +223,9 @@ public void validateForCreateCenterGroup(final JsonCommand command) { final Long centerId = this.fromApiJsonHelper.extractLongNamed(GroupingTypesApiConstants.centerIdParamName, element); baseDataValidator.reset().parameter(GroupingTypesApiConstants.centerIdParamName).value(centerId).notNull().integerGreaterThanZero(); + final Long prequalificationId = this.fromApiJsonHelper.extractLongNamed(GroupingTypesApiConstants.prequalificationId, element); + baseDataValidator.reset().parameter(GroupingTypesApiConstants.prequalificationId).value(prequalificationId).notNull(); + // office is inherited from center final Long officeId = this.fromApiJsonHelper.extractLongNamed(GroupingTypesApiConstants.officeIdParamName, element); baseDataValidator.reset().parameter(GroupingTypesApiConstants.officeIdParamName).value(officeId).notNull().integerGreaterThanZero(); diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/group/service/GroupingTypesWritePlatformServiceJpaRepositoryImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/group/service/GroupingTypesWritePlatformServiceJpaRepositoryImpl.java index eb546eb8b98..aff3e7accfb 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/group/service/GroupingTypesWritePlatformServiceJpaRepositoryImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/group/service/GroupingTypesWritePlatformServiceJpaRepositoryImpl.java @@ -247,6 +247,22 @@ private CommandProcessingResult createGroupingType(final JsonCommand command, fi LocalTime newMeetingEndTime = newMeetingStarTime.plusMinutes(meetingDefaultDuration).plusMinutes(timeBetweenMeetings); meetingEndTime = newMeetingEndTime; + + if (centerId !=null){ + String schemaSql = "select cgroup.id from m_group cgroup where cgroup.parent_id = ? and " + + "( ( ? >= cgroup.meeting_start_time and ? < cgroup.meeting_end_time) OR " + + "( ? > cgroup.meeting_start_time and ? < cgroup.meeting_end_time) ) order by id desc"; + List groupIds = jdbcTemplate.queryForList(schemaSql, Long.class, centerId, meetingStartTime, meetingStartTime, + meetingEndTime, meetingEndTime); + + if (groupIds.size() > 0) { + Long groupId = groupIds.get(0); + GroupGeneralData existingGroup = this.groupReadPlatformService.retrieveOne(groupId); + + throw new GroupMeetingTimeCollisionException(existingGroup.getName(), existingGroup.getId(), meetingStartTime, meetingEndTime); + } + } + } // new custom fields for center @@ -531,6 +547,27 @@ private CommandProcessingResult updateGroupingType(final Long groupId, final Jso this.groupPrequalificationRelationshipRepository.save(relationship); } + Group parent = groupForUpdate.getParent(); + if (actualChanges.containsKey(GroupingTypesApiConstants.meetingStartTime)) { + + if (parent !=null){ + String schemaSql = "select cgroup.id from m_group cgroup where cgroup.parent_id = ? and " + + "( ( ? >= cgroup.meeting_start_time and ? < cgroup.meeting_end_time) OR " + + "( ? > cgroup.meeting_start_time and ? < cgroup.meeting_end_time) ) order by id desc"; + LocalTime meetingEndTime = groupForUpdate.getMeetingEndTime(); + LocalTime meetingStartTime = groupForUpdate.getMeetingStartTime(); + List groupIds = jdbcTemplate.queryForList(schemaSql, Long.class, parent.getId(), meetingStartTime, meetingStartTime, + meetingEndTime, meetingEndTime); + + if (groupIds.size() > 0) { + Long existingGroupId = groupIds.get(0); + GroupGeneralData existingGroup = this.groupReadPlatformService.retrieveOne(existingGroupId); + + throw new GroupMeetingTimeCollisionException(existingGroup.getName(), existingGroup.getId(), meetingStartTime, meetingEndTime); + } + } + } + final GroupLevel groupLevel = this.groupLevelRepository.findById(groupForUpdate.getGroupLevel().getId()).orElse(null); if (groupingType == GroupTypes.CENTER) { @@ -563,7 +600,7 @@ private CommandProcessingResult updateGroupingType(final Long groupId, final Jso if (!groupLevel.isSuperParent()) { Long parentId = null; - final Group presentParentGroup = groupForUpdate.getParent(); + final Group presentParentGroup = parent; if (presentParentGroup != null) { parentId = presentParentGroup.getId(); From c9b239a1b6bd3f2e791e1bf834dd0d685105135f Mon Sep 17 00:00:00 2001 From: Muhimbura Brian Mart Date: Fri, 24 Nov 2023 19:29:26 +0300 Subject: [PATCH 2/2] Transfer group validations --- .../group/data/GroupGeneralData.java | 46 ++++++++++--------- .../service/AllGroupTypesDataMapper.java | 2 +- .../CenterReadPlatformServiceImpl.java | 4 +- .../service/LoanReadPlatformServiceImpl.java | 2 +- 4 files changed, 30 insertions(+), 24 deletions(-) diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/group/data/GroupGeneralData.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/group/data/GroupGeneralData.java index d06d3c819db..8ce994fdec8 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/group/data/GroupGeneralData.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/group/data/GroupGeneralData.java @@ -264,7 +264,7 @@ public static GroupGeneralData lookup(final Long groupId, final String accountNo final Collection closureReasons = null; return new GroupGeneralData(groupId, accountNo, groupName, null, null, null, null, null, null, null, null, null, null, null, clientMembers, null, null, null, null, null, groupRoles, null, null, null, null, closureReasons, null, null, null, null, - null, null, null, null); + null, null, null, null, null, null); } public static GroupGeneralData template(final Long officeId, final Long centerId, final String accountNo, final String centerName, @@ -281,7 +281,7 @@ public static GroupGeneralData template(final Long officeId, final Long centerId return new GroupGeneralData(null, accountNo, null, null, null, null, officeId, null, centerId, centerName, staffId, staffName, null, null, clientMembers, null, centerOptions, officeOptions, staffOptions, clientOptions, groupRoles, availableRoles, null, null, null, closureReasons, null, parentOfficesOptions, responsibleUserOptions, portfolioCenterOptions, - centerGroupLocations, null, null, null); + centerGroupLocations, null, null, null, null, null); } public static GroupGeneralData withTemplate(final GroupGeneralData templatedGrouping, final GroupGeneralData grouping) { @@ -293,7 +293,7 @@ public static GroupGeneralData withTemplate(final GroupGeneralData templatedGrou grouping.calendarsData, grouping.collectionMeetingCalendar, grouping.closureReasons, templatedGrouping.timeline, templatedGrouping.parentOfficesOptions, templatedGrouping.responsibleUserOptions, templatedGrouping.portfolioCenterOptions, templatedGrouping.centerGroupLocations, grouping.prequalificationNumber, grouping.prequalificationId, - grouping.prequalificationStatus); + grouping.prequalificationStatus, grouping.meetingStartTime, grouping.meetingEndTime); return mapDTO(grouping, ret); } @@ -335,15 +335,15 @@ public static GroupGeneralData withAssocations(final GroupGeneralData grouping, grouping.selectedRole, calendarsData, collectionMeetingCalendar, grouping.closureReasons, grouping.timeline, grouping.parentOfficesOptions, grouping.responsibleUserOptions, grouping.portfolioCenterOptions, grouping.centerGroupLocations, grouping.prequalificationNumber, grouping.prequalificationId, - grouping.prequalificationStatus); + grouping.prequalificationStatus, grouping.meetingStartTime, grouping.meetingEndTime); return mapDTO(grouping, ret); } public static GroupGeneralData instance(final Long id, final String accountNo, final String name, final String externalId, - final EnumOptionData status, final LocalDate activationDate, final Long officeId, final String officeName, final Long centerId, - final String centerName, final Long staffId, final String staffName, final String hierarchy, final String groupLevel, - final GroupTimelineData timeline) { + final EnumOptionData status, final LocalDate activationDate, final Long officeId, final String officeName, final Long centerId, + final String centerName, final Long staffId, final String staffName, final String hierarchy, final String groupLevel, + final GroupTimelineData timeline, LocalTime meetingStartTime, LocalTime meetingEndTime) { final Collection clientMembers = null; final Collection activeClientMembers = null; @@ -365,21 +365,22 @@ public static GroupGeneralData instance(final Long id, final String accountNo, f return new GroupGeneralData(id, accountNo, name, externalId, status, activationDate, officeId, officeName, centerId, centerName, staffId, staffName, hierarchy, groupLevel, clientMembers, activeClientMembers, centerOptions, officeOptions, staffOptions, clientOptions, groupRoles, availableRoles, role, calendarsData, collectionMeetingCalendar, closureReasons, timeline, - parentOfficesOptions, responsibleUserOptions, portfolioCenterOptions, centerGroupLocations, null, null, null); + parentOfficesOptions, responsibleUserOptions, portfolioCenterOptions, centerGroupLocations, + null, null, null, meetingStartTime, meetingEndTime); } private GroupGeneralData(final Long id, final String accountNo, final String name, final String externalId, final EnumOptionData status, - final LocalDate activationDate, final Long officeId, final String officeName, final Long centerId, final String centerName, - final Long staffId, final String staffName, final String hierarchy, final String groupLevel, - final Collection clientMembers, final Collection activeClientMembers, - final Collection centerOptions, final Collection officeOptions, - final Collection staffOptions, final Collection clientOptions, - final Collection groupRoles, final Collection availableRoles, final GroupRoleData role, - final Collection calendarsData, final CalendarData collectionMeetingCalendar, - final Collection closureReasons, final GroupTimelineData timeline, - final Collection parentOfficesOptions, final Collection responsibleUserOptions, - final Collection portfolioCenterOptions, Collection centerGroupLocations, - String prequalificationNumber, Long prequalificationId, EnumOptionData prequalificationStatus) { + final LocalDate activationDate, final Long officeId, final String officeName, final Long centerId, final String centerName, + final Long staffId, final String staffName, final String hierarchy, final String groupLevel, + final Collection clientMembers, final Collection activeClientMembers, + final Collection centerOptions, final Collection officeOptions, + final Collection staffOptions, final Collection clientOptions, + final Collection groupRoles, final Collection availableRoles, final GroupRoleData role, + final Collection calendarsData, final CalendarData collectionMeetingCalendar, + final Collection closureReasons, final GroupTimelineData timeline, + final Collection parentOfficesOptions, final Collection responsibleUserOptions, + final Collection portfolioCenterOptions, Collection centerGroupLocations, + String prequalificationNumber, Long prequalificationId, EnumOptionData prequalificationStatus, LocalTime meetingStartTime, LocalTime meetingEndTime) { this.id = id; this.accountNo = accountNo; this.name = name; @@ -428,6 +429,8 @@ private GroupGeneralData(final Long id, final String accountNo, final String nam this.prequalificationNumber = prequalificationNumber; this.prequalificationStatus = prequalificationStatus; this.prequalificationId = prequalificationId; + this.meetingStartTime = meetingStartTime; + this.meetingEndTime = meetingEndTime; } public Long getId() { @@ -465,7 +468,7 @@ public static GroupGeneralData updateSelectedRole(final GroupGeneralData groupin grouping.centerOptions, grouping.officeOptions, grouping.staffOptions, grouping.clientOptions, grouping.groupRoles, grouping.availableRoles, selectedRole, grouping.calendarsData, grouping.collectionMeetingCalendar, grouping.closureReasons, null, null, null, null, null, grouping.prequalificationNumber, grouping.prequalificationId, - grouping.prequalificationStatus); + grouping.prequalificationStatus, grouping.meetingStartTime, grouping.meetingEndTime); } public static GroupGeneralData withClosureReasons(final Collection closureReasons) { @@ -502,7 +505,8 @@ public static GroupGeneralData withClosureReasons(final Collection clientMembers() { diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/group/service/AllGroupTypesDataMapper.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/group/service/AllGroupTypesDataMapper.java index fedb0a9f8fd..6ecd7766992 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/group/service/AllGroupTypesDataMapper.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/group/service/AllGroupTypesDataMapper.java @@ -192,7 +192,7 @@ public GroupGeneralData mapRow(final ResultSet rs, @SuppressWarnings("unused") f closedByUsername, closedByFirstname, closedByLastname); GroupGeneralData ret = GroupGeneralData.instance(id, accountNo, name, externalId, status, activationDate, officeId, officeName, - centerId, centerName, staffId, staffName, hierarchy, groupLevel, timeline); + centerId, centerName, staffId, staffName, hierarchy, groupLevel, timeline, meetingStartTime, meetingEndTime); // set the remaining fields for group general data ret.setLegacyNumber(legacyNumber); diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/group/service/CenterReadPlatformServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/group/service/CenterReadPlatformServiceImpl.java index c977b18ffb0..0fa38ee7923 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/group/service/CenterReadPlatformServiceImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/group/service/CenterReadPlatformServiceImpl.java @@ -414,13 +414,15 @@ public GroupGeneralData mapRow(final ResultSet rs, @SuppressWarnings("unused") f final String activatedByUsername = rs.getString("activatedByUsername"); final String activatedByFirstname = rs.getString("activatedByFirstname"); final String activatedByLastname = rs.getString("activatedByLastname"); + final LocalTime meetingStartTime = JdbcSupport.getLocalTime(rs, "meetingStartTime"); + final LocalTime meetingEndTime = JdbcSupport.getLocalTime(rs, "meetingEndTime"); final GroupTimelineData timeline = new GroupTimelineData(submittedOnDate, submittedByUsername, submittedByFirstname, submittedByLastname, activationDate, activatedByUsername, activatedByFirstname, activatedByLastname, closedOnDate, closedByUsername, closedByFirstname, closedByLastname); return GroupGeneralData.instance(id, accountNo, name, externalId, status, activationDate, officeId, officeName, null, null, - staffId, staffName, hierarchy, groupLevel, timeline); + staffId, staffName, hierarchy, groupLevel, timeline, meetingStartTime,meetingEndTime); } } diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanReadPlatformServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanReadPlatformServiceImpl.java index 3b44816879e..2166be33a39 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanReadPlatformServiceImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanReadPlatformServiceImpl.java @@ -1021,7 +1021,7 @@ public LoanAccountData mapRow(final ResultSet rs, @SuppressWarnings("unused") fi final EnumOptionData groupStatus = ClientEnumerations.status(groupStatusEnum); final LocalDate activationDate = JdbcSupport.getLocalDate(rs, "activationDate"); groupData = GroupGeneralData.instance(groupId, groupAccountNo, groupName, groupExternalId, groupStatus, activationDate, - groupOfficeId, null, groupParentId, centerName, groupStaffId, null, groupHierarchy, groupLevel, null); + groupOfficeId, null, groupParentId, centerName, groupStaffId, null, groupHierarchy, groupLevel, null, null, null); } final Integer loanCounter = JdbcSupport.getInteger(rs, "loanCounter");