001/*
002 * The Kuali Financial System, a comprehensive financial management system for higher education.
003 * 
004 * Copyright 2005-2014 The Kuali Foundation
005 * 
006 * This program is free software: you can redistribute it and/or modify
007 * it under the terms of the GNU Affero General Public License as
008 * published by the Free Software Foundation, either version 3 of the
009 * License, or (at your option) any later version.
010 * 
011 * This program is distributed in the hope that it will be useful,
012 * but WITHOUT ANY WARRANTY; without even the implied warranty of
013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
014 * GNU Affero General Public License for more details.
015 * 
016 * You should have received a copy of the GNU Affero General Public License
017 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
018 */
019package org.kuali.kfs.fp.businessobject;
020
021import org.kuali.kfs.sys.context.KualiTestBase;
022import org.kuali.rice.core.api.util.type.KualiDecimal;
023
024public class CurrencyDetailTest extends KualiTestBase {
025    public enum CurrencyDetailAmountFixture {
026        GOOD_POSITIVE_AMOUNT(500.0, 250.0, 100.0, 50.0, 25.0, 10.0, 5.0), BAD_POSITIVE_AMOUNT(367.0, 367.0, 367.0, 367.0, 367.0, 367.0, 367.5), ALL_FIVES_AMOUNT(500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0), NULL_AMOUNT, ZERO_AMOUNT(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0), NEGATIVE_AMOUNT(-500.0, -500.0, -500.0, -500.0, -500.0, -500.0, -500.0), ALL_TENS_AMOUNT(1000.0, 1000.0, 1000.0, 1000.0, 1000.0, 1000.0, 1000.0);
027
028        private KualiDecimal hundredDollarAmount;
029        private KualiDecimal fiftyDollarAmount;
030        private KualiDecimal twentyDollarAmount;
031        private KualiDecimal tenDollarAmount;
032        private KualiDecimal fiveDollarAmount;
033        private KualiDecimal twoDollarAmount;
034        private KualiDecimal oneDollarAmount;
035
036        private CurrencyDetailAmountFixture() {
037        }
038
039        private CurrencyDetailAmountFixture(double hundredDollarAmount, double fiftyDollarAmount, double twentyDollarAmount, double tenDollarAmount, double fiveDollarAmount, double twoDollarAmount, double oneDollarAmount) {
040            this.hundredDollarAmount = new KualiDecimal(hundredDollarAmount);
041            this.fiftyDollarAmount = new KualiDecimal(fiftyDollarAmount);
042            this.twentyDollarAmount = new KualiDecimal(twentyDollarAmount);
043            this.tenDollarAmount = new KualiDecimal(tenDollarAmount);
044            this.fiveDollarAmount = new KualiDecimal(fiveDollarAmount);
045            this.twoDollarAmount = new KualiDecimal(twoDollarAmount);
046            this.oneDollarAmount = new KualiDecimal(oneDollarAmount);
047        }
048
049        public CurrencyDetail convertToCurrencyDetail() {
050            CurrencyDetail detail = new CurrencyDetail();
051            detail.setFinancialDocumentHundredDollarAmount(this.hundredDollarAmount);
052            detail.setFinancialDocumentFiftyDollarAmount(this.fiftyDollarAmount);
053            detail.setFinancialDocumentTwentyDollarAmount(this.twentyDollarAmount);
054            detail.setFinancialDocumentTenDollarAmount(this.tenDollarAmount);
055            detail.setFinancialDocumentFiveDollarAmount(this.fiveDollarAmount);
056            detail.setFinancialDocumentTwoDollarAmount(this.twoDollarAmount);
057            detail.setFinancialDocumentOneDollarAmount(this.oneDollarAmount);
058
059            return detail;
060        }
061    }
062
063    public enum CurrencyDetailCountFixture {
064        GOOD_POSITIVE_COUNT(new Integer(5), new Integer(10), new Integer(25), new Integer(50), new Integer(100), new Integer(250), new Integer(500)), ALL_FIVE_HUNDREDS_COUNT(new Integer(5), new Integer(5), new Integer(5), new Integer(5), new Integer(5), new Integer(5), new Integer(5)), NULL_COUNT, ZERO_COUNT(new Integer(0), new Integer(0), new Integer(0), new Integer(0), new Integer(0), new Integer(0), new Integer(0)), NEGATIVE_COUNT(new Integer(-5), new Integer(-5), new Integer(-5), new Integer(-5), new Integer(-5), new Integer(-5), new Integer(-5));
065
066        private Integer hundredDollarCount;
067        private Integer fiftyDollarCount;
068        private Integer twentyDollarCount;
069        private Integer tenDollarCount;
070        private Integer fiveDollarCount;
071        private Integer twoDollarCount;
072        private Integer oneDollarCount;
073
074        private CurrencyDetailCountFixture() {
075        }
076
077        private CurrencyDetailCountFixture(Integer hundredDollarCount, Integer fiftyDollarCount, Integer twentyDollarCount, Integer tenDollarCount, Integer fiveDollarCount, Integer twoDollarCount, Integer oneDollarCount) {
078            this.hundredDollarCount = hundredDollarCount;
079            this.fiftyDollarCount = fiftyDollarCount;
080            this.twentyDollarCount = twentyDollarCount;
081            this.tenDollarCount = tenDollarCount;
082            this.fiveDollarCount = fiveDollarCount;
083            this.twoDollarCount = twoDollarCount;
084            this.oneDollarCount = oneDollarCount;
085        }
086
087        public CurrencyDetail convertToCurrencyDetail() {
088            CurrencyDetail detail = new CurrencyDetail();
089            detail.setHundredDollarCount(this.hundredDollarCount);
090            detail.setFiftyDollarCount(this.fiftyDollarCount);
091            detail.setTwentyDollarCount(this.twentyDollarCount);
092            detail.setTenDollarCount(this.tenDollarCount);
093            detail.setFiveDollarCount(this.fiveDollarCount);
094            detail.setTwoDollarCount(this.twoDollarCount);
095            detail.setOneDollarCount(this.oneDollarCount);
096
097            return detail;
098        }
099    }
100
101    public void testAmountToCountConversion() {
102        CurrencyDetail goodAmount = CurrencyDetailAmountFixture.GOOD_POSITIVE_AMOUNT.convertToCurrencyDetail();
103        assertEquals(goodAmount.getHundredDollarCount(), new Integer(5));
104        assertEquals(goodAmount.getFiftyDollarCount(), new Integer(5));
105        assertEquals(goodAmount.getTwentyDollarCount(), new Integer(5));
106        assertEquals(goodAmount.getTenDollarCount(), new Integer(5));
107        assertEquals(goodAmount.getFiveDollarCount(), new Integer(5));
108        assertEquals(goodAmount.getTwoDollarCount(), new Integer(5));
109        assertEquals(goodAmount.getOneDollarCount(), new Integer(5));
110    }
111
112    public void testCountToAmountConversion() {
113        CurrencyDetail goodCount = CurrencyDetailCountFixture.GOOD_POSITIVE_COUNT.convertToCurrencyDetail();
114        assertEquals(goodCount.getFinancialDocumentHundredDollarAmount(), new KualiDecimal(500));
115        assertEquals(goodCount.getFinancialDocumentFiftyDollarAmount(), new KualiDecimal(500));
116        assertEquals(goodCount.getFinancialDocumentTwentyDollarAmount(), new KualiDecimal(500));
117        assertEquals(goodCount.getFinancialDocumentTenDollarAmount(), new KualiDecimal(500));
118        assertEquals(goodCount.getFinancialDocumentFiveDollarAmount(), new KualiDecimal(500));
119        assertEquals(goodCount.getFinancialDocumentTwoDollarAmount(), new KualiDecimal(500));
120        assertEquals(goodCount.getFinancialDocumentOneDollarAmount(), new KualiDecimal(500));
121    }
122
123    public void testZeroOutAmounts() {
124        CurrencyDetail zeroAmountControl = CurrencyDetailAmountFixture.ZERO_AMOUNT.convertToCurrencyDetail();
125        CurrencyDetail zeroAmount = CurrencyDetailAmountFixture.ZERO_AMOUNT.convertToCurrencyDetail();
126        CurrencyDetail nullAmount = CurrencyDetailAmountFixture.NULL_AMOUNT.convertToCurrencyDetail();
127        CurrencyDetail goodAmount = CurrencyDetailAmountFixture.GOOD_POSITIVE_AMOUNT.convertToCurrencyDetail();
128        CurrencyDetail negativeAmount = CurrencyDetailAmountFixture.NEGATIVE_AMOUNT.convertToCurrencyDetail();
129
130        zeroAmount.zeroOutAmounts();
131        assertDetailAmountsEqual(zeroAmount, zeroAmountControl);
132        nullAmount.zeroOutAmounts();
133        assertDetailAmountsEqual(nullAmount, zeroAmountControl);
134        goodAmount.zeroOutAmounts();
135        assertDetailAmountsEqual(goodAmount, zeroAmountControl);
136        negativeAmount.zeroOutAmounts();
137        assertDetailAmountsEqual(negativeAmount, zeroAmountControl);
138
139        CurrencyDetail goodCount = CurrencyDetailCountFixture.GOOD_POSITIVE_COUNT.convertToCurrencyDetail();
140        CurrencyDetail zeroCount = CurrencyDetailCountFixture.ZERO_COUNT.convertToCurrencyDetail();
141        CurrencyDetail negativeCount = CurrencyDetailCountFixture.NEGATIVE_COUNT.convertToCurrencyDetail();
142        CurrencyDetail nullCount = CurrencyDetailCountFixture.NULL_COUNT.convertToCurrencyDetail();
143
144        zeroCount.zeroOutAmounts();
145        assertDetailAmountsEqual(zeroCount, zeroAmountControl);
146        nullCount.zeroOutAmounts();
147        assertDetailAmountsEqual(nullCount, zeroAmountControl);
148        goodCount.zeroOutAmounts();
149        assertDetailAmountsEqual(goodCount, zeroAmountControl);
150        negativeCount.zeroOutAmounts();
151        assertDetailAmountsEqual(negativeCount, zeroAmountControl);
152    }
153
154    public void testZeroOutUnpopulatedAmounts() {
155        CurrencyDetail zeroAmountControl = CurrencyDetailAmountFixture.ZERO_AMOUNT.convertToCurrencyDetail();
156        CurrencyDetail zeroAmount = CurrencyDetailAmountFixture.ZERO_AMOUNT.convertToCurrencyDetail();
157        CurrencyDetail nullAmount = CurrencyDetailAmountFixture.NULL_AMOUNT.convertToCurrencyDetail();
158        CurrencyDetail goodAmount = CurrencyDetailAmountFixture.GOOD_POSITIVE_AMOUNT.convertToCurrencyDetail();
159
160        zeroAmount.zeroOutUnpopulatedAmounts();
161        assertDetailAmountsEqual(zeroAmount, zeroAmountControl);
162        nullAmount.zeroOutUnpopulatedAmounts();
163        assertDetailAmountsEqual(nullAmount, zeroAmountControl);
164        goodAmount.zeroOutUnpopulatedAmounts();
165        assertDetailAmountsNotEqual(goodAmount, zeroAmountControl);
166
167        goodAmount.setFinancialDocumentHundredDollarAmount(null);
168        goodAmount.setFinancialDocumentTwentyDollarAmount(null);
169        goodAmount.setFinancialDocumentFiveDollarAmount(null);
170        goodAmount.setFinancialDocumentTwoDollarAmount(null);
171        CurrencyDetail semiPopulatedAmount = CurrencyDetailAmountFixture.GOOD_POSITIVE_AMOUNT.convertToCurrencyDetail();
172        semiPopulatedAmount.setFinancialDocumentHundredDollarAmount(KualiDecimal.ZERO);
173        semiPopulatedAmount.setFinancialDocumentTwentyDollarAmount(KualiDecimal.ZERO);
174        semiPopulatedAmount.setFinancialDocumentFiveDollarAmount(KualiDecimal.ZERO);
175        semiPopulatedAmount.setFinancialDocumentTwoDollarAmount(KualiDecimal.ZERO);
176        goodAmount.zeroOutUnpopulatedAmounts();
177        assertDetailAmountsEqual(goodAmount, semiPopulatedAmount);
178
179        CurrencyDetail goodCount = CurrencyDetailCountFixture.GOOD_POSITIVE_COUNT.convertToCurrencyDetail();
180        CurrencyDetail zeroCount = CurrencyDetailCountFixture.ZERO_COUNT.convertToCurrencyDetail();
181        CurrencyDetail nullCount = CurrencyDetailCountFixture.NULL_COUNT.convertToCurrencyDetail();
182
183        zeroCount.zeroOutUnpopulatedAmounts();
184        assertDetailAmountsEqual(zeroCount, zeroAmountControl);
185        nullCount.zeroOutUnpopulatedAmounts();
186        assertDetailAmountsEqual(nullCount, zeroAmountControl);
187        goodCount.zeroOutUnpopulatedAmounts();
188        assertDetailAmountsNotEqual(goodCount, zeroAmountControl);
189    }
190
191    public void testAdd() {
192        CurrencyDetail zeroAmountControl = CurrencyDetailAmountFixture.ZERO_AMOUNT.convertToCurrencyDetail();
193        CurrencyDetail zeroAmount = CurrencyDetailAmountFixture.ZERO_AMOUNT.convertToCurrencyDetail();
194        CurrencyDetail nullAmount = CurrencyDetailAmountFixture.NULL_AMOUNT.convertToCurrencyDetail();
195        CurrencyDetail goodAmountControl = CurrencyDetailAmountFixture.ALL_FIVES_AMOUNT.convertToCurrencyDetail();
196        CurrencyDetail goodAmount = CurrencyDetailAmountFixture.ALL_FIVES_AMOUNT.convertToCurrencyDetail();
197        CurrencyDetail negativeAmountControl = CurrencyDetailAmountFixture.NEGATIVE_AMOUNT.convertToCurrencyDetail();
198        CurrencyDetail negativeAmount = CurrencyDetailAmountFixture.NEGATIVE_AMOUNT.convertToCurrencyDetail();
199
200        zeroAmount.add(zeroAmountControl);
201        assertDetailAmountsEqual(zeroAmount, zeroAmountControl);
202        nullAmount.add(zeroAmountControl);
203        assertDetailAmountsEqual(nullAmount, zeroAmountControl);
204        goodAmount.add(zeroAmountControl);
205        assertDetailAmountsEqual(goodAmount, goodAmountControl);
206        negativeAmount.add(zeroAmountControl);
207        assertDetailAmountsEqual(negativeAmount, negativeAmountControl);
208        goodAmount.add(negativeAmount);
209        assertDetailAmountsEqual(goodAmount, zeroAmountControl);
210    }
211
212    public void testSubtract() {
213        CurrencyDetail zeroAmountControl = CurrencyDetailAmountFixture.ZERO_AMOUNT.convertToCurrencyDetail();
214        CurrencyDetail zeroAmount = CurrencyDetailAmountFixture.ZERO_AMOUNT.convertToCurrencyDetail();
215        CurrencyDetail nullAmount = CurrencyDetailAmountFixture.NULL_AMOUNT.convertToCurrencyDetail();
216        CurrencyDetail goodAmountControl = CurrencyDetailAmountFixture.ALL_FIVES_AMOUNT.convertToCurrencyDetail();
217        CurrencyDetail goodAmount = CurrencyDetailAmountFixture.ALL_FIVES_AMOUNT.convertToCurrencyDetail();
218        CurrencyDetail negativeAmountControl = CurrencyDetailAmountFixture.NEGATIVE_AMOUNT.convertToCurrencyDetail();
219        CurrencyDetail negativeAmount = CurrencyDetailAmountFixture.NEGATIVE_AMOUNT.convertToCurrencyDetail();
220
221        zeroAmount.subtract(zeroAmountControl);
222        assertDetailAmountsEqual(zeroAmount, zeroAmountControl);
223        nullAmount.subtract(zeroAmountControl);
224        assertDetailAmountsEqual(nullAmount, zeroAmountControl);
225        goodAmount.subtract(zeroAmountControl);
226        assertDetailAmountsEqual(goodAmount, goodAmountControl);
227        negativeAmount.subtract(zeroAmountControl);
228        assertDetailAmountsEqual(negativeAmount, negativeAmountControl);
229
230        CurrencyDetail doublePositives = new CurrencyDetail();
231        doublePositives.setFinancialDocumentHundredDollarAmount(goodAmount.getFinancialDocumentHundredDollarAmount().multiply(new KualiDecimal(2.0)));
232        doublePositives.setFinancialDocumentFiftyDollarAmount(goodAmount.getFinancialDocumentFiftyDollarAmount().multiply(new KualiDecimal(2.0)));
233        doublePositives.setFinancialDocumentTwentyDollarAmount(goodAmount.getFinancialDocumentTwentyDollarAmount().multiply(new KualiDecimal(2.0)));
234        doublePositives.setFinancialDocumentTenDollarAmount(goodAmount.getFinancialDocumentTenDollarAmount().multiply(new KualiDecimal(2.0)));
235        doublePositives.setFinancialDocumentFiveDollarAmount(goodAmount.getFinancialDocumentFiveDollarAmount().multiply(new KualiDecimal(2.0)));
236        doublePositives.setFinancialDocumentTwoDollarAmount(goodAmount.getFinancialDocumentTwoDollarAmount().multiply(new KualiDecimal(2.0)));
237        doublePositives.setFinancialDocumentOneDollarAmount(goodAmount.getFinancialDocumentOneDollarAmount().multiply(new KualiDecimal(2.0)));
238        goodAmount.subtract(negativeAmount);
239        assertDetailAmountsEqual(goodAmount, doublePositives);
240
241        negativeAmount = CurrencyDetailAmountFixture.NEGATIVE_AMOUNT.convertToCurrencyDetail();
242        goodAmount = CurrencyDetailAmountFixture.ALL_FIVES_AMOUNT.convertToCurrencyDetail();
243        CurrencyDetail doubleNegatives = new CurrencyDetail();
244        doubleNegatives.setFinancialDocumentHundredDollarAmount(negativeAmount.getFinancialDocumentHundredDollarAmount().multiply(new KualiDecimal(2.0)));
245        doubleNegatives.setFinancialDocumentFiftyDollarAmount(negativeAmount.getFinancialDocumentFiftyDollarAmount().multiply(new KualiDecimal(2.0)));
246        doubleNegatives.setFinancialDocumentTwentyDollarAmount(negativeAmount.getFinancialDocumentTwentyDollarAmount().multiply(new KualiDecimal(2.0)));
247        doubleNegatives.setFinancialDocumentTenDollarAmount(negativeAmount.getFinancialDocumentTenDollarAmount().multiply(new KualiDecimal(2.0)));
248        doubleNegatives.setFinancialDocumentFiveDollarAmount(negativeAmount.getFinancialDocumentFiveDollarAmount().multiply(new KualiDecimal(2.0)));
249        doubleNegatives.setFinancialDocumentTwoDollarAmount(negativeAmount.getFinancialDocumentTwoDollarAmount().multiply(new KualiDecimal(2.0)));
250        doubleNegatives.setFinancialDocumentOneDollarAmount(negativeAmount.getFinancialDocumentOneDollarAmount().multiply(new KualiDecimal(2.0)));
251        negativeAmount.subtract(goodAmount);
252        assertDetailAmountsEqual(negativeAmount, doubleNegatives);
253    }
254
255    public void testTotal() {
256        CurrencyDetail zeroAmount = CurrencyDetailAmountFixture.ZERO_AMOUNT.convertToCurrencyDetail();
257        assertEquals(zeroAmount.getTotalAmount(), new KualiDecimal(0.0));
258        CurrencyDetail nullAmount = CurrencyDetailAmountFixture.NULL_AMOUNT.convertToCurrencyDetail();
259        assertEquals(nullAmount.getTotalAmount(), new KualiDecimal(0.0));
260
261        CurrencyDetail goodAmount = CurrencyDetailAmountFixture.GOOD_POSITIVE_AMOUNT.convertToCurrencyDetail();
262        assertEquals(goodAmount.getTotalAmount(), new KualiDecimal(940.0));
263        CurrencyDetail negativeAmount = CurrencyDetailAmountFixture.NEGATIVE_AMOUNT.convertToCurrencyDetail();
264        assertEquals(negativeAmount.getTotalAmount(), new KualiDecimal(-3500.0));
265    }
266
267    public void testIsEmpty() {
268        CurrencyDetail zeroAmount = CurrencyDetailAmountFixture.ZERO_AMOUNT.convertToCurrencyDetail();
269        assertTrue(zeroAmount.isEmpty());
270        CurrencyDetail nullAmount = CurrencyDetailAmountFixture.NULL_AMOUNT.convertToCurrencyDetail();
271        assertTrue(nullAmount.isEmpty());
272
273        CurrencyDetail goodAmount = CurrencyDetailAmountFixture.GOOD_POSITIVE_AMOUNT.convertToCurrencyDetail();
274        assertFalse(goodAmount.isEmpty());
275        CurrencyDetail negativeAmount = CurrencyDetailAmountFixture.NEGATIVE_AMOUNT.convertToCurrencyDetail();
276        assertFalse(negativeAmount.isEmpty());
277    }
278
279    private void assertDetailAmountsEqual(CurrencyDetail tweedleDee, CurrencyDetail tweedleDum) {
280        assertEquals(tweedleDee.getFinancialDocumentHundredDollarAmount(), tweedleDum.getFinancialDocumentHundredDollarAmount());
281        assertEquals(tweedleDee.getFinancialDocumentFiftyDollarAmount(), tweedleDum.getFinancialDocumentFiftyDollarAmount());
282        assertEquals(tweedleDee.getFinancialDocumentTwentyDollarAmount(), tweedleDum.getFinancialDocumentTwentyDollarAmount());
283        assertEquals(tweedleDee.getFinancialDocumentTenDollarAmount(), tweedleDum.getFinancialDocumentTenDollarAmount());
284        assertEquals(tweedleDee.getFinancialDocumentFiveDollarAmount(), tweedleDum.getFinancialDocumentFiveDollarAmount());
285        assertEquals(tweedleDee.getFinancialDocumentTwoDollarAmount(), tweedleDum.getFinancialDocumentTwoDollarAmount());
286        assertEquals(tweedleDee.getFinancialDocumentOneDollarAmount(), tweedleDum.getFinancialDocumentOneDollarAmount());
287    }
288
289    public void assertDetailAmountsNotEqual(CurrencyDetail tweedleDee, CurrencyDetail tweedleDum) {
290        assertFalse(tweedleDee.getFinancialDocumentHundredDollarAmount().equals(tweedleDum.getFinancialDocumentHundredDollarAmount()));
291        assertFalse(tweedleDee.getFinancialDocumentFiftyDollarAmount().equals(tweedleDum.getFinancialDocumentFiftyDollarAmount()));
292        assertFalse(tweedleDee.getFinancialDocumentTwentyDollarAmount().equals(tweedleDum.getFinancialDocumentTwentyDollarAmount()));
293        assertFalse(tweedleDee.getFinancialDocumentTenDollarAmount().equals(tweedleDum.getFinancialDocumentTenDollarAmount()));
294        assertFalse(tweedleDee.getFinancialDocumentFiveDollarAmount().equals(tweedleDum.getFinancialDocumentFiveDollarAmount()));
295        assertFalse(tweedleDee.getFinancialDocumentTwoDollarAmount().equals(tweedleDum.getFinancialDocumentTwoDollarAmount()));
296        assertFalse(tweedleDee.getFinancialDocumentOneDollarAmount().equals(tweedleDum.getFinancialDocumentOneDollarAmount()));
297    }
298}