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.module.purap.service.impl;
017
018import org.kuali.ole.module.purap.businessobject.*;
019import org.kuali.ole.module.purap.service.PurapAccountRevisionService;
020import org.kuali.rice.core.api.datetime.DateTimeService;
021import org.kuali.rice.krad.service.BusinessObjectService;
022
023import java.util.*;
024
025public class PurapAccountRevisionServiceImpl implements PurapAccountRevisionService {
026    private BusinessObjectService businessObjectService;
027    private DateTimeService dateTimeService;
028
029    /**
030     * @see org.kuali.ole.module.purap.service.PurapAccountHistoryService#savePaymentRequestAccountHistories(java.util.List,
031     *      java.lang.Integer, java.lang.String)
032     */
033    public void savePaymentRequestAccountRevisions(List<PaymentRequestItem> paymentRequestItems, Integer postingYear, String postingPeriodCode) {
034        List<PaymentRequestAccountRevision> accountHistories = new ArrayList<PaymentRequestAccountRevision>();
035        for (PaymentRequestItem item : paymentRequestItems) {
036            Map<PurapAccountRevisionGroup, PurapAccountRevisionGroup> currentAcctLineGroups = buildAccountLineGroups(item, postingYear, postingPeriodCode);
037            Map<PurapAccountRevisionGroup, PurapAccountRevisionGroup> historyAcctLineGroups = buildAccountHistoryGroups(item, postingYear, postingPeriodCode, PaymentRequestAccountRevision.class);
038            HashSet<PurapAccountRevisionGroup> existList = new HashSet<PurapAccountRevisionGroup>();
039            // handle existing account line changes
040            for (PurapAccountRevisionGroup histGroup : historyAcctLineGroups.keySet()) {
041                PurapAccountRevisionGroup currGroup = currentAcctLineGroups.get(histGroup);
042                if (currGroup != null) {
043                    // adjust the amount value
044                    histGroup.setChangeAmount(currGroup.getAmount().subtract(histGroup.getAmount()));
045                } else {
046                    // negate the amount if acct line is deleted
047                    histGroup.setChangeAmount(histGroup.getAmount().negated());
048                }
049                // build history record and save
050                PaymentRequestAccountRevision history = (PaymentRequestAccountRevision) histGroup.buildRevisionRecord(PaymentRequestAccountRevision.class);
051                history.setAccountRevisionTimestamp(dateTimeService.getCurrentTimestamp());
052                accountHistories.add(history);
053                existList.add(histGroup);
054            }
055            // handle new accounting lines
056            for (PurapAccountRevisionGroup group : currentAcctLineGroups.keySet()) {
057                if (!existList.contains(group)) {
058                    // set change amount same as new amount
059                    group.setChangeAmount(group.getAmount());
060                    PaymentRequestAccountRevision history = (PaymentRequestAccountRevision) group.buildRevisionRecord(PaymentRequestAccountRevision.class);
061                    history.setAccountRevisionTimestamp(dateTimeService.getCurrentTimestamp());
062                    accountHistories.add(history);
063                }
064            }
065        }
066        businessObjectService.save(accountHistories);
067    }
068
069    public void cancelPaymentRequestAccountRevisions(List<PaymentRequestItem> paymentRequestItems, Integer postingYear, String postingPeriodCode) {
070        List<PaymentRequestAccountRevision> accountHistories = new ArrayList<PaymentRequestAccountRevision>();
071        for (PaymentRequestItem item : paymentRequestItems) {
072            Map<PurapAccountRevisionGroup, PurapAccountRevisionGroup> historyAcctLineGroups = buildAccountHistoryGroups(item, postingYear, postingPeriodCode, PaymentRequestAccountRevision.class);
073            // handle existing account line changes
074            for (PurapAccountRevisionGroup histGroup : historyAcctLineGroups.keySet()) {
075                // negate the amount
076                histGroup.setChangeAmount(histGroup.getAmount().negated());
077                // build history record and save
078                PaymentRequestAccountRevision history = (PaymentRequestAccountRevision) histGroup.buildRevisionRecord(PaymentRequestAccountRevision.class);
079                history.setAccountRevisionTimestamp(dateTimeService.getCurrentTimestamp());
080                accountHistories.add(history);
081            }
082        }
083        businessObjectService.save(accountHistories);
084    }
085
086    /**
087     * @see org.kuali.ole.module.purap.service.PurapAccountHistoryService#savePaymentRequestAccountHistories(java.util.List,
088     *      java.lang.Integer, java.lang.String)
089     */
090    public void saveInvoiceAccountRevisions(List<InvoiceItem> invoiceItems, Integer postingYear, String postingPeriodCode) {
091        List<InvoiceAccountRevision> accountHistories = new ArrayList<InvoiceAccountRevision>();
092        for (InvoiceItem item : invoiceItems) {
093            Map<PurapAccountRevisionGroup, PurapAccountRevisionGroup> currentAcctLineGroups = buildAccountLineGroups(item, postingYear, postingPeriodCode);
094            Map<PurapAccountRevisionGroup, PurapAccountRevisionGroup> historyAcctLineGroups = buildAccountHistoryGroups(item, postingYear, postingPeriodCode, PaymentRequestAccountRevision.class);
095            HashSet<PurapAccountRevisionGroup> existList = new HashSet<PurapAccountRevisionGroup>();
096            // handle existing account line changes
097            for (PurapAccountRevisionGroup histGroup : historyAcctLineGroups.keySet()) {
098                PurapAccountRevisionGroup currGroup = currentAcctLineGroups.get(histGroup);
099                if (currGroup != null) {
100                    // adjust the amount value
101                    histGroup.setChangeAmount(currGroup.getAmount().subtract(histGroup.getAmount()));
102                } else {
103                    // negate the amount if acct line is deleted
104                    histGroup.setChangeAmount(histGroup.getAmount().negated());
105                }
106                // build history record and save
107                InvoiceAccountRevision history = (InvoiceAccountRevision) histGroup.buildRevisionRecord(InvoiceAccountRevision.class);
108                history.setAccountRevisionTimestamp(dateTimeService.getCurrentTimestamp());
109                accountHistories.add(history);
110                existList.add(histGroup);
111            }
112            // handle new accounting lines
113            for (PurapAccountRevisionGroup group : currentAcctLineGroups.keySet()) {
114                if (!existList.contains(group)) {
115                    // set change amount same as new amount
116                    group.setChangeAmount(group.getAmount());
117                    InvoiceAccountRevision history = (InvoiceAccountRevision) group.buildRevisionRecord(InvoiceAccountRevision.class);
118                    history.setAccountRevisionTimestamp(dateTimeService.getCurrentTimestamp());
119                    accountHistories.add(history);
120                }
121            }
122        }
123        businessObjectService.save(accountHistories);
124    }
125
126    public void cancelInvoiceAccountRevisions(List<InvoiceItem> invoiceItems, Integer postingYear, String postingPeriodCode) {
127        List<InvoiceAccountRevision> accountHistories = new ArrayList<InvoiceAccountRevision>();
128        for (InvoiceItem item : invoiceItems) {
129            Map<PurapAccountRevisionGroup, PurapAccountRevisionGroup> historyAcctLineGroups = buildAccountHistoryGroups(item, postingYear, postingPeriodCode, PaymentRequestAccountRevision.class);
130            // handle existing account line changes
131            for (PurapAccountRevisionGroup histGroup : historyAcctLineGroups.keySet()) {
132                // negate the amount
133                histGroup.setChangeAmount(histGroup.getAmount().negated());
134                // build history record and save
135                InvoiceAccountRevision history = (InvoiceAccountRevision) histGroup.buildRevisionRecord(InvoiceAccountRevision.class);
136                history.setAccountRevisionTimestamp(dateTimeService.getCurrentTimestamp());
137                accountHistories.add(history);
138            }
139        }
140        businessObjectService.save(accountHistories);
141    }
142
143    /**
144     * @see org.kuali.ole.module.purap.service.PurapAccountHistoryService#saveCreditMemoAccountHistories(java.util.List,
145     *      java.lang.Integer, java.lang.String)
146     */
147    public void saveCreditMemoAccountRevisions(List<CreditMemoItem> creditMemoItems, Integer postingYear, String postingPeriodCode) {
148        List<CreditMemoAccountRevision> accountHistories = new ArrayList<CreditMemoAccountRevision>();
149        for (CreditMemoItem item : creditMemoItems) {
150            Map<PurapAccountRevisionGroup, PurapAccountRevisionGroup> currentAcctLineGroups = buildAccountLineGroups(item, postingYear, postingPeriodCode);
151            Map<PurapAccountRevisionGroup, PurapAccountRevisionGroup> historyAcctLineGroups = buildAccountHistoryGroups(item, postingYear, postingPeriodCode, CreditMemoAccountRevision.class);
152            HashSet<PurapAccountRevisionGroup> existList = new HashSet<PurapAccountRevisionGroup>();
153            // first handle existing account line changes
154            for (PurapAccountRevisionGroup histGroup : historyAcctLineGroups.keySet()) {
155                PurapAccountRevisionGroup currGroup = currentAcctLineGroups.get(histGroup);
156                if (currGroup != null) {
157                    // adjust the amount
158                    histGroup.setChangeAmount(currGroup.getAmount().subtract(histGroup.getAmount()));
159                } else {
160                    // negate the amount if line is deleted
161                    histGroup.setChangeAmount(histGroup.getAmount().negated());
162                }
163                // build history record and save
164                CreditMemoAccountRevision history = (CreditMemoAccountRevision) histGroup.buildRevisionRecord(CreditMemoAccountRevision.class);
165                history.setAccountRevisionTimestamp(dateTimeService.getCurrentTimestamp());
166                accountHistories.add(history);
167                existList.add(histGroup);
168            }
169            // handle new account lines added
170            for (PurapAccountRevisionGroup group : currentAcctLineGroups.keySet()) {
171                if (!existList.contains(group)) {
172                    // set same change amount same as new amount
173                    group.setChangeAmount(group.getAmount());
174                    CreditMemoAccountRevision history = (CreditMemoAccountRevision) group.buildRevisionRecord(CreditMemoAccountRevision.class);
175                    history.setAccountRevisionTimestamp(dateTimeService.getCurrentTimestamp());
176                    accountHistories.add(history);
177                }
178            }
179        }
180        businessObjectService.save(accountHistories);
181    }
182
183    public void cancelCreditMemoAccountRevisions(List<CreditMemoItem> creditMemoItems, Integer postingYear, String postingPeriodCode) {
184        List<CreditMemoAccountRevision> accountHistories = new ArrayList<CreditMemoAccountRevision>();
185        for (CreditMemoItem item : creditMemoItems) {
186            Map<PurapAccountRevisionGroup, PurapAccountRevisionGroup> historyAcctLineGroups = buildAccountHistoryGroups(item, postingYear, postingPeriodCode, CreditMemoAccountRevision.class);
187            // first handle existing account line changes
188            for (PurapAccountRevisionGroup histGroup : historyAcctLineGroups.keySet()) {
189                // negate the amount
190                histGroup.setChangeAmount(histGroup.getAmount().negated());
191                // build history record and save
192                CreditMemoAccountRevision history = (CreditMemoAccountRevision) histGroup.buildRevisionRecord(CreditMemoAccountRevision.class);
193                history.setAccountRevisionTimestamp(dateTimeService.getCurrentTimestamp());
194                accountHistories.add(history);
195            }
196        }
197        businessObjectService.save(accountHistories);
198    }
199
200    /**
201     * Builds account history grouping data based on given list of purap account lines
202     *
203     * @param item              PurAp Item
204     * @param postingYear       Posting year
205     * @param postingPeriodCode Posting period
206     * @return
207     */
208    protected Map<PurapAccountRevisionGroup, PurapAccountRevisionGroup> buildAccountLineGroups(AccountsPayableItemBase item, Integer postingYear, String postingPeriodCode) {
209        Map<PurapAccountRevisionGroup, PurapAccountRevisionGroup> accountLineGroups = new HashMap<PurapAccountRevisionGroup, PurapAccountRevisionGroup>();
210        for (PurApAccountingLine account : item.getSourceAccountingLines()) {
211            PurapAccountRevisionGroup lineGroup = new PurapAccountRevisionGroup((PurApAccountingLineBase) account);
212            lineGroup.setPostingYear(postingYear);
213            lineGroup.setPostingPeriodCode(postingPeriodCode);
214            if ((accountLineGroups.get(lineGroup)) == null) {
215                accountLineGroups.put(lineGroup, lineGroup);
216            } else {
217                accountLineGroups.get(lineGroup).combineEntry((PurApAccountingLineBase) account);
218            }
219        }
220        return accountLineGroups;
221    }
222
223    /**
224     * Builds account history group based on existing account history lines
225     *
226     * @param item              PurAp item
227     * @param postingYear       Posting year
228     * @param postingPeriodCode Posting period code
229     * @param clazz             History class
230     * @return Map of account history groups
231     */
232    protected Map<PurapAccountRevisionGroup, PurapAccountRevisionGroup> buildAccountHistoryGroups(AccountsPayableItemBase item, Integer postingYear, String postingPeriodCode, Class<? extends PurApAccountingLineBase> clazz) {
233        Map<PurapAccountRevisionGroup, PurapAccountRevisionGroup> historyGroups = new HashMap<PurapAccountRevisionGroup, PurapAccountRevisionGroup>();
234        // find the current sum value from history table and adjusts the amount
235        Map<String, Object> fieldValues = new HashMap<String, Object>();
236        fieldValues.put("itemIdentifier", item.getItemIdentifier());
237        Collection<PurApAccountingLineBase> existingAccounts = (Collection<PurApAccountingLineBase>) businessObjectService.findMatching(clazz, fieldValues);
238        if (existingAccounts != null && !existingAccounts.isEmpty()) {
239            for (PurApAccountingLineBase existAcct : existingAccounts) {
240                PurapAccountRevisionGroup historyGroup = new PurapAccountRevisionGroup(existAcct);
241                historyGroup.setPostingYear(postingYear);
242                historyGroup.setPostingPeriodCode(postingPeriodCode);
243                if ((historyGroups.get(historyGroup)) == null) {
244                    historyGroups.put(historyGroup, historyGroup);
245                } else {
246                    historyGroups.get(historyGroup).combineEntry((PaymentRequestAccount) existAcct);
247                }
248            }
249        }
250        return historyGroups;
251    }
252
253    /**
254     * Gets the businessObjectService attribute.
255     *
256     * @return Returns the businessObjectService.
257     */
258    public BusinessObjectService getBusinessObjectService() {
259        return businessObjectService;
260    }
261
262    /**
263     * Sets the businessObjectService attribute value.
264     *
265     * @param businessObjectService The businessObjectService to set.
266     */
267    public void setBusinessObjectService(BusinessObjectService businessObjectService) {
268        this.businessObjectService = businessObjectService;
269    }
270
271    /**
272     * Gets the dateTimeService attribute.
273     *
274     * @return Returns the dateTimeService.
275     */
276    public DateTimeService getDateTimeService() {
277        return dateTimeService;
278    }
279
280    /**
281     * Sets the dateTimeService attribute value.
282     *
283     * @param dateTimeService The dateTimeService to set.
284     */
285    public void setDateTimeService(DateTimeService dateTimeService) {
286        this.dateTimeService = dateTimeService;
287    }
288
289}