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.module.endow.document.service.impl;
017    
018    import java.math.BigDecimal;
019    import java.util.ArrayList;
020    import java.util.List;
021    
022    import org.kuali.kfs.module.endow.businessobject.EndowmentTransactionLine;
023    import org.kuali.kfs.module.endow.businessobject.EndowmentTransactionSecurity;
024    import org.kuali.kfs.module.endow.businessobject.EndowmentTransactionTaxLotLine;
025    import org.kuali.kfs.module.endow.businessobject.HoldingTaxLot;
026    import org.kuali.kfs.module.endow.businessobject.Security;
027    import org.kuali.kfs.module.endow.document.EndowmentUnitShareAdjustmentDocument;
028    import org.kuali.kfs.module.endow.document.service.HoldingTaxLotService;
029    import org.kuali.kfs.module.endow.document.service.SecurityService;
030    import org.kuali.kfs.module.endow.document.service.UpdateUnitShareAdjustmentDocumentTaxLotsService;
031    import org.kuali.kfs.module.endow.util.KEMCalculationRoundingHelper;
032    import org.kuali.rice.kns.util.ObjectUtils;
033    
034    public class UpdateUnitShareAdjustmentDocumentTaxLotsServiceImpl implements UpdateUnitShareAdjustmentDocumentTaxLotsService {
035    
036        private HoldingTaxLotService taxLotService;
037        private SecurityService securityService;
038    
039        /**
040         * @see org.kuali.kfs.module.endow.document.service.UpdateUnitShareAdjustmentDocumentTaxLotsService#updateTransactionLineTaxLots(boolean,
041         *      org.kuali.kfs.module.endow.document.EndowmentUnitShareAdjustmentDocument,
042         *      org.kuali.kfs.module.endow.businessobject.EndowmentTransactionLine, boolean)
043         */
044        public void updateTransactionLineTaxLots(boolean isUpdate, EndowmentUnitShareAdjustmentDocument unitShareAdjustmentDocument, EndowmentTransactionLine transLine, boolean isSource) {
045            EndowmentTransactionSecurity endowmentTransactionSecurity = unitShareAdjustmentDocument.getSourceTransactionSecurity();
046    
047            Security security = securityService.getByPrimaryKey(endowmentTransactionSecurity.getSecurityID());
048            if (ObjectUtils.isNotNull(security)) {
049    
050                List<HoldingTaxLot> holdingTaxLots = new ArrayList<HoldingTaxLot>();
051    
052                if (isUpdate) {
053                    List<EndowmentTransactionTaxLotLine> existingTransactionLines = transLine.getTaxLotLines();
054                    for (EndowmentTransactionTaxLotLine endowmentTransactionTaxLotLine : existingTransactionLines) {
055                        HoldingTaxLot holdingTaxLot = taxLotService.getByPrimaryKey(transLine.getKemid(), endowmentTransactionSecurity.getSecurityID(), endowmentTransactionSecurity.getRegistrationCode(), endowmentTransactionTaxLotLine.getTransactionHoldingLotNumber(), transLine.getTransactionIPIndicatorCode());
056    
057                        if (ObjectUtils.isNotNull(holdingTaxLot)) {
058                            holdingTaxLots.add(holdingTaxLot);
059                        }
060                    }
061    
062                    transLine.getTaxLotLines().clear();
063                }
064                else {
065                    transLine.getTaxLotLines().clear();
066                    holdingTaxLots = taxLotService.getAllTaxLotsWithPositiveUnits(transLine.getKemid(), endowmentTransactionSecurity.getSecurityID(), endowmentTransactionSecurity.getRegistrationCode(), transLine.getTransactionIPIndicatorCode());
067                }
068    
069                BigDecimal taxLotsTotalUnits = BigDecimal.ZERO;
070    
071                if (holdingTaxLots != null) {
072                    for (HoldingTaxLot holdingTaxLot : holdingTaxLots) {
073                        EndowmentTransactionTaxLotLine endowmentTransactionTaxLotLine = new EndowmentTransactionTaxLotLine();
074                        endowmentTransactionTaxLotLine.setDocumentNumber(unitShareAdjustmentDocument.getDocumentNumber());
075                        endowmentTransactionTaxLotLine.setDocumentLineNumber(transLine.getTransactionLineNumber());
076                        endowmentTransactionTaxLotLine.setTransactionHoldingLotNumber(holdingTaxLot.getLotNumber().intValue());
077                        endowmentTransactionTaxLotLine.setKemid(transLine.getKemid());
078                        endowmentTransactionTaxLotLine.setSecurityID(holdingTaxLot.getSecurityId());
079                        endowmentTransactionTaxLotLine.setRegistrationCode(holdingTaxLot.getRegistrationCode());
080                        endowmentTransactionTaxLotLine.setIpIndicator(holdingTaxLot.getIncomePrincipalIndicator());
081                        endowmentTransactionTaxLotLine.setLotAcquiredDate(holdingTaxLot.getAcquiredDate());
082                        // set it just for future computation
083                        endowmentTransactionTaxLotLine.setLotUnits(holdingTaxLot.getUnits());
084                        transLine.getTaxLotLines().add(endowmentTransactionTaxLotLine);
085    
086                        taxLotsTotalUnits = taxLotsTotalUnits.add(holdingTaxLot.getUnits());
087    
088                        // set the new lot indicator
089                        endowmentTransactionTaxLotLine.setNewLotIndicator(false);
090                    }
091                }
092    
093                if (transLine.getTaxLotLines() != null) {
094                    BigDecimal totalUnits = BigDecimal.ZERO;
095    
096                    EndowmentTransactionTaxLotLine oldestTaxLot = null;
097                    for (EndowmentTransactionTaxLotLine endowmentTransactionTaxLotLine : transLine.getTaxLotLines()) {
098                        if (endowmentTransactionTaxLotLine.getTransactionHoldingLotNumber().compareTo(1) != 0) {
099                            oldestTaxLot = endowmentTransactionTaxLotLine;
100                        }
101                        BigDecimal percentage = KEMCalculationRoundingHelper.divide(endowmentTransactionTaxLotLine.getLotUnits(), taxLotsTotalUnits, 5);
102                        endowmentTransactionTaxLotLine.setLotUnits(KEMCalculationRoundingHelper.multiply(percentage, transLine.getTransactionUnits().bigDecimalValue(), 0));
103    
104                        totalUnits = totalUnits.add(endowmentTransactionTaxLotLine.getLotUnits());
105    
106                        if (isSource) {
107                            endowmentTransactionTaxLotLine.setLotUnits(endowmentTransactionTaxLotLine.getLotUnits().negate());
108                        }
109                    }
110    
111                    BigDecimal transLineUnits = transLine.getTransactionUnits().bigDecimalValue();
112                    adjustTaxLotsUnits(totalUnits, transLineUnits, oldestTaxLot, isSource);
113                }
114            }
115        }
116    
117    
118        /**
119         * Adjusts the oldest tax lot units if the transaction line units do not match the total of the tax lot units.
120         * 
121         * @param totalTaxLotsUnits
122         * @param transLineUnits
123         * @param oldestTaxLot
124         * @param isSource
125         */
126        private void adjustTaxLotsUnits(BigDecimal totalTaxLotsUnits, BigDecimal transLineUnits, EndowmentTransactionTaxLotLine oldestTaxLot, boolean isSource) {
127    
128            if (totalTaxLotsUnits.compareTo(transLineUnits) != 0 && oldestTaxLot != null) {
129                BigDecimal diff = transLineUnits.subtract(totalTaxLotsUnits);
130    
131                if (isSource) {
132                    oldestTaxLot.setLotUnits(oldestTaxLot.getLotUnits().add(diff.negate()));
133                }
134                else {
135                    oldestTaxLot.setLotUnits(oldestTaxLot.getLotUnits().add(diff));
136                }
137            }
138    
139        }
140    
141        /**
142         * Gets the taxLotService.
143         * 
144         * @return taxLotService
145         */
146        public HoldingTaxLotService getTaxLotService() {
147            return taxLotService;
148        }
149    
150        /**
151         * Sets the taxLotService.
152         * 
153         * @param taxLotService
154         */
155        public void setTaxLotService(HoldingTaxLotService taxLotService) {
156            this.taxLotService = taxLotService;
157        }
158    
159        /**
160         * Gets the securityService.
161         * 
162         * @return securityService
163         */
164        public SecurityService getSecurityService() {
165            return securityService;
166        }
167    
168        /**
169         * Sets the securityService.
170         * 
171         * @param securityService
172         */
173        public void setSecurityService(SecurityService securityService) {
174            this.securityService = securityService;
175        }
176    
177    }