View Javadoc
1   /*
2    * The Kuali Financial System, a comprehensive financial management system for higher education.
3    * 
4    * Copyright 2005-2014 The Kuali Foundation
5    * 
6    * This program is free software: you can redistribute it and/or modify
7    * it under the terms of the GNU Affero General Public License as
8    * published by the Free Software Foundation, either version 3 of the
9    * License, or (at your option) any later version.
10   * 
11   * This program is distributed in the hope that it will be useful,
12   * but WITHOUT ANY WARRANTY; without even the implied warranty of
13   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14   * GNU Affero General Public License for more details.
15   * 
16   * You should have received a copy of the GNU Affero General Public License
17   * along with this program.  If not, see <http://www.gnu.org/licenses/>.
18   */
19  package org.kuali.kfs.module.cam.document.web.struts;
20  
21  import java.io.FileNotFoundException;
22  import java.io.IOException;
23  import java.util.Collection;
24  import java.util.HashMap;
25  import java.util.HashSet;
26  import java.util.List;
27  import java.util.Map;
28  import java.util.Set;
29  
30  import javax.servlet.http.HttpServletRequest;
31  import javax.servlet.http.HttpServletResponse;
32  
33  import org.apache.commons.lang.StringUtils;
34  import org.apache.struts.action.ActionForm;
35  import org.apache.struts.action.ActionForward;
36  import org.apache.struts.action.ActionMapping;
37  import org.kuali.kfs.module.cam.CamsKeyConstants;
38  import org.kuali.kfs.module.cam.CamsPropertyConstants;
39  import org.kuali.kfs.module.cam.businessobject.Asset;
40  import org.kuali.kfs.module.cam.businessobject.AssetPaymentAssetDetail;
41  import org.kuali.kfs.module.cam.businessobject.AssetPaymentDetail;
42  import org.kuali.kfs.module.cam.document.AssetPaymentDocument;
43  import org.kuali.kfs.module.cam.document.service.AssetPaymentService;
44  import org.kuali.kfs.module.cam.document.validation.event.AssetPaymentAddAssetEvent;
45  import org.kuali.kfs.module.cam.document.validation.event.AssetPaymentAllocationEvent;
46  import org.kuali.kfs.module.cam.document.validation.event.AssetPaymentManuallyAddAccountingLineEvent;
47  import org.kuali.kfs.module.cam.document.validation.event.AssetPaymentPrepareRouteEvent;
48  import org.kuali.kfs.sys.KFSConstants;
49  import org.kuali.kfs.sys.KFSKeyConstants;
50  import org.kuali.kfs.sys.businessobject.SourceAccountingLine;
51  import org.kuali.kfs.sys.context.SpringContext;
52  import org.kuali.kfs.sys.document.validation.event.AddAccountingLineEvent;
53  import org.kuali.kfs.sys.service.SegmentedLookupResultsService;
54  import org.kuali.kfs.sys.web.struts.KualiAccountingDocumentActionBase;
55  import org.kuali.rice.kew.api.KewApiConstants;
56  import org.kuali.rice.kew.api.exception.WorkflowException;
57  import org.kuali.rice.kns.service.DataDictionaryService;
58  import org.kuali.rice.kns.web.struts.form.KualiDocumentFormBase;
59  import org.kuali.rice.krad.bo.PersistableBusinessObject;
60  import org.kuali.rice.krad.service.KualiRuleService;
61  import org.kuali.rice.krad.service.PersistenceService;
62  import org.kuali.rice.krad.util.GlobalVariables;
63  import org.kuali.rice.krad.util.ObjectUtils;
64  
65  /**
66   * Control user responses
67   */
68  public class AssetPaymentAction extends KualiAccountingDocumentActionBase {
69  	protected static final org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(AssetPaymentAction.class);
70  
71  	@Override
72  	protected void createDocument(KualiDocumentFormBase kualiDocumentFormBase) throws WorkflowException {
73  		super.createDocument(kualiDocumentFormBase);
74  		((AssetPaymentDocument) kualiDocumentFormBase.getDocument()).setAssetPaymentAllocationTypeCode(CamsPropertyConstants.AssetPaymentAllocation.ASSET_DISTRIBUTION_DEFAULT_CODE);
75  	}
76  	
77  	@Override
78  	public ActionForward docHandler(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
79  		ActionForward actionForward = super.docHandler(mapping, form, request, response);
80  		AssetPaymentForm assetPaymentForm = (AssetPaymentForm) form;
81  		String command = assetPaymentForm.getCommand();
82  
83  		// If a asset was selected from the asset payment lookup page then
84  		// insert asset into the document.
85  		if (KewApiConstants.INITIATE_COMMAND.equals(command) && ((assetPaymentForm.getCapitalAssetNumber() != null) && !assetPaymentForm.getCapitalAssetNumber().trim().equals(""))) {
86  			List<AssetPaymentAssetDetail> assetPaymentAssetDetails = assetPaymentForm.getAssetPaymentDocument().getAssetPaymentAssetDetail();
87  
88  			AssetPaymentAssetDetail assetPaymentAssetDetail = new AssetPaymentAssetDetail();
89  			assetPaymentAssetDetail.setDocumentNumber(assetPaymentForm.getAssetPaymentDocument().getDocumentNumber());
90  			assetPaymentAssetDetail.setCapitalAssetNumber(new Long(assetPaymentForm.getCapitalAssetNumber()));
91  			assetPaymentAssetDetail.refreshReferenceObject(CamsPropertyConstants.AssetPaymentDocument.ASSET);
92  			assetPaymentAssetDetail.setPreviousTotalCostAmount(assetPaymentAssetDetail.getAsset().getTotalCostAmount());
93  
94  			assetPaymentAssetDetails.add(assetPaymentAssetDetail);
95  			assetPaymentForm.getAssetPaymentDocument().setAssetPaymentAssetDetail(assetPaymentAssetDetails);
96  			assetPaymentForm.setCapitalAssetNumber("");
97  		}
98  		return actionForward;
99  	}
100 
101 	/**
102 	 * @see org.kuali.kfs.sys.web.struts.KualiAccountingDocumentActionBase#refresh(org.apache.struts.action.ActionMapping,
103 	 *      org.apache.struts.action.ActionForm,
104 	 *      javax.servlet.http.HttpServletRequest,
105 	 *      javax.servlet.http.HttpServletResponse)
106 	 */
107 	@Override
108 	public ActionForward refresh(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
109 		super.refresh(mapping, form, request, response);
110 
111 		AssetPaymentForm assetPaymentForm = (AssetPaymentForm) form;
112 
113 		Collection<PersistableBusinessObject> rawValues = null;
114 		Map<String, Set<String>> segmentedSelection = new HashMap<String, Set<String>>();
115 
116 		// If multiple asset lookup was used to select the assets, then....
117 		if (StringUtils.equals(KFSConstants.MULTIPLE_VALUE, assetPaymentForm.getRefreshCaller())) {
118 			String lookupResultsSequenceNumber = assetPaymentForm.getLookupResultsSequenceNumber();
119 
120 			if (StringUtils.isNotBlank(lookupResultsSequenceNumber)) {
121 				// actually returning from a multiple value lookup
122 				Set<String> selectedIds = SpringContext.getBean(SegmentedLookupResultsService.class).retrieveSetOfSelectedObjectIds(lookupResultsSequenceNumber, GlobalVariables.getUserSession().getPerson().getPrincipalId());
123 				for (String selectedId : selectedIds) {
124 					String selectedObjId = StringUtils.substringBefore(selectedId, ".");
125 					String selectedMonthData = StringUtils.substringAfter(selectedId, ".");
126 
127 					if (!segmentedSelection.containsKey(selectedObjId)) {
128 						segmentedSelection.put(selectedObjId, new HashSet<String>());
129 					}
130 					segmentedSelection.get(selectedObjId).add(selectedMonthData);
131 				}
132 				// Retrieving selected data from table.
133 				if (LOG.isDebugEnabled()) {
134 					LOG.debug("Asking segmentation service for object ids " + segmentedSelection.keySet());
135 				}
136 				rawValues = SpringContext.getBean(SegmentedLookupResultsService.class).retrieveSelectedResultBOs(lookupResultsSequenceNumber, segmentedSelection.keySet(), Asset.class, GlobalVariables.getUserSession().getPerson().getPrincipalId());
137 			}
138 
139 			List<AssetPaymentAssetDetail> assetPaymentAssetDetails = assetPaymentForm.getAssetPaymentDocument().getAssetPaymentAssetDetail();
140 			if (rawValues != null) {
141 				for (PersistableBusinessObject bo : rawValues) {
142 					Asset asset = (Asset) bo;
143 
144 					boolean addIt = true;
145 					for (AssetPaymentAssetDetail detail : assetPaymentAssetDetails) {
146 						if (detail.getCapitalAssetNumber().compareTo(asset.getCapitalAssetNumber()) == 0) {
147 							addIt = false;
148 							break;
149 						}
150 					}
151 
152 					// If it doesn't already exist in the list add it.
153 					if (addIt) {
154 						AssetPaymentAssetDetail assetPaymentAssetDetail = new AssetPaymentAssetDetail();
155 						assetPaymentAssetDetail.setDocumentNumber(assetPaymentForm.getAssetPaymentDocument().getDocumentNumber());
156 						assetPaymentAssetDetail.setCapitalAssetNumber(asset.getCapitalAssetNumber());
157 						assetPaymentAssetDetail.refreshReferenceObject(CamsPropertyConstants.AssetPaymentDocument.ASSET);
158 						assetPaymentAssetDetail.setPreviousTotalCostAmount(assetPaymentAssetDetail.getAsset().getTotalCostAmount());
159 
160 						assetPaymentAssetDetails.add(assetPaymentAssetDetail);
161 					}
162 				}
163 				assetPaymentForm.getAssetPaymentDocument().setAssetPaymentAssetDetail(assetPaymentAssetDetails);
164 			}
165 		}
166 
167 		validateAllocations(assetPaymentForm);
168 
169 		return mapping.findForward(KFSConstants.MAPPING_BASIC);
170 	}
171 
172 	/**
173 	 * @see org.kuali.kfs.sys.web.struts.KualiAccountingDocumentActionBase#uploadAccountingLines(boolean,
174 	 *      org.apache.struts.action.ActionForm)
175 	 */
176 	@Override
177 	protected void uploadAccountingLines(boolean isSource, ActionForm form) throws FileNotFoundException, IOException {
178 		AssetPaymentForm assetPaymentForm = (AssetPaymentForm) form;
179 		super.uploadAccountingLines(isSource, assetPaymentForm);
180 		List<AssetPaymentDetail> assetPaymentDetails = assetPaymentForm.getAssetPaymentDocument().getSourceAccountingLines();
181 		for (AssetPaymentDetail assetPaymentDetail : assetPaymentDetails) {
182 			getAssetPaymentService().extractPostedDatePeriod(assetPaymentDetail);
183 		}
184 	}
185 
186 	/**
187 	 * @see org.kuali.kfs.sys.web.struts.KualiAccountingDocumentActionBase#insertSourceLine(org.apache.struts.action.ActionMapping,
188 	 *      org.apache.struts.action.ActionForm,
189 	 *      javax.servlet.http.HttpServletRequest,
190 	 *      javax.servlet.http.HttpServletResponse)
191 	 */
192 	@Override
193 	public ActionForward insertSourceLine(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
194 		AssetPaymentForm assetPaymentForm = (AssetPaymentForm) form;
195 		SourceAccountingLine line = assetPaymentForm.getNewSourceLine();
196 
197 		// populate chartOfAccountsCode from account number if accounts cant
198 		// cross chart and Javascript is turned off
199 		// SpringContext.getBean(AccountService.class).populateAccountingLineChartIfNeeded(line);
200 
201 		boolean rulePassed = true;
202 		// Check any business rules. We separate general accounting line
203 		// validation into AssetPaymentManuallyAddAccountingLineEvent,
204 		// and trigger it from this action, also document save.
205 		rulePassed &= getRuleService().applyRules(new AssetPaymentManuallyAddAccountingLineEvent(KFSConstants.NEW_SOURCE_ACCT_LINE_PROPERTY_NAME, assetPaymentForm.getDocument(), line));
206 		if (rulePassed) {
207 			rulePassed &= getRuleService().applyRules(new AddAccountingLineEvent(KFSConstants.NEW_SOURCE_ACCT_LINE_PROPERTY_NAME, assetPaymentForm.getDocument(), line));
208 		}
209 		if (rulePassed) {
210 			// add accountingLine
211 			SpringContext.getBean(PersistenceService.class).refreshAllNonUpdatingReferences(line);
212 			insertAccountingLine(true, assetPaymentForm, line);
213 
214 			// clear the used new source line
215 			assetPaymentForm.setNewSourceLine(new AssetPaymentDetail());
216 		}
217 
218 		validateAllocations(assetPaymentForm);
219 
220 		return mapping.findForward(KFSConstants.MAPPING_BASIC);
221 	}
222 
223 	/**
224 	 * Inserts a new asset into the document
225 	 * 
226 	 * @param mapping
227 	 * @param form
228 	 * @param request
229 	 * @param response
230 	 * @return ActionForward
231 	 * @throws Exception
232 	 */
233 	public ActionForward insertAssetPaymentAssetDetail(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
234 		AssetPaymentForm assetPaymentForm = (AssetPaymentForm) form;
235 		AssetPaymentDocument assetPaymentDocument = assetPaymentForm.getAssetPaymentDocument();
236 
237 		List<AssetPaymentAssetDetail> assetPaymentDetails = assetPaymentForm.getAssetPaymentDocument().getAssetPaymentAssetDetail();
238 
239 		AssetPaymentAssetDetail newAssetPaymentAssetDetail = new AssetPaymentAssetDetail();
240 		String sCapitalAssetNumber = assetPaymentForm.getCapitalAssetNumber();
241 
242 		String errorPath = CamsPropertyConstants.Asset.CAPITAL_ASSET_NUMBER;
243 
244 		// Validating the asset code is numeric
245 		Long capitalAssetNumber = null;
246 		try {
247 			capitalAssetNumber = Long.parseLong(sCapitalAssetNumber);
248 		} catch (NumberFormatException e) {
249 			// Validating the asset number field is not empty
250 			if (ObjectUtils.isNull(sCapitalAssetNumber) || StringUtils.isBlank(sCapitalAssetNumber)) {
251 				String label = SpringContext.getBean(DataDictionaryService.class).getDataDictionary().getBusinessObjectEntry(AssetPaymentAssetDetail.class.getName()).getAttributeDefinition(CamsPropertyConstants.Asset.CAPITAL_ASSET_NUMBER).getLabel();
252 				GlobalVariables.getMessageMap().putError(errorPath, KFSKeyConstants.ERROR_REQUIRED, label);
253 			} else {
254 				// it is not empty but has an invalid value.
255 				GlobalVariables.getMessageMap().putError(errorPath, CamsKeyConstants.AssetLocationGlobal.ERROR_INVALID_CAPITAL_ASSET_NUMBER, sCapitalAssetNumber);
256 			}
257 			return mapping.findForward(KFSConstants.MAPPING_BASIC);
258 		}
259 
260 		boolean rulePassed = true;
261 
262 		newAssetPaymentAssetDetail.setDocumentNumber(assetPaymentDocument.getDocumentNumber());
263 		newAssetPaymentAssetDetail.setCapitalAssetNumber(capitalAssetNumber);
264 		newAssetPaymentAssetDetail.refreshReferenceObject(CamsPropertyConstants.AssetPaymentDocument.ASSET);
265 		// Validating the new asset
266 		rulePassed &= getRuleService().applyRules(new AssetPaymentAddAssetEvent(errorPath, assetPaymentForm.getDocument(), newAssetPaymentAssetDetail));
267 		if (rulePassed) {
268 			// Storing the current asset cost.
269 			newAssetPaymentAssetDetail.setPreviousTotalCostAmount(newAssetPaymentAssetDetail.getAsset().getTotalCostAmount());
270 
271 			assetPaymentForm.getAssetPaymentDocument().addAssetPaymentAssetDetail(newAssetPaymentAssetDetail);
272 			assetPaymentForm.setCapitalAssetNumber("");
273 		}
274 
275 		validateAllocations(assetPaymentForm);
276 
277 		return mapping.findForward(KFSConstants.MAPPING_BASIC);
278 	}
279 
280 	/**
281 	 * Deletes an asset from the document
282 	 * 
283 	 * @param mapping
284 	 * @param form
285 	 * @param request
286 	 * @param response
287 	 * @return ActionForward
288 	 * @throws Exception
289 	 */
290 	public ActionForward deleteAssetPaymentAssetDetail(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
291 		AssetPaymentForm assetPaymentForm = (AssetPaymentForm) form;
292 
293 		int deleteIndex = getLineToDelete(request);
294 
295 		// Getting the asset number that is going to be deleted from document
296 		Long capitalAssetNumber = assetPaymentForm.getAssetPaymentDocument().getAssetPaymentAssetDetail().get(deleteIndex).getCapitalAssetNumber();
297 
298 		// Deleting the asset from document
299 		assetPaymentForm.getAssetPaymentDocument().getAssetPaymentAssetDetail().remove(deleteIndex);
300 
301 		validateAllocations(assetPaymentForm);
302 
303 		return mapping.findForward(KFSConstants.MAPPING_BASIC);
304 	}
305 
306 	/**
307 	 * Update allocations made to assets
308 	 * 
309 	 * @param mapping
310 	 * @param form
311 	 * @param request
312 	 * @param response
313 	 * @return
314 	 * @throws Exception
315 	 */
316 	public ActionForward updateAssetPaymentAssetDetail(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
317 		validateAllocations(form);
318 		return mapping.findForward(KFSConstants.MAPPING_BASIC);
319 	}
320 
321 	/**
322 	 * Validate allocations
323 	 * 
324 	 * @param form
325 	 */
326 	private boolean validateAllocations(ActionForm form) {
327 		AssetPaymentForm assetPaymentForm = (AssetPaymentForm) form;
328 		AssetPaymentDocument assetPaymentDocument = assetPaymentForm.getAssetPaymentDocument();
329 
330         assetPaymentDocument.getAssetPaymentDistributor().applyDistributionsToDocument();
331         String errorPath = KFSConstants.DOCUMENT_PROPERTY_NAME;
332         return getRuleService().applyRules(new AssetPaymentAllocationEvent(errorPath, assetPaymentDocument));
333 	}
334 
335 	/**
336 	 * @see org.kuali.kfs.sys.web.struts.KualiAccountingDocumentActionBase#route(org.apache.struts.action.ActionMapping,
337 	 *      org.apache.struts.action.ActionForm,
338 	 *      javax.servlet.http.HttpServletRequest,
339 	 *      javax.servlet.http.HttpServletResponse)
340 	 */
341 	@Override
342 	public ActionForward route(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
343 		AssetPaymentDocument assetPaymentDocument = ((AssetPaymentForm) form).getAssetPaymentDocument();
344 		String errorPath = KFSConstants.DOCUMENT_PROPERTY_NAME;
345 		// run all validation first
346 		boolean rulePassed = getRuleService().applyRules(new AssetPaymentPrepareRouteEvent(errorPath, assetPaymentDocument));
347 		rulePassed &= validateAllocations(form);
348 		if (rulePassed) {
349 			// this super method call could trigger the warning message of
350 			// object sub type code from payment lines not matching the
351 			// one from assets.
352 			return super.route(mapping, form, request, response);
353 		} else {
354 			return mapping.findForward(KFSConstants.MAPPING_BASIC);
355 		}
356 	}
357 
358 	@Override
359 	public ActionForward blanketApprove(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
360 		AssetPaymentDocument assetPaymentDocument = ((AssetPaymentForm) form).getAssetPaymentDocument();
361 		String errorPath = KFSConstants.DOCUMENT_PROPERTY_NAME;
362 		// run all validation first
363 		boolean rulePassed = getRuleService().applyRules(new AssetPaymentPrepareRouteEvent(errorPath, assetPaymentDocument));
364 		rulePassed &= validateAllocations(form);
365 		if (rulePassed) {
366 			return super.blanketApprove(mapping, form, request, response);
367 		} else {
368 			return mapping.findForward(KFSConstants.MAPPING_BASIC);
369 		}
370 	}
371 
372 	@Override
373 	public ActionForward deleteSourceLine(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
374 		validateAllocations(form);
375 		return super.deleteSourceLine(mapping, form, request, response);
376 	}
377 
378 	/**
379 	 * Called when the user selects a distribution (asset payment allocation)
380 	 * type.
381 	 * 
382 	 * @param mapping
383 	 * @param form
384 	 * @param request
385 	 * @param response
386 	 * @return
387 	 * @throws Exception
388 	 */
389 	public ActionForward selectAllocationType(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
390 		AssetPaymentDocument assetPaymentDocument = ((AssetPaymentForm) form).getAssetPaymentDocument();
391 		assetPaymentDocument.getAssetPaymentDistributor().applyDistributionsToDocument();
392 		return mapping.findForward(KFSConstants.MAPPING_BASIC);
393 	}
394 
395 	/**
396 	 * Get the payment service
397 	 * 
398 	 * @return
399 	 */
400 	protected AssetPaymentService getAssetPaymentService() {
401 		return SpringContext.getBean(AssetPaymentService.class);
402 	}
403 
404 	/**
405 	 * Get the rule service
406 	 * 
407 	 * @return
408 	 */
409 	protected KualiRuleService getRuleService() {
410 		return SpringContext.getBean(KualiRuleService.class);
411 	}
412 
413 }