View Javadoc
1   /*
2    * The Kuali Financial System, a comprehensive financial management system for higher education.
3    * 
4    * Copyright 2005-2014 The Kuali Foundation
5    * 
6    * This program is free software: you can redistribute it and/or modify
7    * it under the terms of the GNU Affero General Public License as
8    * published by the Free Software Foundation, either version 3 of the
9    * License, or (at your option) any later version.
10   * 
11   * This program is distributed in the hope that it will be useful,
12   * but WITHOUT ANY WARRANTY; without even the implied warranty of
13   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14   * GNU Affero General Public License for more details.
15   * 
16   * You should have received a copy of the GNU Affero General Public License
17   * along with this program.  If not, see <http://www.gnu.org/licenses/>.
18   */
19  package org.kuali.kfs.module.ar.document.validation.impl;
20  
21  import static org.kuali.kfs.sys.fixture.UserNameFixture.khuntley;
22  
23  import java.math.BigDecimal;
24  import java.util.List;
25  
26  import org.kuali.kfs.module.ar.ArConstants;
27  import org.kuali.kfs.module.ar.businessobject.CustomerCreditMemoDetail;
28  import org.kuali.kfs.module.ar.businessobject.CustomerInvoiceDetail;
29  import org.kuali.kfs.module.ar.document.CustomerCreditMemoDocument;
30  import org.kuali.kfs.module.ar.document.CustomerInvoiceDocument;
31  import org.kuali.kfs.module.ar.document.service.CustomerInvoiceDocumentTestUtil;
32  import org.kuali.kfs.module.ar.fixture.CustomerInvoiceDetailFixture;
33  import org.kuali.kfs.module.ar.fixture.CustomerInvoiceDocumentFixture;
34  import org.kuali.kfs.sys.ConfigureContext;
35  import org.kuali.kfs.sys.DocumentTestUtils;
36  import org.kuali.kfs.sys.context.KualiTestBase;
37  import org.kuali.kfs.sys.context.SpringContext;
38  import org.kuali.rice.core.api.util.type.KualiDecimal;
39  import org.kuali.rice.kew.api.exception.WorkflowException;
40  import org.kuali.rice.krad.document.Document;
41  import org.kuali.rice.krad.service.DocumentService;
42  
43  @ConfigureContext(session = khuntley, shouldCommitTransactions = true)
44  public class CustomerCreditMemoDocumentRuleTest extends KualiTestBase {
45  
46      public static org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(CustomerCreditMemoDocumentRuleTest.class);
47  
48      private CustomerCreditMemoDocumentRule rule;
49      private CustomerCreditMemoDocument document;
50  
51      @Override
52      protected  void setUp() throws Exception {
53          super.setUp();
54          rule = new CustomerCreditMemoDocumentRule();
55          document = new CustomerCreditMemoDocument();
56      }
57  
58      @Override
59      protected void tearDown() throws Exception {
60          rule = null;
61          document = null;
62          super.tearDown();
63      }
64  
65      /*
66       *  This method tests if isQtyOrItemAmountEntered returns an empty string if customer doesn't enter any information
67       */
68      public void testIsQtyOrItemAmountEntered_EmptyString_True() {
69         CustomerCreditMemoDetail detail = new CustomerCreditMemoDetail();
70  
71         assertTrue(rule.isQtyOrItemAmountEntered(detail).equals(""));
72      }
73  
74      /*
75       *  This method tests if isQtyOrItemAmountEntered returns correct key if customer enteres only quantity
76       */
77     public void testIsQtyOrItemAmountEntered_Qty_True() {
78         CustomerCreditMemoDetail detail = new CustomerCreditMemoDetail();
79         detail.setCreditMemoItemQuantity(new BigDecimal(1));
80  
81         assertTrue(rule.isQtyOrItemAmountEntered(detail).equals(ArConstants.CustomerCreditMemoConstants.CUSTOMER_CREDIT_MEMO_ITEM_QUANTITY));
82      }
83  
84      /*
85       *  This method tests if isQtyOrItemAmountEntered returns correct key if customer enteres only amount
86       */
87      public void testIsQtyOrItemAmountEntered_Amount_True() {
88         CustomerCreditMemoDetail detail = new CustomerCreditMemoDetail();
89         detail.setCreditMemoItemTotalAmount(new KualiDecimal(1));
90  
91         assertTrue(rule.isQtyOrItemAmountEntered(detail).equals(ArConstants.CustomerCreditMemoConstants.CUSTOMER_CREDIT_MEMO_ITEM_TOTAL_AMOUNT));
92      }
93  
94      /*
95       *  This method tests if isQtyOrItemAmountEntered returns correct key if customer enteres both amount and quantity
96       */
97      public void testIsQtyOrItemAmountEntered_Both_True() {
98         CustomerCreditMemoDetail detail = new CustomerCreditMemoDetail();
99  
100        detail.setCreditMemoItemTotalAmount(new KualiDecimal(1));
101        detail.setCreditMemoItemQuantity(new BigDecimal(1));
102 
103        assertTrue(rule.isQtyOrItemAmountEntered(detail).equals(ArConstants.CustomerCreditMemoConstants.BOTH_QUANTITY_AND_ITEM_TOTAL_AMOUNT_ENTERED));
104     }
105 
106     /*
107      *  This method tests if isValueGreaterThanZero returns true if passed a valid value
108      */
109    public void testIsValueGreaterThanZero_True() {
110         assertTrue(rule.isValueGreaterThanZero(BigDecimal.ONE));
111     }
112 
113     /*
114      *  This method tests if isValueGreaterThanZero returns false if passed a zero.
115      */
116     public void testIsValueGreaterThanZero_False() {
117         assertFalse(rule.isValueGreaterThanZero(BigDecimal.ZERO));
118     }
119 
120     /*
121      *  This method tests if isValueGreaterThanZero returns true if passed a valid value
122      */
123     public void testIsValueGreaterThanZero_KualiDecimal_True() {
124         assertTrue(rule.isValueGreaterThanZero(new KualiDecimal(1)));
125     }
126 
127     /*
128      *  This method tests if isValueGreaterThanZero returns false if passed a zero.
129      */
130     public void testIsValueGreaterThanZero_KualiDecimal_False() {
131         assertFalse(rule.isValueGreaterThanZero(KualiDecimal.ZERO));
132     }
133 
134     /*
135      *  This method tests if isCustomerCreditMemoItemAmountLessThanEqualToInvoiceOpenItemAmount returns true if passed correct values (invoiceOpenItemAmount = creditMemoItemAmount)
136      */
137    public void testIsCustomerCreditMemoItemAmountGreaterThanInvoiceOpenItemAmount_Equal_True() {
138         CustomerCreditMemoDetail detail = new CustomerCreditMemoDetail();
139         detail.setInvoiceOpenItemAmount(new KualiDecimal(2));
140         detail.setCreditMemoItemTotalAmount(new KualiDecimal(2));
141 
142         assertTrue(rule.isCustomerCreditMemoItemAmountLessThanEqualToInvoiceOpenItemAmount(document, detail));
143     }
144 
145     /*
146      *  This method tests if isCustomerCreditMemoItemAmountLessThanEqualToInvoiceOpenItemAmount returns true if passed correct values (creditMemoItemAmount < invoiceOpenItemAmount)
147      */
148    public void testIsCustomerCreditMemoItemAmountGreaterThanInvoiceOpenItemAmount_Less_True() {
149         CustomerCreditMemoDetail detail = new CustomerCreditMemoDetail();
150         detail.setInvoiceOpenItemAmount(new KualiDecimal(2));
151         detail.setCreditMemoItemTotalAmount(new KualiDecimal(1));
152 
153         assertTrue(rule.isCustomerCreditMemoItemAmountLessThanEqualToInvoiceOpenItemAmount(document, detail));
154     }
155 
156     /*
157      *  This method tests if isCustomerCreditMemoItemAmountLessThanEqualToInvoiceOpenItemAmount returns false if passed creditMemoItemAmount > invoiceOpenItemAmount)
158      */
159     public void testIsCustomerCreditMemoItemAmountGreaterThanInvoiceOpenItemAmount_False() {
160         CustomerCreditMemoDetail detail = new CustomerCreditMemoDetail();
161         detail.setInvoiceOpenItemAmount(new KualiDecimal(1));
162         detail.setCreditMemoItemTotalAmount(new KualiDecimal(2));
163 
164         assertFalse(rule.isCustomerCreditMemoItemAmountLessThanEqualToInvoiceOpenItemAmount(document, detail));
165     }
166 
167     /*
168      *  This method tests if isCustomerCreditMemoQtyLessThanEqualToInvoiceOpenQty returns true if crm qty = invoice qty
169      */
170     public void testIsCustomerCreditMemoQtyGreaterThanInvoiceQty_Equal_True() {
171         CustomerCreditMemoDetail detail = new CustomerCreditMemoDetail();
172 
173         detail.setInvoiceOpenItemQuantity(new BigDecimal(2));
174         detail.setCreditMemoItemQuantity(new BigDecimal(2));
175 
176         assertTrue(rule.isCustomerCreditMemoQtyLessThanEqualToInvoiceOpenQty(detail));
177     }
178 
179     /*
180      *  This method tests if isCustomerCreditMemoQtyLessThanEqualToInvoiceOpenQty returns true if crm qty < invoice qty
181      */
182     public void testIsCustomerCreditMemoQtyGreaterThanInvoiceQty_Less_True() {
183         CustomerCreditMemoDetail detail = new CustomerCreditMemoDetail();
184 
185         detail.setInvoiceOpenItemQuantity(new BigDecimal(2));
186         detail.setCreditMemoItemQuantity(new BigDecimal(1));
187 
188         assertTrue(rule.isCustomerCreditMemoQtyLessThanEqualToInvoiceOpenQty(detail));
189     }
190 
191     /*
192      *  This method tests if isCustomerCreditMemoQtyLessThanEqualToInvoiceOpenQty returns false if crm qty > invoice qty
193      */
194     public void testIsCustomerCreditMemoQtyGreaterThanInvoiceQty_False() {
195         CustomerCreditMemoDetail detail = new CustomerCreditMemoDetail();
196 
197         detail.setInvoiceOpenItemQuantity(new BigDecimal(1));
198         detail.setCreditMemoItemQuantity(new BigDecimal(2));
199 
200         assertFalse(rule.isCustomerCreditMemoQtyLessThanEqualToInvoiceOpenQty(detail));
201     }
202 
203     /*
204      *  This method tests if checkIfCustomerCreditMemoQtyAndCustomerCreditMemoItemAmountValid returns true if passed valid quantity and amount
205      */
206     public void testCheckIfCustomerCreditMemoQtyAndCustomerCreditMemoItemAmountValid_ExactMatch() {
207         CustomerCreditMemoDetail detail = new CustomerCreditMemoDetail();
208         detail.setCreditMemoItemTotalAmount(new KualiDecimal(4));
209         detail.setCreditMemoItemQuantity(new BigDecimal(2));
210 
211         assertTrue(rule.checkIfCustomerCreditMemoQtyAndCustomerCreditMemoItemAmountValid(detail,new BigDecimal(2)));
212     }
213 
214     /*
215      *  This method tests if checkIfCustomerCreditMemoQtyAndCustomerCreditMemoItemAmountValid returns false if passed invalid quantity and/or amount
216      */
217     public void testCheckIfCustomerCreditMemoQtyAndCustomerCreditMemoItemAmountValid_FarOff() {
218         CustomerCreditMemoDetail detail = new CustomerCreditMemoDetail();
219         detail.setCreditMemoItemTotalAmount(new KualiDecimal(50));
220         detail.setCreditMemoItemQuantity(new BigDecimal(10)); // should be 5
221 
222         assertFalse(rule.checkIfCustomerCreditMemoQtyAndCustomerCreditMemoItemAmountValid(detail,new BigDecimal(10)));
223     }
224 
225     public void testCheckIfCustomerCreditMemoQtyAndCustomerCreditMemoItemAmountValid_JustAboveAllowedDeviation() {
226         CustomerCreditMemoDetail detail = new CustomerCreditMemoDetail();
227         detail.setCreditMemoItemTotalAmount(new KualiDecimal(50));
228         detail.setCreditMemoItemQuantity(new BigDecimal(5.6)); // should be 5
229 
230         assertFalse(rule.checkIfCustomerCreditMemoQtyAndCustomerCreditMemoItemAmountValid(detail,new BigDecimal(10)));
231     }
232 
233     public void testCheckIfCustomerCreditMemoQtyAndCustomerCreditMemoItemAmountValid_ExactlyAllowedDeviation() {
234         CustomerCreditMemoDetail detail = new CustomerCreditMemoDetail();
235         detail.setCreditMemoItemTotalAmount(new KualiDecimal(50));
236         detail.setCreditMemoItemQuantity(new BigDecimal(5.5)); // should be 5
237 
238         assertTrue(rule.checkIfCustomerCreditMemoQtyAndCustomerCreditMemoItemAmountValid(detail,new BigDecimal(10)));
239     }
240 
241     public void testCheckIfCustomerCreditMemoQtyAndCustomerCreditMemoItemAmountValid_JustBelowAllowedDeviation() {
242         CustomerCreditMemoDetail detail = new CustomerCreditMemoDetail();
243         detail.setCreditMemoItemTotalAmount(new KualiDecimal(50));
244         detail.setCreditMemoItemQuantity(new BigDecimal(5.4)); // should be 5
245 
246         assertTrue(rule.checkIfCustomerCreditMemoQtyAndCustomerCreditMemoItemAmountValid(detail,new BigDecimal(10)));
247     }
248 
249     /*
250      *  This method tests if checkIfInvoiceNumberIsValid returns false if passed invalid invoice number
251      */
252     public void testCheckIfInvoiceNumberIsValid_False() {
253         assertFalse(rule.checkIfInvoiceNumberIsFinal("KLM0456"));
254     }
255 
256     /*
257      *  This method tests if checkIfInvoiceNumberIsValid returns true if passed a valid invoice number
258      */
259     public void testCheckIfInvoiceNumberIsValid_True() throws WorkflowException {
260 
261         String documentNumber = CustomerInvoiceDocumentTestUtil.submitNewCustomerInvoiceDocument(CustomerInvoiceDocumentFixture.BASE_CIDOC_WITH_CUSTOMER,
262             new CustomerInvoiceDetailFixture[]
263             {CustomerInvoiceDetailFixture.CUSTOMER_INVOICE_DETAIL_CHART_RECEIVABLE},
264             null);
265 
266         assertTrue(rule.checkIfInvoiceNumberIsFinal(documentNumber));
267     }
268 
269     /*
270      *  This method tests if checkIfThereIsNoAnotherCRMInRouteForTheInvoice returns true if there are no CRMs associated with the invoice
271      */
272     public void testCheckIfThereIsNoAnotherCRMInRouteForTheInvoice_True() throws WorkflowException {
273         String documentNumber = CustomerInvoiceDocumentTestUtil.submitNewCustomerInvoiceDocument(CustomerInvoiceDocumentFixture.BASE_CIDOC_WITH_CUSTOMER,
274             new CustomerInvoiceDetailFixture[]
275             {CustomerInvoiceDetailFixture.CUSTOMER_INVOICE_DETAIL_CHART_RECEIVABLE},
276             null);
277         assertTrue(rule.checkIfThereIsNoAnotherCRMInRouteForTheInvoice(documentNumber));
278     }
279 
280     /*
281      *  This method tests if checkIfThereIsNoAnotherCRMInRouteForTheInvoice returns false if passed an invoice number for which there is a CRM in route.
282      */
283 
284     public void testCheckIfThereIsNoAnotherCRMInRouteForTheInvoice_False() throws WorkflowException {
285         String invoiceNumber = "";
286 
287         // create a new invoice
288         CustomerInvoiceDocument invoice = CustomerInvoiceDocumentTestUtil.submitNewCustomerInvoiceDocumentAndReturnIt(CustomerInvoiceDocumentFixture.BASE_CIDOC_WITH_CUSTOMER,
289             new CustomerInvoiceDetailFixture[]
290             {CustomerInvoiceDetailFixture.CUSTOMER_INVOICE_DETAIL_CHART_RECEIVABLE},
291             null);
292 
293         // create a new credit memo for the invoice and save it
294         invoiceNumber = invoice.getDocumentNumber();
295         document = createCustomerCreditMemoDocument(invoice);
296         document.getDocumentHeader().setDocumentDescription("CREATING TEST CRM DOCUMENT");
297 
298         try {
299             Document savedDocument = SpringContext.getBean(DocumentService.class).routeDocument(document, "Routing from Unit Test", null);
300         } catch (Exception e){
301             LOG.error(e.getMessage());
302         }
303         assertFalse(rule.checkIfThereIsNoAnotherCRMInRouteForTheInvoice(invoiceNumber));
304     }
305 
306     /**
307      * This method creates a customer credit memo document based on the passed in customer invoice document
308      *
309      * @param customer invoice document
310      * @return
311      */
312     public CustomerCreditMemoDocument createCustomerCreditMemoDocument(CustomerInvoiceDocument invoice){
313 
314         CustomerCreditMemoDetail customerCreditMemoDetail;
315         CustomerCreditMemoDocument customerCreditMemoDocument = null;
316         KualiDecimal invItemTaxAmount, itemAmount;
317         Integer itemLineNumber;
318         BigDecimal itemQuantity;
319         String documentNumber;
320 
321         try {
322             // the document header is created and set here
323             customerCreditMemoDocument = DocumentTestUtils.createDocument(SpringContext.getBean(DocumentService.class), CustomerCreditMemoDocument.class);
324         }
325         catch (WorkflowException e) {
326             throw new RuntimeException("Document creation failed.");
327         }
328 
329         customerCreditMemoDocument.setInvoice(invoice); // invoice, not sure I need to set it at all for this test
330         customerCreditMemoDocument.setFinancialDocumentReferenceInvoiceNumber(invoice.getDocumentNumber());
331 
332         List<CustomerInvoiceDetail> customerInvoiceDetails = invoice.getCustomerInvoiceDetailsWithoutDiscounts();
333         if (customerInvoiceDetails == null) {
334             return customerCreditMemoDocument;
335         }
336 
337         for (CustomerInvoiceDetail customerInvoiceDetail : customerInvoiceDetails) {
338                 customerCreditMemoDetail = new CustomerCreditMemoDetail();
339                 customerCreditMemoDetail.setDocumentNumber(customerCreditMemoDocument.getDocumentNumber());
340 
341                 invItemTaxAmount = customerInvoiceDetail.getInvoiceItemTaxAmount();
342                 if (invItemTaxAmount == null) {
343                     invItemTaxAmount = KualiDecimal.ZERO;
344                 }
345                 customerCreditMemoDetail.setCreditMemoItemTaxAmount(invItemTaxAmount.divide(new KualiDecimal(2)));
346 
347                 customerCreditMemoDetail.setReferenceInvoiceItemNumber(customerInvoiceDetail.getSequenceNumber());
348                 itemQuantity = customerInvoiceDetail.getInvoiceItemQuantity().divide(new BigDecimal(2));
349                 customerCreditMemoDetail.setCreditMemoItemQuantity(itemQuantity);
350 
351                 itemAmount = customerInvoiceDetail.getAmount().divide(new KualiDecimal(2));
352                 customerCreditMemoDetail.setCreditMemoItemTotalAmount(itemAmount);
353                 customerCreditMemoDetail.setFinancialDocumentReferenceInvoiceNumber(invoice.getDocumentNumber());
354                 customerCreditMemoDetail.setCustomerInvoiceDetail(customerInvoiceDetail);
355                 customerCreditMemoDocument.getCreditMemoDetails().add(customerCreditMemoDetail);
356         }
357         return customerCreditMemoDocument;
358     }
359 
360 }
361