001    /**
002     * Copyright 2004-2013 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.hr.lm.balancetransfer;
017    
018    import java.math.BigDecimal;
019    import java.sql.Date;
020    import java.util.ArrayList;
021    import java.util.List;
022    
023    import org.kuali.hr.lm.accrual.AccrualCategory;
024    import org.kuali.hr.lm.accrual.AccrualCategoryRule;
025    import org.kuali.hr.lm.leaveblock.LeaveBlock;
026    import org.kuali.hr.time.HrBusinessObject;
027    import org.kuali.hr.time.service.base.TkServiceLocator;
028    import org.kuali.hr.time.util.TkConstants;
029    import org.kuali.rice.kim.api.identity.Person;
030    import org.kuali.rice.krad.util.ObjectUtils;
031    
032    public class BalanceTransfer extends HrBusinessObject {
033    
034            private static final long serialVersionUID = 6948695780968441016L;
035            
036            private String balanceTransferId;
037            private String documentHeaderId;
038            private String accrualCategoryRule;
039            private String principalId;
040            private String toAccrualCategory;
041            private String fromAccrualCategory;
042            private BigDecimal transferAmount;
043            private BigDecimal amountTransferred;
044            private BigDecimal forfeitedAmount;
045            private String leaveCalendarDocumentId;
046    
047            private String status;
048            private String forfeitedLeaveBlockId;
049            private String accruedLeaveBlockId;
050            private String debitedLeaveBlockId;
051            private String sstoId;
052            
053            private Person principal;
054            
055            public String getPrincipalId() {
056                    return principalId;
057            }
058    
059            public void setPrincipalId(String principalId) {
060                    this.principalId = principalId;
061            }
062    
063            public String getToAccrualCategory() {
064                    return toAccrualCategory;
065            }
066    
067            public void setToAccrualCategory(String toAccrualCategory) {
068                    this.toAccrualCategory = toAccrualCategory;
069            }
070    
071            public String getFromAccrualCategory() {
072                    return fromAccrualCategory;
073            }
074    
075            public void setFromAccrualCategory(String fromAccrualCategory) {
076                    this.fromAccrualCategory = fromAccrualCategory;
077            }
078    
079            public BigDecimal getTransferAmount() {
080                    return transferAmount;
081            }
082    
083            public void setTransferAmount(BigDecimal transferAmount) {
084                    this.transferAmount = transferAmount;
085            }
086    
087            public BigDecimal getForfeitedAmount() {
088                    return forfeitedAmount;
089            }
090    
091            public void setForfeitedAmount(BigDecimal forfeitedAmount) {
092                    this.forfeitedAmount = forfeitedAmount;
093            }
094            
095            public String getBalanceTransferId() {
096                    return balanceTransferId;
097            }
098    
099            public void setBalanceTransferId(String balanceTransferId) {
100                    this.balanceTransferId = balanceTransferId;
101            }
102            
103            public String getAccrualCategoryRule() {
104                    return accrualCategoryRule;
105            }
106    
107            public void setAccrualCategoryRule(String accrualCategoryRule) {
108                    this.accrualCategoryRule = accrualCategoryRule;
109            }
110    
111            @Override
112            protected String getUniqueKey() {
113                    return balanceTransferId;
114            }
115    
116            @Override
117            public String getId() {
118                    return getBalanceTransferId();
119            }
120    
121            @Override
122            public void setId(String id) {
123                    setBalanceTransferId(id);
124            }
125    
126            public Person getPrincipal() {
127                    return principal;
128            }
129    
130            public void setPrincipal(Person principal) {
131                    this.principal = principal;
132            }
133    
134            public AccrualCategory getCreditedAccrualCategory() {
135                    return TkServiceLocator.getAccrualCategoryService().getAccrualCategory(toAccrualCategory, super.getEffectiveDate());
136            }
137    
138            public AccrualCategory getDebitedAccrualCategory() {
139                    return TkServiceLocator.getAccrualCategoryService().getAccrualCategory(fromAccrualCategory, super.getEffectiveDate());
140            }
141    
142            public String getLeaveCalendarDocumentId() {
143                    return leaveCalendarDocumentId;
144            }
145    
146            public void setLeaveCalendarDocumentId(String leaveCalendarDocumentId) {
147                    this.leaveCalendarDocumentId = leaveCalendarDocumentId;
148            }
149    
150            /**
151             * Returns a balance transfer object adjusted for the new transfer amount.
152             * 
153             * "this" must be a default initialized balance transfer. i.e. transfer amount plus forfeited amount
154             * equal to the amount of leave in excess of the from accrual category's max balance for the given principal.
155             * 
156             * calling this method without first validating the supplied transfer amount via BalanceTransferValidationUtils may produce undesired results.
157             *
158             * @param transferAmount The desired transfer amount
159             * @return A balance transfer object with forfeited and amount transfer amounts adjusted to transferAmount
160             */
161            public BalanceTransfer adjust(BigDecimal transferAmount) {
162                    BigDecimal difference = this.transferAmount.subtract(transferAmount);
163                    AccrualCategoryRule aRule = TkServiceLocator.getAccrualCategoryRuleService().getAccrualCategoryRule(accrualCategoryRule);
164                    //technically if there is forfeiture, then the transfer amount has already been maximized
165                    //via BalanceTransferService::initializeTransfer(...)
166                    //i.o.w. transfer amount cannot be increased.
167                    //this method is written with the intention of eventually allowing end user to adjust the transfer
168                    //amount as many times as they wish before submitting. Currently they cannot.
169                    if(difference.signum() < 0) {
170                            //transfer amount is being increased.
171                            if(forfeitedAmount.compareTo(BigDecimal.ZERO) > 0) {
172                                    //transfer amount has already been maximized.
173                                    if(forfeitedAmount.compareTo(difference.abs()) >= 0)
174                                            // there is enough leave in the forfeited amount to take out the difference.
175                                            forfeitedAmount = forfeitedAmount.subtract(difference.abs());
176                                    else
177                                            // the difference zero's the forfeited amount.
178                                            forfeitedAmount = BigDecimal.ZERO;
179                            }
180                            // a forfeited amount equal to zero with an increase in the transfer amount
181                            // does not produce forfeiture.
182                            // forfeiture cannot be negative.
183                    }
184                    else if (difference.signum() > 0) {
185                            //transfer amount is being decreased
186                            forfeitedAmount = forfeitedAmount.add(difference);
187                    }
188    
189                    this.transferAmount = transferAmount;
190    
191                    if(ObjectUtils.isNotNull(aRule.getMaxBalanceTransferConversionFactor()))
192                            this.amountTransferred = transferAmount.multiply(aRule.getMaxBalanceTransferConversionFactor()).setScale(2);
193                    else
194                            this.amountTransferred = transferAmount;
195                    
196                    return this;
197            }
198    
199            public List<LeaveBlock> getLeaveBlocks() {
200                    List<LeaveBlock> leaveBlocks = new ArrayList<LeaveBlock>();
201                    if (getForfeitedLeaveBlockId() != null) {
202                        leaveBlocks.add(TkServiceLocator.getLeaveBlockService().getLeaveBlock(forfeitedLeaveBlockId));
203            }
204            if (getAccruedLeaveBlockId() != null) {
205                        leaveBlocks.add(TkServiceLocator.getLeaveBlockService().getLeaveBlock(accruedLeaveBlockId));
206            }
207            if (getDebitedLeaveBlockId() != null) {
208                        leaveBlocks.add(TkServiceLocator.getLeaveBlockService().getLeaveBlock(debitedLeaveBlockId));
209            }
210    
211                    return leaveBlocks;
212            }
213    
214            public String getStatus() {
215                    return status;
216            }
217    
218            public void setStatus(String status) {
219                    this.status = status;
220            }
221    
222            public void disapprove() {
223                    TkServiceLocator.getLeaveBlockService().updateLeaveBlock(null, principalId);
224                    setStatus(TkConstants.ROUTE_STATUS.DISAPPROVED);
225            }
226    
227            public void approve() {
228    
229                    setStatus(TkConstants.ROUTE_STATUS.FINAL);
230            }
231    
232            public void cancel() {
233    
234                    setStatus(TkConstants.ROUTE_STATUS.CANCEL);
235            }
236    
237            public String getAccruedLeaveBlockId() {
238                    return accruedLeaveBlockId;
239            }
240    
241            public void setAccruedLeaveBlockId(String accruedLeaveBlockId) {
242                    this.accruedLeaveBlockId = accruedLeaveBlockId;
243            }
244    
245            public String getForfeitedLeaveBlockId() {
246                    return forfeitedLeaveBlockId;
247            }
248    
249            public void setForfeitedLeaveBlockId(String forfeitedLeaveBlockId) {
250                    this.forfeitedLeaveBlockId = forfeitedLeaveBlockId;
251            }
252    
253            public String getDebitedLeaveBlockId() {
254                    return debitedLeaveBlockId;
255            }
256    
257            public void setDebitedLeaveBlockId(String debitedLeaveBlockId) {
258                    this.debitedLeaveBlockId = debitedLeaveBlockId;
259            }
260    
261            public BigDecimal getAmountTransferred() {
262                    return amountTransferred;
263            }
264    
265            public void setAmountTransferred(BigDecimal amountTransferrerd) {
266                    this.amountTransferred = amountTransferrerd;
267            }
268            
269            public String getSstoId() {
270                    return sstoId;
271            }
272    
273            public void setSstoId(String sstoId) {
274                    this.sstoId = sstoId;
275            }
276    
277            public String getDocumentHeaderId() {
278                    return documentHeaderId;
279            }
280    
281            public void setDocumentHeaderId(String documentHeaderId) {
282                    this.documentHeaderId = documentHeaderId;
283            }
284            
285            //Comparable for order handling of more than one transfer occurring during the same
286            //action frequency interval?
287            
288    }