001/*
002 * Copyright 2006 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.fp.document;
017
018import java.util.ArrayList;
019import java.util.List;
020
021import org.kuali.ole.fp.businessobject.AdvanceDepositDetail;
022import org.kuali.ole.sys.OLEConstants;
023import org.kuali.ole.sys.OLEKeyConstants;
024import org.kuali.ole.sys.OLEPropertyConstants;
025import org.kuali.ole.sys.businessobject.GeneralLedgerPendingEntry;
026import org.kuali.ole.sys.businessobject.GeneralLedgerPendingEntrySequenceHelper;
027import org.kuali.ole.sys.context.SpringContext;
028import org.kuali.ole.sys.document.AmountTotaling;
029import org.kuali.ole.sys.document.service.AccountingDocumentRuleHelperService;
030import org.kuali.ole.sys.service.BankService;
031import org.kuali.ole.sys.service.ElectronicPaymentClaimingService;
032import org.kuali.ole.sys.service.GeneralLedgerPendingEntryService;
033import org.kuali.rice.core.api.util.type.KualiDecimal;
034import org.kuali.rice.core.web.format.CurrencyFormatter;
035import org.kuali.rice.kew.framework.postprocessor.DocumentRouteStatusChange;
036import org.kuali.rice.kns.service.DataDictionaryService;
037import org.kuali.rice.krad.document.Copyable;
038import org.kuali.rice.krad.rules.rule.event.KualiDocumentEvent;
039import org.kuali.rice.krad.rules.rule.event.SaveDocumentEvent;
040
041/**
042 * This is the business object that represents the AdvanceDeposit document in Kuali. This is a transactional document that will
043 * eventually post transactions to the G/L. It integrates with workflow. Since an Advance Deposit document is a one sided
044 * transactional document, only accepting funds into the university, the accounting line data will be held in the source accounting
045 * line data structure only.
046 */
047public class AdvanceDepositDocument extends CashReceiptFamilyBase implements Copyable, AmountTotaling {
048    public static final String ADVANCE_DEPOSIT_DOCUMENT_TYPE_CODE = "OLE_AD";
049    
050    // holds details about each advance deposit
051    protected List<AdvanceDepositDetail> advanceDeposits = new ArrayList<AdvanceDepositDetail>();
052
053    // incrementers for detail lines
054    protected Integer nextAdvanceDepositLineNumber = 1;
055
056    // monetary attributes
057    protected KualiDecimal totalAdvanceDepositAmount = KualiDecimal.ZERO;
058
059    /**
060     * Default constructor that calls super.
061     */
062    public AdvanceDepositDocument() {
063        super();
064    }
065
066    /**
067     * Gets the total advance deposit amount.
068     * 
069     * @return KualiDecimal
070     */
071    public KualiDecimal getTotalAdvanceDepositAmount() {
072        return totalAdvanceDepositAmount;
073    }
074
075    /**
076     * This method returns the advance deposit total amount as a currency formatted string.
077     * 
078     * @return String
079     */
080    public String getCurrencyFormattedTotalAdvanceDepositAmount() {
081        return (String) new CurrencyFormatter().format(totalAdvanceDepositAmount);
082    }
083
084    /**
085     * Sets the total advance deposit amount which is the sum of all advance deposits on this document.
086     * 
087     * @param advanceDepositAmount
088     */
089    public void setTotalAdvanceDepositAmount(KualiDecimal advanceDepositAmount) {
090        this.totalAdvanceDepositAmount = advanceDepositAmount;
091    }
092
093    /**
094     * Gets the list of advance deposits which is a list of AdvanceDepositDetail business objects.
095     * 
096     * @return List
097     */
098    public List<AdvanceDepositDetail> getAdvanceDeposits() {
099        return advanceDeposits;
100    }
101
102    /**
103     * Sets the advance deposits list.
104     * 
105     * @param advanceDeposits
106     */
107    public void setAdvanceDeposits(List<AdvanceDepositDetail> advanceDeposits) {
108        this.advanceDeposits = advanceDeposits;
109    }
110
111    /**
112     * Adds a new advance deposit to the list.
113     * 
114     * @param advanceDepositDetail
115     */
116    public void addAdvanceDeposit(AdvanceDepositDetail advanceDepositDetail) {
117        // these three make up the primary key for an advance deposit detail record
118        prepareNewAdvanceDeposit(advanceDepositDetail);
119
120        // add the new detail record to the list
121        this.advanceDeposits.add(advanceDepositDetail);
122
123        // increment line number
124        this.nextAdvanceDepositLineNumber++;
125
126        // update the overall amount
127        this.totalAdvanceDepositAmount = this.totalAdvanceDepositAmount.add(advanceDepositDetail.getFinancialDocumentAdvanceDepositAmount());
128    }
129
130    /**
131     * This is a helper method that automatically populates document specfic information into the advance deposit
132     * (AdvanceDepositDetail) instance.
133     * 
134     * @param advanceDepositDetail
135     */
136    public final void prepareNewAdvanceDeposit(AdvanceDepositDetail advanceDepositDetail) {
137        advanceDepositDetail.setFinancialDocumentLineNumber(this.nextAdvanceDepositLineNumber);
138        advanceDepositDetail.setDocumentNumber(this.getDocumentNumber());
139        advanceDepositDetail.setFinancialDocumentTypeCode(SpringContext.getBean(DataDictionaryService.class).getDocumentTypeNameByClass(this.getClass()));
140    }
141
142    /**
143     * Retrieve a particular advance deposit at a given index in the list of advance deposits.
144     * 
145     * @param index
146     * @return AdvanceDepositDetail
147     */
148    public AdvanceDepositDetail getAdvanceDepositDetail(int index) {
149        while (this.advanceDeposits.size() <= index) {
150            advanceDeposits.add(new AdvanceDepositDetail());
151        }
152        return advanceDeposits.get(index);
153    }
154
155    /**
156     * This method removes an advance deposit from the list and updates the total appropriately.
157     * 
158     * @param index
159     */
160    public void removeAdvanceDeposit(int index) {
161        AdvanceDepositDetail advanceDepositDetail = advanceDeposits.remove(index);
162        this.totalAdvanceDepositAmount = this.totalAdvanceDepositAmount.subtract(advanceDepositDetail.getFinancialDocumentAdvanceDepositAmount());
163    }
164
165    /**
166     * @return Integer
167     */
168    public Integer getNextAdvanceDepositLineNumber() {
169        return nextAdvanceDepositLineNumber;
170    }
171
172    /**
173     * @param nextAdvanceDepositLineNumber
174     */
175    public void setNextAdvanceDepositLineNumber(Integer nextAdvanceDepositLineNumber) {
176        this.nextAdvanceDepositLineNumber = nextAdvanceDepositLineNumber;
177    }
178
179    /**
180     * This method returns the overall total of the document - the advance deposit total.
181     * 
182     * @see org.kuali.ole.sys.document.AccountingDocumentBase#getTotalDollarAmount()
183     * @return KualiDecimal
184     */
185    @Override
186    public KualiDecimal getTotalDollarAmount() {
187        return this.totalAdvanceDepositAmount;
188    }
189
190    /**
191     * This method defers to its parent's version of handleRouteStatusChange, but then, if the document is processed, it creates
192     * ElectronicPaymentClaim records for any qualifying accountings lines in the document.
193     * 
194     * @see org.kuali.ole.sys.document.GeneralLedgerPostingDocumentBase#doRouteStatusChange()
195     */
196    @Override
197    public void doRouteStatusChange(DocumentRouteStatusChange statusChangeEvent) {
198        super.doRouteStatusChange(statusChangeEvent);
199        if (getDocumentHeader().getWorkflowDocument().isProcessed()) {
200            SpringContext.getBean(ElectronicPaymentClaimingService.class).generateElectronicPaymentClaimRecords(this);
201        }
202        this.getCapitalAssetManagementModuleService().deleteDocumentAssetLocks(this); 
203    }
204
205
206    /**
207     * Overrides super to call super and then also add in the new list of advance deposits that have to be managed.
208     * 
209     * @see org.kuali.rice.krad.document.TransactionalDocumentBase#buildListOfDeletionAwareLists()
210     */
211    @Override
212    public List buildListOfDeletionAwareLists() {
213        List managedLists = super.buildListOfDeletionAwareLists();
214        managedLists.add(getAdvanceDeposits());
215
216        return managedLists;
217    }
218
219    /**
220     * Generates bank offset GLPEs for deposits, if enabled.
221     * 
222     * @param financialDocument submitted financial document
223     * @param sequenceHelper helper class which will allows us to increment a reference without using an Integer
224     * @return true if there are no issues creating GLPE's
225     * @see org.kuali.rice.krad.rule.GenerateGeneralLedgerDocumentPendingEntriesRule#processGenerateDocumentGeneralLedgerPendingEntries(org.kuali.rice.krad.document.FinancialDocument,org.kuali.ole.sys.businessobject.GeneralLedgerPendingEntrySequenceHelper)
226     */
227    @Override
228    public boolean generateDocumentGeneralLedgerPendingEntries(GeneralLedgerPendingEntrySequenceHelper sequenceHelper) {
229        boolean success = true;
230
231        GeneralLedgerPendingEntryService glpeService = SpringContext.getBean(GeneralLedgerPendingEntryService.class);
232
233        if (SpringContext.getBean(BankService.class).isBankSpecificationEnabled()) {
234            int displayedDepositNumber = 1;
235            for (AdvanceDepositDetail detail : getAdvanceDeposits()) {
236                detail.refreshReferenceObject(OLEPropertyConstants.BANK);
237
238                GeneralLedgerPendingEntry bankOffsetEntry = new GeneralLedgerPendingEntry();
239                if (!glpeService.populateBankOffsetGeneralLedgerPendingEntry(detail.getBank(), detail.getFinancialDocumentAdvanceDepositAmount(), this, getPostingYear(), sequenceHelper, bankOffsetEntry, OLEConstants.ADVANCE_DEPOSITS_LINE_ERRORS)) {
240                    success = false;
241                    continue; // An unsuccessfully populated bank offset entry may contain invalid relations, so don't add it
242                }
243
244                AccountingDocumentRuleHelperService accountingDocumentRuleUtil = SpringContext.getBean(AccountingDocumentRuleHelperService.class);
245                bankOffsetEntry.setTransactionLedgerEntryDescription(accountingDocumentRuleUtil.formatProperty(OLEKeyConstants.AdvanceDeposit.DESCRIPTION_GLPE_BANK_OFFSET, displayedDepositNumber++));
246                addPendingEntry(bankOffsetEntry);
247                sequenceHelper.increment();
248
249                GeneralLedgerPendingEntry offsetEntry = new GeneralLedgerPendingEntry(bankOffsetEntry);
250                success &= glpeService.populateOffsetGeneralLedgerPendingEntry(getPostingYear(), bankOffsetEntry, sequenceHelper, offsetEntry);
251                addPendingEntry(offsetEntry);
252                sequenceHelper.increment();
253            }
254        }
255
256        return success;
257    }
258
259    @Override
260    public void postProcessSave(KualiDocumentEvent event) {
261        super.postProcessSave(event);
262        if (!(event instanceof SaveDocumentEvent)) { // don't lock until they route
263            String documentTypeName = SpringContext.getBean(DataDictionaryService.class).getDocumentTypeNameByClass(this.getClass());
264            this.getCapitalAssetManagementModuleService().generateCapitalAssetLock(this,documentTypeName);
265        }        
266    }
267}