/* * The Kuali Financial System, a comprehensive financial management system for higher education. * * Copyright 2005-2014 The Kuali Foundation * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package org.kuali.kfs.module.cam.document.web.struts; import java.io.FileNotFoundException; import java.io.IOException; import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.commons.lang.StringUtils; import org.apache.struts.action.ActionForm; import org.apache.struts.action.ActionForward; import org.apache.struts.action.ActionMapping; import org.kuali.kfs.module.cam.CamsKeyConstants; import org.kuali.kfs.module.cam.CamsPropertyConstants; import org.kuali.kfs.module.cam.businessobject.Asset; import org.kuali.kfs.module.cam.businessobject.AssetPaymentAssetDetail; import org.kuali.kfs.module.cam.businessobject.AssetPaymentDetail; import org.kuali.kfs.module.cam.document.AssetPaymentDocument; import org.kuali.kfs.module.cam.document.service.AssetPaymentService; import org.kuali.kfs.module.cam.document.validation.event.AssetPaymentAddAssetEvent; import org.kuali.kfs.module.cam.document.validation.event.AssetPaymentAllocationEvent; import org.kuali.kfs.module.cam.document.validation.event.AssetPaymentManuallyAddAccountingLineEvent; import org.kuali.kfs.module.cam.document.validation.event.AssetPaymentPrepareRouteEvent; import org.kuali.kfs.sys.KFSConstants; import org.kuali.kfs.sys.KFSKeyConstants; import org.kuali.kfs.sys.businessobject.SourceAccountingLine; import org.kuali.kfs.sys.context.SpringContext; import org.kuali.kfs.sys.document.validation.event.AddAccountingLineEvent; import org.kuali.kfs.sys.service.SegmentedLookupResultsService; import org.kuali.kfs.sys.web.struts.KualiAccountingDocumentActionBase; import org.kuali.rice.kew.api.KewApiConstants; import org.kuali.rice.kew.api.exception.WorkflowException; import org.kuali.rice.kns.service.DataDictionaryService; import org.kuali.rice.kns.web.struts.form.KualiDocumentFormBase; import org.kuali.rice.krad.bo.PersistableBusinessObject; import org.kuali.rice.krad.service.KualiRuleService; import org.kuali.rice.krad.service.PersistenceService; import org.kuali.rice.krad.util.GlobalVariables; import org.kuali.rice.krad.util.ObjectUtils; /** * Control user responses */ public class AssetPaymentAction extends KualiAccountingDocumentActionBase { protected static final org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(AssetPaymentAction.class); @Override protected void createDocument(KualiDocumentFormBase kualiDocumentFormBase) throws WorkflowException { super.createDocument(kualiDocumentFormBase); ((AssetPaymentDocument) kualiDocumentFormBase.getDocument()).setAssetPaymentAllocationTypeCode(CamsPropertyConstants.AssetPaymentAllocation.ASSET_DISTRIBUTION_DEFAULT_CODE); } @Override public ActionForward docHandler(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { ActionForward actionForward = super.docHandler(mapping, form, request, response); AssetPaymentForm assetPaymentForm = (AssetPaymentForm) form; String command = assetPaymentForm.getCommand(); // If a asset was selected from the asset payment lookup page then // insert asset into the document. if (KewApiConstants.INITIATE_COMMAND.equals(command) && ((assetPaymentForm.getCapitalAssetNumber() != null) && !assetPaymentForm.getCapitalAssetNumber().trim().equals(""))) { List<AssetPaymentAssetDetail> assetPaymentAssetDetails = assetPaymentForm.getAssetPaymentDocument().getAssetPaymentAssetDetail(); AssetPaymentAssetDetail assetPaymentAssetDetail = new AssetPaymentAssetDetail(); assetPaymentAssetDetail.setDocumentNumber(assetPaymentForm.getAssetPaymentDocument().getDocumentNumber()); assetPaymentAssetDetail.setCapitalAssetNumber(new Long(assetPaymentForm.getCapitalAssetNumber())); assetPaymentAssetDetail.refreshReferenceObject(CamsPropertyConstants.AssetPaymentDocument.ASSET); assetPaymentAssetDetail.setPreviousTotalCostAmount(assetPaymentAssetDetail.getAsset().getTotalCostAmount()); assetPaymentAssetDetails.add(assetPaymentAssetDetail); assetPaymentForm.getAssetPaymentDocument().setAssetPaymentAssetDetail(assetPaymentAssetDetails); assetPaymentForm.setCapitalAssetNumber(""); } return actionForward; } /** * @see org.kuali.kfs.sys.web.struts.KualiAccountingDocumentActionBase#refresh(org.apache.struts.action.ActionMapping, * org.apache.struts.action.ActionForm, * javax.servlet.http.HttpServletRequest, * javax.servlet.http.HttpServletResponse) */ @Override public ActionForward refresh(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { super.refresh(mapping, form, request, response); AssetPaymentForm assetPaymentForm = (AssetPaymentForm) form; Collection<PersistableBusinessObject> rawValues = null; Map<String, Set<String>> segmentedSelection = new HashMap<String, Set<String>>(); // If multiple asset lookup was used to select the assets, then.... if (StringUtils.equals(KFSConstants.MULTIPLE_VALUE, assetPaymentForm.getRefreshCaller())) { String lookupResultsSequenceNumber = assetPaymentForm.getLookupResultsSequenceNumber(); if (StringUtils.isNotBlank(lookupResultsSequenceNumber)) { // actually returning from a multiple value lookup Set<String> selectedIds = SpringContext.getBean(SegmentedLookupResultsService.class).retrieveSetOfSelectedObjectIds(lookupResultsSequenceNumber, GlobalVariables.getUserSession().getPerson().getPrincipalId()); for (String selectedId : selectedIds) { String selectedObjId = StringUtils.substringBefore(selectedId, "."); String selectedMonthData = StringUtils.substringAfter(selectedId, "."); if (!segmentedSelection.containsKey(selectedObjId)) { segmentedSelection.put(selectedObjId, new HashSet<String>()); } segmentedSelection.get(selectedObjId).add(selectedMonthData); } // Retrieving selected data from table. if (LOG.isDebugEnabled()) { LOG.debug("Asking segmentation service for object ids " + segmentedSelection.keySet()); } rawValues = SpringContext.getBean(SegmentedLookupResultsService.class).retrieveSelectedResultBOs(lookupResultsSequenceNumber, segmentedSelection.keySet(), Asset.class, GlobalVariables.getUserSession().getPerson().getPrincipalId()); } List<AssetPaymentAssetDetail> assetPaymentAssetDetails = assetPaymentForm.getAssetPaymentDocument().getAssetPaymentAssetDetail(); if (rawValues != null) { for (PersistableBusinessObject bo : rawValues) { Asset asset = (Asset) bo; boolean addIt = true; for (AssetPaymentAssetDetail detail : assetPaymentAssetDetails) { if (detail.getCapitalAssetNumber().compareTo(asset.getCapitalAssetNumber()) == 0) { addIt = false; break; } } // If it doesn't already exist in the list add it. if (addIt) { AssetPaymentAssetDetail assetPaymentAssetDetail = new AssetPaymentAssetDetail(); assetPaymentAssetDetail.setDocumentNumber(assetPaymentForm.getAssetPaymentDocument().getDocumentNumber()); assetPaymentAssetDetail.setCapitalAssetNumber(asset.getCapitalAssetNumber()); assetPaymentAssetDetail.refreshReferenceObject(CamsPropertyConstants.AssetPaymentDocument.ASSET); assetPaymentAssetDetail.setPreviousTotalCostAmount(assetPaymentAssetDetail.getAsset().getTotalCostAmount()); assetPaymentAssetDetails.add(assetPaymentAssetDetail); } } assetPaymentForm.getAssetPaymentDocument().setAssetPaymentAssetDetail(assetPaymentAssetDetails); } } validateAllocations(assetPaymentForm); return mapping.findForward(KFSConstants.MAPPING_BASIC); } /** * @see org.kuali.kfs.sys.web.struts.KualiAccountingDocumentActionBase#uploadAccountingLines(boolean, * org.apache.struts.action.ActionForm) */ @Override protected void uploadAccountingLines(boolean isSource, ActionForm form) throws FileNotFoundException, IOException { AssetPaymentForm assetPaymentForm = (AssetPaymentForm) form; super.uploadAccountingLines(isSource, assetPaymentForm); List<AssetPaymentDetail> assetPaymentDetails = assetPaymentForm.getAssetPaymentDocument().getSourceAccountingLines(); for (AssetPaymentDetail assetPaymentDetail : assetPaymentDetails) { getAssetPaymentService().extractPostedDatePeriod(assetPaymentDetail); } } /** * @see org.kuali.kfs.sys.web.struts.KualiAccountingDocumentActionBase#insertSourceLine(org.apache.struts.action.ActionMapping, * org.apache.struts.action.ActionForm, * javax.servlet.http.HttpServletRequest, * javax.servlet.http.HttpServletResponse) */ @Override public ActionForward insertSourceLine(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { AssetPaymentForm assetPaymentForm = (AssetPaymentForm) form; SourceAccountingLine line = assetPaymentForm.getNewSourceLine(); // populate chartOfAccountsCode from account number if accounts cant // cross chart and Javascript is turned off // SpringContext.getBean(AccountService.class).populateAccountingLineChartIfNeeded(line); boolean rulePassed = true; // Check any business rules. We separate general accounting line // validation into AssetPaymentManuallyAddAccountingLineEvent, // and trigger it from this action, also document save. rulePassed &= getRuleService().applyRules(new AssetPaymentManuallyAddAccountingLineEvent(KFSConstants.NEW_SOURCE_ACCT_LINE_PROPERTY_NAME, assetPaymentForm.getDocument(), line)); if (rulePassed) { rulePassed &= getRuleService().applyRules(new AddAccountingLineEvent(KFSConstants.NEW_SOURCE_ACCT_LINE_PROPERTY_NAME, assetPaymentForm.getDocument(), line)); } if (rulePassed) { // add accountingLine SpringContext.getBean(PersistenceService.class).refreshAllNonUpdatingReferences(line); insertAccountingLine(true, assetPaymentForm, line); // clear the used new source line assetPaymentForm.setNewSourceLine(new AssetPaymentDetail()); } validateAllocations(assetPaymentForm); return mapping.findForward(KFSConstants.MAPPING_BASIC); } /** * Inserts a new asset into the document * * @param mapping * @param form * @param request * @param response * @return ActionForward * @throws Exception */ public ActionForward insertAssetPaymentAssetDetail(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { AssetPaymentForm assetPaymentForm = (AssetPaymentForm) form; AssetPaymentDocument assetPaymentDocument = assetPaymentForm.getAssetPaymentDocument(); List<AssetPaymentAssetDetail> assetPaymentDetails = assetPaymentForm.getAssetPaymentDocument().getAssetPaymentAssetDetail(); AssetPaymentAssetDetail newAssetPaymentAssetDetail = new AssetPaymentAssetDetail(); String sCapitalAssetNumber = assetPaymentForm.getCapitalAssetNumber(); String errorPath = CamsPropertyConstants.Asset.CAPITAL_ASSET_NUMBER; // Validating the asset code is numeric Long capitalAssetNumber = null; try { capitalAssetNumber = Long.parseLong(sCapitalAssetNumber); } catch (NumberFormatException e) { // Validating the asset number field is not empty if (ObjectUtils.isNull(sCapitalAssetNumber) || StringUtils.isBlank(sCapitalAssetNumber)) { String label = SpringContext.getBean(DataDictionaryService.class).getDataDictionary().getBusinessObjectEntry(AssetPaymentAssetDetail.class.getName()).getAttributeDefinition(CamsPropertyConstants.Asset.CAPITAL_ASSET_NUMBER).getLabel(); GlobalVariables.getMessageMap().putError(errorPath, KFSKeyConstants.ERROR_REQUIRED, label); } else { // it is not empty but has an invalid value. GlobalVariables.getMessageMap().putError(errorPath, CamsKeyConstants.AssetLocationGlobal.ERROR_INVALID_CAPITAL_ASSET_NUMBER, sCapitalAssetNumber); } return mapping.findForward(KFSConstants.MAPPING_BASIC); } boolean rulePassed = true; newAssetPaymentAssetDetail.setDocumentNumber(assetPaymentDocument.getDocumentNumber()); newAssetPaymentAssetDetail.setCapitalAssetNumber(capitalAssetNumber); newAssetPaymentAssetDetail.refreshReferenceObject(CamsPropertyConstants.AssetPaymentDocument.ASSET); // Validating the new asset rulePassed &= getRuleService().applyRules(new AssetPaymentAddAssetEvent(errorPath, assetPaymentForm.getDocument(), newAssetPaymentAssetDetail)); if (rulePassed) { // Storing the current asset cost. newAssetPaymentAssetDetail.setPreviousTotalCostAmount(newAssetPaymentAssetDetail.getAsset().getTotalCostAmount()); assetPaymentForm.getAssetPaymentDocument().addAssetPaymentAssetDetail(newAssetPaymentAssetDetail); assetPaymentForm.setCapitalAssetNumber(""); } validateAllocations(assetPaymentForm); return mapping.findForward(KFSConstants.MAPPING_BASIC); } /** * Deletes an asset from the document * * @param mapping * @param form * @param request * @param response * @return ActionForward * @throws Exception */ public ActionForward deleteAssetPaymentAssetDetail(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { AssetPaymentForm assetPaymentForm = (AssetPaymentForm) form; int deleteIndex = getLineToDelete(request); // Getting the asset number that is going to be deleted from document Long capitalAssetNumber = assetPaymentForm.getAssetPaymentDocument().getAssetPaymentAssetDetail().get(deleteIndex).getCapitalAssetNumber(); // Deleting the asset from document assetPaymentForm.getAssetPaymentDocument().getAssetPaymentAssetDetail().remove(deleteIndex); validateAllocations(assetPaymentForm); return mapping.findForward(KFSConstants.MAPPING_BASIC); } /** * Update allocations made to assets * * @param mapping * @param form * @param request * @param response * @return * @throws Exception */ public ActionForward updateAssetPaymentAssetDetail(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { validateAllocations(form); return mapping.findForward(KFSConstants.MAPPING_BASIC); } /** * Validate allocations * * @param form */ private boolean validateAllocations(ActionForm form) { AssetPaymentForm assetPaymentForm = (AssetPaymentForm) form; AssetPaymentDocument assetPaymentDocument = assetPaymentForm.getAssetPaymentDocument(); assetPaymentDocument.getAssetPaymentDistributor().applyDistributionsToDocument(); String errorPath = KFSConstants.DOCUMENT_PROPERTY_NAME; return getRuleService().applyRules(new AssetPaymentAllocationEvent(errorPath, assetPaymentDocument)); } /** * @see org.kuali.kfs.sys.web.struts.KualiAccountingDocumentActionBase#route(org.apache.struts.action.ActionMapping, * org.apache.struts.action.ActionForm, * javax.servlet.http.HttpServletRequest, * javax.servlet.http.HttpServletResponse) */ @Override public ActionForward route(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { AssetPaymentDocument assetPaymentDocument = ((AssetPaymentForm) form).getAssetPaymentDocument(); String errorPath = KFSConstants.DOCUMENT_PROPERTY_NAME; // run all validation first boolean rulePassed = getRuleService().applyRules(new AssetPaymentPrepareRouteEvent(errorPath, assetPaymentDocument)); rulePassed &= validateAllocations(form); if (rulePassed) { // this super method call could trigger the warning message of // object sub type code from payment lines not matching the // one from assets. return super.route(mapping, form, request, response); } else { return mapping.findForward(KFSConstants.MAPPING_BASIC); } } @Override public ActionForward blanketApprove(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { AssetPaymentDocument assetPaymentDocument = ((AssetPaymentForm) form).getAssetPaymentDocument(); String errorPath = KFSConstants.DOCUMENT_PROPERTY_NAME; // run all validation first boolean rulePassed = getRuleService().applyRules(new AssetPaymentPrepareRouteEvent(errorPath, assetPaymentDocument)); rulePassed &= validateAllocations(form); if (rulePassed) { return super.blanketApprove(mapping, form, request, response); } else { return mapping.findForward(KFSConstants.MAPPING_BASIC); } } @Override public ActionForward deleteSourceLine(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { validateAllocations(form); return super.deleteSourceLine(mapping, form, request, response); } /** * Called when the user selects a distribution (asset payment allocation) * type. * * @param mapping * @param form * @param request * @param response * @return * @throws Exception */ public ActionForward selectAllocationType(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { AssetPaymentDocument assetPaymentDocument = ((AssetPaymentForm) form).getAssetPaymentDocument(); assetPaymentDocument.getAssetPaymentDistributor().applyDistributionsToDocument(); return mapping.findForward(KFSConstants.MAPPING_BASIC); } /** * Get the payment service * * @return */ protected AssetPaymentService getAssetPaymentService() { return SpringContext.getBean(AssetPaymentService.class); } /** * Get the rule service * * @return */ protected KualiRuleService getRuleService() { return SpringContext.getBean(KualiRuleService.class); } }