001 /* 002 * Copyright 2011 The Kuali Foundation. 003 * 004 * Licensed under the Educational Community License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.opensource.org/licenses/ecl2.php 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 package org.kuali.kfs.sys.service.impl; 017 018 import java.util.ArrayList; 019 import java.util.Collection; 020 import java.util.Date; 021 import java.util.HashMap; 022 import java.util.List; 023 import java.util.Map; 024 025 import org.kuali.kfs.fp.document.AdvanceDepositDocument; 026 import org.kuali.kfs.integration.ar.AccountsReceivableModuleService; 027 import org.kuali.kfs.sys.KFSConstants; 028 import org.kuali.kfs.sys.businessobject.AccountingLine; 029 import org.kuali.kfs.sys.businessobject.ElectronicPaymentClaim; 030 import org.kuali.kfs.sys.context.SpringContext; 031 import org.kuali.kfs.sys.identity.KfsKimAttributes; 032 import org.kuali.kfs.sys.service.ElectronicPaymentClaimingDocumentGenerationStrategy; 033 import org.kuali.kfs.sys.service.ElectronicPaymentClaimingService; 034 import org.kuali.rice.kim.bo.Person; 035 import org.kuali.rice.kim.bo.types.dto.AttributeSet; 036 import org.kuali.rice.kim.service.IdentityManagementService; 037 import org.kuali.rice.kns.document.Document; 038 import org.kuali.rice.kns.service.BusinessObjectService; 039 import org.kuali.rice.kns.service.DateTimeService; 040 import org.kuali.rice.kns.service.DocumentService; 041 import org.kuali.rice.kns.service.ParameterService; 042 import org.kuali.rice.kns.util.ObjectUtils; 043 044 public class ElectronicPaymentClaimingServiceImpl implements ElectronicPaymentClaimingService { 045 private org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(ElectronicPaymentClaimingServiceImpl.class); 046 private DocumentService documentService; 047 private BusinessObjectService businessObjectService; 048 private ParameterService parameterService; 049 private DateTimeService dateTimeService; 050 051 protected static final String ELECTRONIC_FUNDS_CLAIMANT_GROUP_PARAMETER = "ELECTRONIC_FUNDS_CLAIMANT_GROUP"; 052 protected final static String ELECTRONIC_PAYMENT_ADMINISTRATOR_GROUP_PARAM_NAME = "ELECTRONIC_FUNDS_ADMINISTRATOR_GROUP"; 053 protected static final String ELECTRONIC_FUNDS_CLAIM_SUMMARIES_PER_NOTE_PARAMETER = "ELECTRONIC_FUNDS_CLAIM_SUMMARIES_PER_NOTE"; 054 protected static final String CLAIMING_NOTE_PRELUDE = "Claiming CR Items: "; 055 protected static final String DI_CLAIMING_DOC_HELPER_BEAN_NAME = "distributionOfIncomeAndExpenseElectronicPaymentClaimingDocumentHelper"; 056 protected static final String YEDI_CLAIMING_DOC_HELPER_BEAN_NAME = "yearEndDistributionOfIncomeAndExpenseElectronicPaymentClaimingDocumentHelper"; 057 protected static final String CLAIMING_DOC_HELPER_BEAN_NAME = "expenseElectronicPaymentClaimingDocumentHelper"; 058 protected static final String ELECTRONIC_PAYMENT_CLAIM_ACCOUNTS_PARAMETER = "ELECTRONIC_FUNDS_ACCOUNTS"; 059 060 /** 061 * @see org.kuali.kfs.sys.service.ElectronicPaymentClaimingService#constructNotesForClaims(java.util.List) 062 */ 063 public List<String> constructNoteTextsForClaims(List<ElectronicPaymentClaim> claims) { 064 int summariesPerNote; 065 List<String> noteTexts = new ArrayList<String>(); 066 try { 067 summariesPerNote = Integer.parseInt(parameterService.getParameterValue(ElectronicPaymentClaim.class, ELECTRONIC_FUNDS_CLAIM_SUMMARIES_PER_NOTE_PARAMETER)); 068 int i = 0; 069 while (i < claims.size()) { 070 String noteText = constructNoteText(claims, i, summariesPerNote); 071 noteTexts.add(noteText); 072 i += summariesPerNote; 073 } 074 } 075 catch (NumberFormatException nfe) { 076 throw new RuntimeException("The KFS-SYS / ElectronicPaymentClaim / " + ELECTRONIC_FUNDS_CLAIM_SUMMARIES_PER_NOTE_PARAMETER + " should have a value that can be parsed into an integer.", nfe); 077 } 078 return noteTexts; 079 } 080 081 /** 082 * This creates a note for the given point in the list of summaries. 083 * 084 * @param claims a List of ElectronicPaymentClaim records that are being claimed 085 * @param startPoint the point in the list the note is starting at 086 * @param maxSummariesPerNote the number of ElectronicPaymentClaim summaries we can have on a note 087 * @return a newly constructed note, that needs to have a user added 088 */ 089 protected String constructNoteText(List<ElectronicPaymentClaim> claims, int startPoint, int maxSummariesPerNote) { 090 StringBuilder sb = new StringBuilder(); 091 sb.append(CLAIMING_NOTE_PRELUDE); 092 for (int i = startPoint; i < (startPoint + maxSummariesPerNote) && i < claims.size(); i++) { 093 ElectronicPaymentClaim claim = claims.get(i); 094 sb.append(createSummaryLineForClaim(claim)); 095 } 096 // substring out the final " ; " 097 String noteText = sb.substring(0, sb.length() - 3); 098 return noteText; 099 } 100 101 /** 102 * Creates a summary line for a note from a claim 103 * 104 * @param claim the electronic payment claim to summarize 105 * @return a String with the summary of the claim. 106 */ 107 protected String createSummaryLineForClaim(ElectronicPaymentClaim claim) { 108 StringBuilder summary = new StringBuilder(); 109 summary.append(claim.getDocumentNumber()); 110 summary.append('-'); 111 summary.append(claim.getFinancialDocumentLineNumber().toString()); 112 summary.append(' '); 113 final Date advanceDepositDate = claim.getGeneratingAdvanceDepositDetail().getFinancialDocumentAdvanceDepositDate(); 114 if (!ObjectUtils.isNull(advanceDepositDate)) { 115 summary.append(dateTimeService.toDateString(advanceDepositDate)); 116 summary.append(' '); 117 } 118 summary.append('$'); 119 summary.append(claim.getGeneratingAccountingLine().getAmount()); 120 summary.append(' '); 121 summary.append(';'); 122 summary.append(' '); 123 return summary.toString(); 124 } 125 126 /** 127 * @see org.kuali.kfs.sys.service.ElectronicPaymentClaimingService#createPaymentClaimingDocument(java.util.List, 128 * org.kuali.kfs.sys.service.ElectronicPaymentClaimingDocumentGenerationStrategy) 129 */ 130 public String createPaymentClaimingDocument(List<ElectronicPaymentClaim> claims, ElectronicPaymentClaimingDocumentGenerationStrategy documentCreationHelper, Person user) { 131 return documentCreationHelper.createDocumentFromElectronicPayments(claims, user); 132 } 133 134 /** 135 * @see org.kuali.kfs.sys.service.ElectronicPaymentClaimingService#getClaimingDocumentChoices(org.kuali.rice.kim.bo.Person) 136 */ 137 public List<ElectronicPaymentClaimingDocumentGenerationStrategy> getClaimingDocumentChoices(Person user) { 138 List<ElectronicPaymentClaimingDocumentGenerationStrategy> documentChoices = new ArrayList<ElectronicPaymentClaimingDocumentGenerationStrategy>(); 139 Map<String, ElectronicPaymentClaimingDocumentGenerationStrategy> claimingDocHelpers = SpringContext.getBeansOfType(ElectronicPaymentClaimingDocumentGenerationStrategy.class); 140 ElectronicPaymentClaimingDocumentGenerationStrategy claimingDocHelper; 141 142 // try the helper for no document case 143 claimingDocHelper = claimingDocHelpers.get(CLAIMING_DOC_HELPER_BEAN_NAME); 144 if (claimingDocHelper.userMayUseToClaim(user)) { 145 documentChoices.add(claimingDocHelper); 146 } 147 148 // try the DI 149 claimingDocHelper = claimingDocHelpers.get(DI_CLAIMING_DOC_HELPER_BEAN_NAME); 150 if (claimingDocHelper.userMayUseToClaim(user)) { 151 documentChoices.add(claimingDocHelper); 152 } 153 154 // try the YEDI 155 claimingDocHelper = claimingDocHelpers.get(YEDI_CLAIMING_DOC_HELPER_BEAN_NAME); 156 if (claimingDocHelper.userMayUseToClaim(user)) { 157 documentChoices.add(claimingDocHelper); 158 } 159 160 // try the AR Cash Control 161 claimingDocHelper = SpringContext.getBean(AccountsReceivableModuleService.class).getAccountsReceivablePaymentClaimingStrategy(); 162 if (claimingDocHelper.userMayUseToClaim(user)) { 163 documentChoices.add(claimingDocHelper); 164 } 165 166 return documentChoices; 167 } 168 169 /** 170 * Sets the referenceFinancialDocumentNumber on each of the payments passed in with the given document number and then saves 171 * them. 172 * 173 * @param payments a list of payments to claim 174 * @param docmentNumber the document number of the claiming document 175 */ 176 public void claimElectronicPayments(List<ElectronicPaymentClaim> payments, String documentNumber) { 177 for (ElectronicPaymentClaim payment : payments) { 178 payment.setReferenceFinancialDocumentNumber(documentNumber); 179 payment.setPaymentClaimStatusCode(ElectronicPaymentClaim.ClaimStatusCodes.CLAIMED); 180 businessObjectService.save(payment); 181 } 182 } 183 184 /** 185 * @see org.kuali.kfs.sys.service.ElectronicPaymentClaimingService#declaimElectronicPaymentClaimsForDocument(org.kuali.rice.kns.document.Document) 186 */ 187 public void declaimElectronicPaymentClaimsForDocument(Document document) { 188 Map<String, String> searchKeys = new HashMap<String, String>(); 189 searchKeys.put("referenceFinancialDocumentNumber", document.getDocumentNumber()); 190 Collection<ElectronicPaymentClaim> claimsAsObjects = businessObjectService.findMatching(ElectronicPaymentClaim.class, searchKeys); 191 for (Object claimAsObject : claimsAsObjects) { 192 ElectronicPaymentClaim claim = (ElectronicPaymentClaim) claimAsObject; 193 claim.setReferenceFinancialDocumentNumber(null); 194 claim.setPaymentClaimStatusCode(ElectronicPaymentClaim.ClaimStatusCodes.UNCLAIMED); 195 businessObjectService.save(claim); 196 } 197 } 198 199 /** 200 * @see org.kuali.kfs.sys.service.ElectronicPaymentClaimingService#isAuthorizedForClaimingElectronicPayment(org.kuali.rice.kim.bo.Person, 201 * java.lang.String, java.lang.String) 202 */ 203 public boolean isAuthorizedForClaimingElectronicPayment(Person user, String workflowDocumentTypeName) { 204 String principalId = user.getPrincipalId(); 205 String namespaceCode = KFSConstants.ParameterNamespaces.KFS; 206 String permissionTemplateName = KFSConstants.PermissionTemplate.CLAIM_ELECTRONIC_PAYMENT.name; 207 208 AttributeSet permissionDetails = new AttributeSet(); 209 permissionDetails.put(KfsKimAttributes.DOCUMENT_TYPE_NAME, workflowDocumentTypeName); 210 211 IdentityManagementService identityManagementService = SpringContext.getBean(IdentityManagementService.class); 212 boolean isAuthorized = identityManagementService.hasPermissionByTemplateName(principalId, namespaceCode, permissionTemplateName, permissionDetails); 213 214 return isAuthorized; 215 } 216 217 /** 218 * @see org.kuali.kfs.sys.service.ElectronicPaymentClaimingService#generateElectronicPaymentClaimRecords(org.kuali.kfs.fp.document.AdvanceDepositDocument) 219 */ 220 public List<ElectronicPaymentClaim> generateElectronicPaymentClaimRecords(AdvanceDepositDocument doc) { 221 List<ElectronicPaymentClaim> claimRecords = new ArrayList<ElectronicPaymentClaim>(); 222 for (Object accountingLineAsObj : doc.getSourceAccountingLines()) { 223 final AccountingLine accountingLine = (AccountingLine) accountingLineAsObj; 224 if (this.representsElectronicFundAccount(accountingLine)) { 225 ElectronicPaymentClaim electronicPayment = createElectronicPayment(doc, accountingLine); 226 businessObjectService.save(electronicPayment); 227 claimRecords.add(electronicPayment); 228 } 229 } 230 return claimRecords; 231 } 232 233 /** 234 * Determines if the given accounting line represents an electronic payment 235 * @param accountingLine the accounting line to check 236 * @return true if the accounting line does represent an electronic payment, false otherwise 237 */ 238 public boolean representsElectronicFundAccount(AccountingLine accountingLine) { 239 return parameterService.getParameterEvaluator(AdvanceDepositDocument.class, ELECTRONIC_PAYMENT_CLAIM_ACCOUNTS_PARAMETER, accountingLine.getChartOfAccountsCode(), accountingLine.getAccountNumber()).evaluationSucceeds(); 240 } 241 242 /** 243 * Creates an electronic payment claim record to match the given accounting line on the document 244 * 245 * @param accountingLine an accounting line that an electronic payment claim record should be created for 246 * @return the created ElectronicPaymentClaim business object 247 */ 248 protected ElectronicPaymentClaim createElectronicPayment(AdvanceDepositDocument document, AccountingLine accountingLine) { 249 ElectronicPaymentClaim electronicPayment = new ElectronicPaymentClaim(); 250 electronicPayment.setDocumentNumber(document.getDocumentNumber()); 251 electronicPayment.setFinancialDocumentLineNumber(accountingLine.getSequenceNumber()); 252 electronicPayment.setFinancialDocumentPostingPeriodCode(document.getPostingPeriodCode()); 253 electronicPayment.setFinancialDocumentPostingYear(document.getPostingYear()); 254 electronicPayment.setPaymentClaimStatusCode(ElectronicPaymentClaim.ClaimStatusCodes.UNCLAIMED); 255 return electronicPayment; 256 } 257 258 /** 259 * Sets the businessObjectService attribute value. 260 * 261 * @param businessObjectService The businessObjectService to set. 262 */ 263 public void setBusinessObjectService(BusinessObjectService businessObjectService) { 264 this.businessObjectService = businessObjectService; 265 } 266 267 /** 268 * Sets the documentService attribute value. 269 * 270 * @param documentService The documentService to set. 271 */ 272 public void setDocumentService(DocumentService documentService) { 273 this.documentService = documentService; 274 } 275 276 /** 277 * Sets the parameterService attribute value. 278 * 279 * @param parameterService The parameterService to set. 280 */ 281 public void setParameterService(ParameterService parameterService) { 282 this.parameterService = parameterService; 283 } 284 285 /** 286 * Sets the dateTimeService attribute value. 287 * 288 * @param dateTimeService The dateTimeService to set. 289 */ 290 public void setDateTimeService(DateTimeService dateTimeService) { 291 this.dateTimeService = dateTimeService; 292 } 293 }