Skip to content

Commit 1b2a5ff

Browse files
committed
AMP-31085: Bulk delete for orgs
Resolve activity delete issue
1 parent a4382b8 commit 1b2a5ff

5 files changed

Lines changed: 154 additions & 1 deletion

File tree

amp/src/main/java/org/digijava/module/aim/action/OrganisationManager.java

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,19 @@
66
import org.apache.struts.action.ActionForm;
77
import org.apache.struts.action.ActionForward;
88
import org.apache.struts.action.ActionMapping;
9+
import org.apache.struts.action.ActionMessage;
10+
import org.apache.struts.action.ActionMessages;
911
import org.digijava.module.aim.dbentity.AmpOrganisation;
12+
import org.digijava.module.aim.dbentity.AmpTeam;
1013
import org.digijava.module.aim.form.OrgManagerForm;
1114
import org.digijava.module.aim.helper.TeamMember;
15+
import org.digijava.module.aim.util.ActivityUtil;
1216
import org.digijava.module.aim.util.DbUtil;
17+
import org.digijava.module.aim.util.TeamUtil;
1318
import org.digijava.module.calendar.util.AmpUtil;
19+
import org.hibernate.JDBCException;
1420

21+
import javax.servlet.http.HttpServletRequest;
1522
import javax.servlet.http.HttpSession;
1623
import java.util.*;
1724

@@ -50,6 +57,9 @@ public ActionForward execute(ActionMapping mapping, ActionForm form,
5057

5158
OrgManagerForm eaForm = (OrgManagerForm) form;
5259
eaForm.setAdminSide(isAdmin);
60+
if (isAdmin && "true".equals(request.getParameter("deleteSelectedOrgs"))) {
61+
deleteSelectedOrganisations(eaForm, request);
62+
}
5363
if (request.getParameter("orgSelReset") != null
5464
&& request.getParameter("orgSelReset").equals("false")) {
5565
eaForm.setOrgSelReset(false);
@@ -229,6 +239,84 @@ else if (StringUtils.isNotBlank(eaForm.getKeyword())) {
229239

230240
}
231241

242+
/**
243+
* Deletes the organizations checked in the "Select" column, applying the same
244+
* referential checks as the single-organization delete on the edit page.
245+
*/
246+
private void deleteSelectedOrganisations(OrgManagerForm eaForm, HttpServletRequest request) {
247+
Long[] ids = eaForm.getSelectedOrgIds();
248+
if (ids == null || ids.length == 0) {
249+
return;
250+
}
251+
252+
ActionMessages messages = new ActionMessages();
253+
int deletedCount = 0;
254+
for (Long orgId : ids) {
255+
AmpOrganisation org = DbUtil.getOrganisation(orgId);
256+
if (org == null) {
257+
continue;
258+
}
259+
260+
boolean blocked = false;
261+
262+
Set<String> ampIds = new TreeSet<>();
263+
addAllIfNotNull(ampIds, DbUtil.getAmpIdsByOrg(orgId));
264+
addAllIfNotNull(ampIds, ActivityUtil.getAmpIdsByFundingOrg(orgId));
265+
addAllIfNotNull(ampIds, DbUtil.getAmpIdsByInternalIdOrg(orgId));
266+
if (!ampIds.isEmpty()) {
267+
messages.add(ActionMessages.GLOBAL_MESSAGE, new ActionMessage(
268+
"error.aim.organizationManager.deleteOrgActErrorBulk", org.getName(), String.join(", ", ampIds)));
269+
blocked = true;
270+
}
271+
272+
if (org.getCalendar() != null && !org.getCalendar().isEmpty()) {
273+
messages.add(ActionMessages.GLOBAL_MESSAGE,
274+
new ActionMessage("error.aim.organizationManager.deleteOrgEventErrorBulk", org.getName()));
275+
blocked = true;
276+
}
277+
278+
List<AmpTeam> relatedTeams = TeamUtil.getTeamByOrg(orgId);
279+
if (relatedTeams != null && !relatedTeams.isEmpty()) {
280+
messages.add(ActionMessages.GLOBAL_MESSAGE,
281+
new ActionMessage("error.aim.organizationManager.deleteOrgTeamErrorBulk", org.getName()));
282+
blocked = true;
283+
}
284+
285+
if (org.getUsers() != null && !org.getUsers().isEmpty()) {
286+
messages.add(ActionMessages.GLOBAL_MESSAGE,
287+
new ActionMessage("error.aim.organizationManager.deleteOrgVerifiedOrgErrorBulk", org.getName()));
288+
blocked = true;
289+
}
290+
291+
if (blocked) {
292+
continue;
293+
}
294+
295+
try {
296+
DbUtil.deleteOrg(org);
297+
deletedCount++;
298+
} catch (JDBCException e) {
299+
messages.add(ActionMessages.GLOBAL_MESSAGE,
300+
new ActionMessage("error.aim.organizationManager.deleteOrgJdbcErrorBulk", org.getName()));
301+
}
302+
}
303+
304+
if (deletedCount > 0) {
305+
messages.add(ActionMessages.GLOBAL_MESSAGE,
306+
new ActionMessage("error.aim.organizationManager.deleteOrgSuccessBulk", String.valueOf(deletedCount)));
307+
}
308+
if (!messages.isEmpty()) {
309+
saveErrors(request, messages);
310+
}
311+
eaForm.setSelectedOrgIds(null);
312+
}
313+
314+
private void addAllIfNotNull(Set<String> set, Collection<String> toAdd) {
315+
if (toAdd != null && !toAdd.isEmpty()) {
316+
set.addAll(toAdd);
317+
}
318+
}
319+
232320
private void collectAlphaArray(OrgManagerForm eaForm, Collection<AmpOrganisation> col) {
233321
SortedSet<String> chars = new TreeSet<String>(AmpUtil.CharUnicodeComparator);
234322
SortedSet<String> digits = new TreeSet<String>(AmpUtil.CharUnicodeComparator);

amp/src/main/java/org/digijava/module/aim/form/OrgManagerForm.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ public class OrgManagerForm
4343

4444
private String[] digitPages;
4545
private String[] alphaPages = null;
46+
private Long[] selectedOrgIds;
4647

4748
public boolean isAdminSide() {
4849
return adminSide;
@@ -107,6 +108,14 @@ public void setAlphaPages(String[] alphaPages) {
107108
this.alphaPages = alphaPages;
108109
}
109110

111+
public Long[] getSelectedOrgIds() {
112+
return selectedOrgIds;
113+
}
114+
115+
public void setSelectedOrgIds(Long[] selectedOrgIds) {
116+
this.selectedOrgIds = selectedOrgIds;
117+
}
118+
110119
/**
111120
* @return Returns the ampOrgTypeId.
112121
*/

amp/src/main/resources/java/resources/application.properties

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -583,6 +583,12 @@ error.aim.organizationManager.deleteOrgActError=Can not delete this organization
583583
error.aim.organizationManager.deleteOrgEventError=Can not delete this organization as it is currently referenced by Events
584584
error.aim.organizationManager.deleteOrgTeamError=Can not delete this organization as it is currently referenced by Teams
585585
error.aim.organizationManager.deleteOrgVerifiedOrgError=Can not delete this organization as it is currently referenced as verified Organization
586+
error.aim.organizationManager.deleteOrgActErrorBulk=Cannot delete organization "{0}": it is currently referenced by the following Activities (AMP Ids): {1}.
587+
error.aim.organizationManager.deleteOrgEventErrorBulk=Cannot delete organization "{0}": it is currently referenced by Events.
588+
error.aim.organizationManager.deleteOrgTeamErrorBulk=Cannot delete organization "{0}": it is currently referenced by Teams.
589+
error.aim.organizationManager.deleteOrgVerifiedOrgErrorBulk=Cannot delete organization "{0}": it is currently referenced as a verified Organization.
590+
error.aim.organizationManager.deleteOrgJdbcErrorBulk=Cannot delete organization "{0}": it is referenced by other data (e.g. Table widgets).
591+
error.aim.organizationManager.deleteOrgSuccessBulk=Successfully deleted {0} organization(s).
586592
error.aim.organizationManager.saveOrgPledgeError=Please complete the fields program, amount and date for each Pledge
587593
error.aim.organizationManager.saveOrgCodeError=Please choose another organization code as it is currently in use by some other organization.
588594
error.aim.organizationManager.saveOrgAcronymError = Please choose another organization acronym as it is currently in \

amp/src/main/resources/org/digijava/module/aim/dbentity/AmpActivityVersion.hbm.xml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,9 @@
139139
</set>
140140
141141
142-
<set name="categories" table="AMP_ACTIVITIES_CATEGORYVALUES" lazy="false" cascade="delete">
142+
<!-- AmpCategoryValue rows are shared reference data (statuses, types, etc.), never owned by
143+
one activity version, so this join must not cascade delete to the category value itself. -->
144+
<set name="categories" table="AMP_ACTIVITIES_CATEGORYVALUES" lazy="false" cascade="none">
143145
<cache usage="read-write" />
144146
<key column="amp_activity_id" />
145147
<many-to-many class="org.digijava.module.categorymanager.dbentity.AmpCategoryValue"

amp/src/main/webapp/WEB-INF/jsp/aim/view/organisationManager.jsp

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,37 @@
5858
document.aimOrgManagerForm.submit();
5959
}
6060
61+
function toggleAllOrgCheckboxes(masterCheckbox) {
62+
var boxes = document.getElementsByName("selectedOrgIds");
63+
for (var i = 0; i < boxes.length; i++) {
64+
boxes[i].checked = masterCheckbox.checked;
65+
}
66+
}
67+
68+
function deleteSelectedOrgs() {
69+
var boxes = document.getElementsByName("selectedOrgIds");
70+
var selected = false;
71+
for (var i = 0; i < boxes.length; i++) {
72+
if (boxes[i].checked) {
73+
selected = true;
74+
break;
75+
}
76+
}
77+
if (!selected) {
78+
alert('<digi:trn jsFriendly="true">Please select at least one organization first.</digi:trn>');
79+
return false;
80+
}
81+
if (!confirm('<digi:trn jsFriendly="true">Are you sure you want to delete the selected organizations?</digi:trn>')) {
82+
return false;
83+
}
84+
<digi:context name="searchOrg" property="context/module/moduleinstance/organisationManager.do"/>
85+
url = "<%= searchOrg %>?deleteSelectedOrgs=true&orgSelReset=false";
86+
document.aimOrgManagerForm.action = url;
87+
document.aimOrgManagerForm.target = "_self";
88+
document.aimOrgManagerForm.submit();
89+
return true;
90+
}
91+
6192
6293
6394
@@ -182,6 +213,13 @@
182213
</td>
183214
<!-- end header -->
184215
</tr>
216+
<c:if test="${aimOrgManagerForm.adminSide}">
217+
<tr>
218+
<td colspan="6" align="right" style="padding: 5px;">
219+
<input type="button" class="buttonx_sm" onclick="return deleteSelectedOrgs()" value="<digi:trn jsFriendly="true">Delete Selected</digi:trn>">
220+
</td>
221+
</tr>
222+
</c:if>
185223
<!-- Page Logic -->
186224

187225
<logic:empty name="aimOrgManagerForm"
@@ -203,6 +241,11 @@
203241
class="inside">
204242
<thead>
205243
<tr>
244+
<c:if test="${aimOrgManagerForm.adminSide}">
245+
<td class="inside" bgcolor=#F2F2F2 align="center">
246+
<input type="checkbox" onclick="toggleAllOrgCheckboxes(this)">
247+
</td>
248+
</c:if>
206249
<td class="inside" bgcolor=#F2F2F2><c:if
207250
test="${not empty aimOrgManagerForm.sortBy && aimOrgManagerForm.sortBy!='nameAscending'}">
208251
<digi:link
@@ -306,6 +349,11 @@
306349
property="pagedCol" id="organisation"
307350
indexId="index">
308351
<tr>
352+
<c:if test="${aimOrgManagerForm.adminSide}">
353+
<td class="inside" align="center">
354+
<input type="checkbox" name="selectedOrgIds" value="${organisation.ampOrgId}">
355+
</td>
356+
</c:if>
309357
<td class="inside">
310358
<jsp:useBean
311359
id="urlParams" type="java.util.Map"

0 commit comments

Comments
 (0)