001/*
002 * Copyright 2008 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 */
016package org.kuali.ole.sys.service.impl;
017
018import java.util.ArrayList;
019import java.util.Collection;
020import java.util.Date;
021import java.util.HashMap;
022import java.util.List;
023import java.util.Map;
024
025import org.kuali.ole.fp.document.AdvanceDepositDocument;
026import org.kuali.ole.sys.OLEConstants;
027import org.kuali.ole.sys.businessobject.AccountingLine;
028import org.kuali.ole.sys.businessobject.ElectronicPaymentClaim;
029import org.kuali.ole.sys.context.SpringContext;
030import org.kuali.ole.sys.service.ElectronicPaymentClaimingDocumentGenerationStrategy;
031import org.kuali.ole.sys.service.ElectronicPaymentClaimingService;
032import org.kuali.rice.core.api.datetime.DateTimeService;
033import org.kuali.rice.core.api.parameter.ParameterEvaluatorService;
034import org.kuali.rice.coreservice.framework.parameter.ParameterService;
035import org.kuali.rice.kim.api.KimConstants;
036import org.kuali.rice.kim.api.identity.Person;
037import org.kuali.rice.kim.api.services.IdentityManagementService;
038import org.kuali.rice.krad.document.Document;
039import org.kuali.rice.krad.service.BusinessObjectService;
040import org.kuali.rice.krad.service.DocumentService;
041import org.kuali.rice.krad.util.ObjectUtils;
042
043public class ElectronicPaymentClaimingServiceImpl implements ElectronicPaymentClaimingService {
044    private org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(ElectronicPaymentClaimingServiceImpl.class);
045    private DocumentService documentService;
046    private BusinessObjectService businessObjectService;
047    private ParameterService parameterService;
048    private DateTimeService dateTimeService;
049
050    protected static final String ELECTRONIC_FUNDS_CLAIMANT_GROUP_PARAMETER = "ELECTRONIC_FUNDS_CLAIMANT_GROUP";
051    protected final static String ELECTRONIC_PAYMENT_ADMINISTRATOR_GROUP_PARAM_NAME = "ELECTRONIC_FUNDS_ADMINISTRATOR_GROUP";
052    protected static final String ELECTRONIC_FUNDS_CLAIM_SUMMARIES_PER_NOTE_PARAMETER = "ELECTRONIC_FUNDS_CLAIM_SUMMARIES_PER_NOTE";
053    protected static final String CLAIMING_NOTE_PRELUDE = "Claiming CR Items: ";
054    protected static final String DI_CLAIMING_DOC_HELPER_BEAN_NAME = "distributionOfIncomeAndExpenseElectronicPaymentClaimingDocumentHelper";
055    protected static final String YEDI_CLAIMING_DOC_HELPER_BEAN_NAME = "yearEndDistributionOfIncomeAndExpenseElectronicPaymentClaimingDocumentHelper";
056    protected static final String CLAIMING_DOC_HELPER_BEAN_NAME = "expenseElectronicPaymentClaimingDocumentHelper";
057    protected static final String ELECTRONIC_PAYMENT_CLAIM_ACCOUNTS_PARAMETER = "ELECTRONIC_FUNDS_ACCOUNTS";
058
059    /**
060     * @see org.kuali.ole.sys.service.ElectronicPaymentClaimingService#constructNotesForClaims(java.util.List)
061     */
062    @Override
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.getParameterValueAsString(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 OLE-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.ole.sys.service.ElectronicPaymentClaimingService#createPaymentClaimingDocument(java.util.List,
128     *      org.kuali.ole.sys.service.ElectronicPaymentClaimingDocumentGenerationStrategy)
129     */
130    @Override
131    public String createPaymentClaimingDocument(List<ElectronicPaymentClaim> claims, ElectronicPaymentClaimingDocumentGenerationStrategy documentCreationHelper, Person user) {
132        return documentCreationHelper.createDocumentFromElectronicPayments(claims, user);
133    }
134
135    /**
136     * @see org.kuali.ole.sys.service.ElectronicPaymentClaimingService#getClaimingDocumentChoices(org.kuali.rice.kim.api.identity.Person)
137     */
138    @Override
139    public List<ElectronicPaymentClaimingDocumentGenerationStrategy> getClaimingDocumentChoices(Person user) {
140        List<ElectronicPaymentClaimingDocumentGenerationStrategy> documentChoices = new ArrayList<ElectronicPaymentClaimingDocumentGenerationStrategy>();
141        Map<String, ElectronicPaymentClaimingDocumentGenerationStrategy> claimingDocHelpers = SpringContext.getBeansOfType(ElectronicPaymentClaimingDocumentGenerationStrategy.class);
142        ElectronicPaymentClaimingDocumentGenerationStrategy claimingDocHelper;
143        
144        // try the helper for no document case
145        claimingDocHelper = claimingDocHelpers.get(CLAIMING_DOC_HELPER_BEAN_NAME);
146        if (claimingDocHelper.userMayUseToClaim(user)) {
147            documentChoices.add(claimingDocHelper);
148        }        
149
150        // try the DI
151        claimingDocHelper = claimingDocHelpers.get(DI_CLAIMING_DOC_HELPER_BEAN_NAME);
152        if (claimingDocHelper.userMayUseToClaim(user)) {
153            documentChoices.add(claimingDocHelper);
154        }
155        
156        // try the YEDI
157        claimingDocHelper = claimingDocHelpers.get(YEDI_CLAIMING_DOC_HELPER_BEAN_NAME);
158        if (claimingDocHelper.userMayUseToClaim(user)) {
159            documentChoices.add(claimingDocHelper);
160        }
161
162        return documentChoices;
163    }
164
165    /**
166     * Sets the referenceFinancialDocumentNumber on each of the payments passed in with the given document number and then saves
167     * them.
168     * 
169     * @param payments a list of payments to claim
170     * @param docmentNumber the document number of the claiming document
171     */
172    @Override
173    public void claimElectronicPayments(List<ElectronicPaymentClaim> payments, String documentNumber) {
174        for (ElectronicPaymentClaim payment : payments) {
175            payment.setReferenceFinancialDocumentNumber(documentNumber);
176            payment.setPaymentClaimStatusCode(ElectronicPaymentClaim.ClaimStatusCodes.CLAIMED);
177            businessObjectService.save(payment);
178        }
179    }
180
181    /**
182     * @see org.kuali.ole.sys.service.ElectronicPaymentClaimingService#declaimElectronicPaymentClaimsForDocument(org.kuali.rice.krad.document.Document)
183     */
184    @Override
185    public void declaimElectronicPaymentClaimsForDocument(Document document) {
186        Map<String, String> searchKeys = new HashMap<String, String>();
187        searchKeys.put("referenceFinancialDocumentNumber", document.getDocumentNumber());
188        Collection<ElectronicPaymentClaim> claimsAsObjects = businessObjectService.findMatching(ElectronicPaymentClaim.class, searchKeys);
189        for (Object claimAsObject : claimsAsObjects) {
190            ElectronicPaymentClaim claim = (ElectronicPaymentClaim) claimAsObject;
191            claim.setReferenceFinancialDocumentNumber(null);
192            claim.setPaymentClaimStatusCode(ElectronicPaymentClaim.ClaimStatusCodes.UNCLAIMED);
193            businessObjectService.save(claim);
194        }
195    }
196
197    /**
198     * @see org.kuali.ole.sys.service.ElectronicPaymentClaimingService#isAuthorizedForClaimingElectronicPayment(org.kuali.rice.kim.api.identity.Person,
199     *      java.lang.String, java.lang.String)
200     */
201    @Override
202    public boolean isAuthorizedForClaimingElectronicPayment(Person user, String workflowDocumentTypeName) {
203        String principalId = user.getPrincipalId();
204        String namespaceCode = OLEConstants.ParameterNamespaces.OLE;
205        String permissionTemplateName = OLEConstants.PermissionTemplate.CLAIM_ELECTRONIC_PAYMENT.name;
206
207        Map<String,String> permissionDetails = new HashMap<String,String>();
208        permissionDetails.put(KimConstants.AttributeConstants.DOCUMENT_TYPE_NAME, workflowDocumentTypeName);      
209
210        IdentityManagementService identityManagementService = SpringContext.getBean(IdentityManagementService.class);
211        boolean isAuthorized = identityManagementService.hasPermissionByTemplateName(principalId, namespaceCode, permissionTemplateName, permissionDetails);
212        
213        return isAuthorized;
214    }
215
216    /**
217     * @see org.kuali.ole.sys.service.ElectronicPaymentClaimingService#generateElectronicPaymentClaimRecords(org.kuali.ole.fp.document.AdvanceDepositDocument)
218     */
219    @Override
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    @Override
239    public boolean representsElectronicFundAccount(AccountingLine accountingLine) {
240        return /*REFACTORME*/SpringContext.getBean(ParameterEvaluatorService.class).getParameterEvaluator(AdvanceDepositDocument.class, ELECTRONIC_PAYMENT_CLAIM_ACCOUNTS_PARAMETER, accountingLine.getChartOfAccountsCode(), accountingLine.getAccountNumber()).evaluationSucceeds();
241    }
242
243    /**
244     * Creates an electronic payment claim record to match the given accounting line on the document
245     * 
246     * @param accountingLine an accounting line that an electronic payment claim record should be created for
247     * @return the created ElectronicPaymentClaim business object
248     */
249    protected ElectronicPaymentClaim createElectronicPayment(AdvanceDepositDocument document, AccountingLine accountingLine) {
250        ElectronicPaymentClaim electronicPayment = new ElectronicPaymentClaim();
251        electronicPayment.setDocumentNumber(document.getDocumentNumber());
252        electronicPayment.setFinancialDocumentLineNumber(accountingLine.getSequenceNumber());
253        electronicPayment.setFinancialDocumentPostingPeriodCode(document.getPostingPeriodCode());
254        electronicPayment.setFinancialDocumentPostingYear(document.getPostingYear());
255        electronicPayment.setPaymentClaimStatusCode(ElectronicPaymentClaim.ClaimStatusCodes.UNCLAIMED);
256        return electronicPayment;
257    }
258
259    /**
260     * Sets the businessObjectService attribute value.
261     * 
262     * @param businessObjectService The businessObjectService to set.
263     */
264    public void setBusinessObjectService(BusinessObjectService businessObjectService) {
265        this.businessObjectService = businessObjectService;
266    }
267
268    /**
269     * Sets the documentService attribute value.
270     * 
271     * @param documentService The documentService to set.
272     */
273    public void setDocumentService(DocumentService documentService) {
274        this.documentService = documentService;
275    }
276
277    /**
278     * Sets the parameterService attribute value.
279     * 
280     * @param parameterService The parameterService to set.
281     */
282    public void setParameterService(ParameterService parameterService) {
283        this.parameterService = parameterService;
284    }
285
286    /**
287     * Sets the dateTimeService attribute value.
288     * 
289     * @param dateTimeService The dateTimeService to set.
290     */
291    public void setDateTimeService(DateTimeService dateTimeService) {
292        this.dateTimeService = dateTimeService;
293    }
294}