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.fp.batch.service.impl;
017    
018    import java.util.List;
019    
020    import org.kuali.kfs.fp.document.DistributionOfIncomeAndExpenseDocument;
021    import org.kuali.kfs.sys.KFSConstants;
022    import org.kuali.kfs.sys.businessobject.ElectronicPaymentClaim;
023    import org.kuali.kfs.sys.businessobject.SourceAccountingLine;
024    import org.kuali.kfs.sys.context.SpringContext;
025    import org.kuali.kfs.sys.service.ElectronicPaymentClaimingDocumentGenerationStrategy;
026    import org.kuali.kfs.sys.service.ElectronicPaymentClaimingService;
027    import org.kuali.rice.kew.exception.WorkflowException;
028    import org.kuali.rice.kew.util.KEWConstants;
029    import org.kuali.rice.kim.bo.Person;
030    import org.kuali.rice.kns.bo.Note;
031    import org.kuali.rice.kns.service.DataDictionaryService;
032    import org.kuali.rice.kns.service.DocumentService;
033    import org.kuali.rice.kns.service.KNSServiceLocator;
034    import org.kuali.rice.kns.service.ParameterService;
035    import org.kuali.rice.kns.workflow.service.KualiWorkflowInfo;
036    import org.kuali.rice.kns.workflow.service.WorkflowInfoService;
037    
038    public class DistributionOfIncomeAndExpenseElectronicPaymentClaimingHelperStrategyImpl implements ElectronicPaymentClaimingDocumentGenerationStrategy {
039        private org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(DistributionOfIncomeAndExpenseElectronicPaymentClaimingHelperStrategyImpl.class);
040        
041        private DataDictionaryService dataDictionaryService;
042        private DocumentService documentService;
043        private ElectronicPaymentClaimingService electronicPaymentClaimingService;
044        private ParameterService parameterService;
045    
046        /**
047         * The name of the parameter to get the description for this document; without a description, we can't save the document, and if
048         * we don't save the document, there's a chance that electronic payment claims will go to limbo
049         */
050        private final static String DOCUMENT_DESCRIPTION_PARAM_NAME = "ELECTRONIC_FUNDS_DOCUMENT_DESCRIPTION";
051        private final static String URL_PREFIX = "financial";
052        private final static String URL_MIDDLE = ".do?methodToCall=docHandler&command=";
053        private final static String URL_SUFFIX = "&docId=";
054        private final static String URL_DOC_TYPE = "DistributionOfIncomeAndExpense";
055    
056        /**
057         * @see org.kuali.kfs.sys.service.ElectronicPaymentClaimingDocumentGenerationStrategy#createDocumentFromElectronicPayments(java.util.List)
058         */
059        public String createDocumentFromElectronicPayments(List<ElectronicPaymentClaim> electronicPayments, Person user) {
060            DistributionOfIncomeAndExpenseDocument document = null;
061            try {
062                document = (DistributionOfIncomeAndExpenseDocument) documentService.getNewDocument(getClaimingDocumentWorkflowDocumentType());
063                addAccountingLinesToDocument(document, electronicPayments);
064                addDescriptionToDocument(document);
065                addNotesToDocument(document, electronicPayments, user);
066                documentService.saveDocument(document);
067                electronicPaymentClaimingService.claimElectronicPayments(electronicPayments, document.getDocumentNumber());
068            }
069            catch (WorkflowException we) {
070                throw new RuntimeException("WorkflowException while creating a DistributionOfIncomeAndExpenseDocument to claim ElectronicPaymentClaim records.", we);
071            }
072    
073            return getURLForDocument(document);
074        }
075    
076        /**
077         * Builds the URL that can be used to redirect to the correct document
078         * 
079         * @param doc the document to build the URL for
080         * @return the relative URL to redirect to
081         */
082        protected String getURLForDocument(DistributionOfIncomeAndExpenseDocument doc) {
083            StringBuilder url = new StringBuilder();
084            url.append(URL_PREFIX);
085            url.append(getUrlDocType());
086            url.append(URL_MIDDLE);
087            url.append(KEWConstants.ACTIONLIST_COMMAND);
088            url.append(URL_SUFFIX);
089            url.append(doc.getDocumentNumber());
090            return url.toString();
091        }
092    
093        /**
094         * Creates notes for the claims (using the ElectronicPaymentClaimingService) and then adds them to the document
095         * 
096         * @param claimingDoc the claiming document
097         * @param claims the electronic payments being claimed
098         * @param user the user doing the claiming
099         */
100        protected void addNotesToDocument(DistributionOfIncomeAndExpenseDocument claimingDoc, List<ElectronicPaymentClaim> claims, Person user) {
101            for (String noteText : electronicPaymentClaimingService.constructNoteTextsForClaims(claims)) {
102                try {
103                    Note note = documentService.createNoteFromDocument(claimingDoc, noteText);
104                    documentService.addNoteToDocument(claimingDoc, note);
105                }
106                catch (Exception e) {
107                    LOG.error("Exception while attempting to create or add note: " + e);
108                }
109            }
110        }
111    
112        /**
113         * Adds an accounting line to the document for each ElectronicPaymentClaim record that is being added
114         * 
115         * @param document the claiming Distribution of Income and Expense document
116         * @param electronicPayments the list of ElectronicPaymentClaim records that are being claimed
117         */
118        protected void addAccountingLinesToDocument(DistributionOfIncomeAndExpenseDocument document, List<ElectronicPaymentClaim> electronicPayments) {
119            for (ElectronicPaymentClaim payment : electronicPayments) {
120                SourceAccountingLine claimingAccountingLine = copyAccountingLineToNew(payment.getGeneratingAccountingLine(), createNewAccountingLineForDocument(document));
121                document.addSourceAccountingLine(claimingAccountingLine);
122            }
123        }
124    
125        /**
126         * Adds the parameterized description to the document, so the doc can be saved
127         * 
128         * @param document the document to add a description to
129         */
130        protected void addDescriptionToDocument(DistributionOfIncomeAndExpenseDocument document) {
131            String description = parameterService.getParameterValue(DistributionOfIncomeAndExpenseDocument.class, DistributionOfIncomeAndExpenseElectronicPaymentClaimingHelperStrategyImpl.DOCUMENT_DESCRIPTION_PARAM_NAME);
132            if (description != null) {
133                document.getDocumentHeader().setDocumentDescription(description);
134            }
135            else {
136                throw new RuntimeException("There is evidently no value for Parameter KFS-FP / Distribution of Income and Expense / " + DistributionOfIncomeAndExpenseElectronicPaymentClaimingHelperStrategyImpl.DOCUMENT_DESCRIPTION_PARAM_NAME + "; please set a value before claiming Electronic Payments");
137            }
138        }
139    
140        /**
141         * Creates a new accounting line, based on what the source accounting line class for the document is
142         * 
143         * @param document the document that is claiming these payments
144         * @return a new, ready-to-be-filled in accounting line of the class that the given document uses for Source Accounting Lines
145         */
146        protected SourceAccountingLine createNewAccountingLineForDocument(DistributionOfIncomeAndExpenseDocument document) {
147            SourceAccountingLine newLine = null;
148            try {
149                Class accountingLineClass = document.getSourceAccountingLineClass();
150                newLine = (SourceAccountingLine) accountingLineClass.newInstance();
151            }
152            catch (InstantiationException ie) {
153                throw new RuntimeException(ie);
154            }
155            catch (IllegalAccessException iae) {
156                throw new RuntimeException(iae);
157            }
158            return newLine;
159        }
160    
161        /**
162         * Copies an original accounting line to a new accounting line
163         * 
164         * @param line the original accounting line
165         * @return an accounting line that copies that accounting line
166         */
167        protected SourceAccountingLine copyAccountingLineToNew(SourceAccountingLine line, SourceAccountingLine newLine) {
168            newLine.setChartOfAccountsCode(line.getChartOfAccountsCode());
169            newLine.setAccountNumber(line.getAccountNumber());
170            newLine.setSubAccountNumber(line.getSubAccountNumber());
171            newLine.setFinancialObjectCode(line.getFinancialObjectCode());
172            newLine.setFinancialSubObjectCode(line.getFinancialSubObjectCode());
173            newLine.setProjectCode(line.getProjectCode());
174            newLine.setOrganizationReferenceId(line.getOrganizationReferenceId());
175            newLine.setAmount(line.getAmount());
176            return newLine;
177        }
178    
179        /**
180         * @see org.kuali.kfs.sys.service.ElectronicPaymentClaimingDocumentGenerationStrategy#getClaimingDocumentWorkflowDocumentType()
181         * @return the name DistributionOfIncomeAndExpenseDocument workflow document type
182         */
183        public String getClaimingDocumentWorkflowDocumentType() {
184            return "DI";
185        }
186        
187        /**
188         * @return the class of the document which claims these electronic payments
189         */
190        protected String getUrlDocType() {
191            return DistributionOfIncomeAndExpenseElectronicPaymentClaimingHelperStrategyImpl.URL_DOC_TYPE;
192        }
193    
194        /**
195         * Uses the data dictionary to find the label for this document
196         * 
197         * @see org.kuali.kfs.sys.service.ElectronicPaymentClaimingDocumentGenerationStrategy#getDocumentLabel()
198         */
199        public String getDocumentLabel() {
200            try {
201                KualiWorkflowInfo workflowInfo = KNSServiceLocator.getWorkflowInfoService();
202                
203                return workflowInfo.getDocType(getClaimingDocumentWorkflowDocumentType()).getDocTypeLabel();
204            }
205            catch (WorkflowException e) {
206                throw new RuntimeException("Caught Exception trying to get Workflow Document Type", e);
207            }
208        }
209    
210        /**
211         * This always returns true if the given user in the claiming workgroup.
212         * 
213         * @see org.kuali.kfs.sys.service.ElectronicPaymentClaimingDocumentGenerationStrategy#userMayUseToClaim(org.kuali.rice.kim.bo.Person)
214         */
215        public boolean userMayUseToClaim(Person claimingUser) {
216            final String documentTypeName = this.getClaimingDocumentWorkflowDocumentType();
217    
218            final boolean canClaim = electronicPaymentClaimingService.isAuthorizedForClaimingElectronicPayment(claimingUser, documentTypeName) || electronicPaymentClaimingService.isAuthorizedForClaimingElectronicPayment(claimingUser, null);       
219            
220            return canClaim;
221        }
222    
223        /**
224         * @see org.kuali.kfs.sys.service.ElectronicPaymentClaimingDocumentGenerationStrategy#isDocumentReferenceValid(java.lang.String)
225         */
226        public boolean isDocumentReferenceValid(String referenceDocumentNumber) {
227            boolean valid = false;
228            try {
229                long docNumberAsLong = Long.parseLong(referenceDocumentNumber);
230                if (docNumberAsLong > 0L) {
231                    valid = documentService.documentExists(referenceDocumentNumber);
232                }
233            }
234            catch (NumberFormatException nfe) {
235                valid = false; // the doc # can't be parsed into a Long? Then it ain't no valid!
236            }
237            return valid;
238        }
239    
240        /**
241         * Sets the ddService attribute value.
242         * 
243         * @param ddService The ddService to set.
244         */
245        public void setDataDictionaryService(DataDictionaryService dataDictionaryService) {
246            this.dataDictionaryService = dataDictionaryService;
247        }
248    
249        /**
250         * Gets the dataDictionaryService attribute. 
251         * @return Returns the dataDictionaryService.
252         */
253        public DataDictionaryService getDataDictionaryService() {
254            return dataDictionaryService;
255        }
256    
257        /**
258         * Sets the documentService attribute value.
259         * 
260         * @param documentService The documentService to set.
261         */
262        public void setDocumentService(DocumentService documentService) {
263            this.documentService = documentService;
264        }
265    
266        /**
267         * Sets the electronicPaymentClaimingService attribute value.
268         * 
269         * @param electronicPaymentClaimingService The electronicPaymentClaimingService to set.
270         */
271        public void setElectronicPaymentClaimingService(ElectronicPaymentClaimingService electronicPaymentClaimingService) {
272            this.electronicPaymentClaimingService = electronicPaymentClaimingService;
273        }
274    
275        /**
276         * Sets the parameterService attribute value.
277         * 
278         * @param parameterService The parameterService to set.
279         */
280        public void setParameterService(ParameterService parameterService) {
281            this.parameterService = parameterService;
282        }
283    }