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 }