1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.kuali.ole.module.purap.document.validation.impl;
17
18 import org.kuali.ole.module.purap.PurapConstants;
19 import org.kuali.ole.module.purap.PurapConstants.ItemFields;
20 import org.kuali.ole.module.purap.PurapKeyConstants;
21 import org.kuali.ole.module.purap.PurapParameterConstants;
22 import org.kuali.ole.module.purap.businessobject.InvoiceItem;
23 import org.kuali.ole.module.purap.businessobject.PurApAccountingLine;
24 import org.kuali.ole.module.purap.businessobject.PurApItem;
25 import org.kuali.ole.module.purap.document.InvoiceDocument;
26 import org.kuali.ole.module.purap.document.service.PurapService;
27 import org.kuali.ole.select.OleSelectConstant;
28 import org.kuali.ole.select.businessobject.OleInvoiceItem;
29 import org.kuali.ole.select.document.OleInvoiceDocument;
30 import org.kuali.ole.sys.OLEKeyConstants;
31 import org.kuali.ole.sys.context.SpringContext;
32 import org.kuali.ole.sys.document.validation.GenericValidation;
33 import org.kuali.ole.sys.document.validation.Validation;
34 import org.kuali.ole.sys.document.validation.event.AttributedDocumentEvent;
35 import org.kuali.ole.sys.document.validation.impl.*;
36 import org.kuali.ole.sys.service.impl.OleParameterConstants;
37 import org.kuali.rice.core.api.util.type.KualiDecimal;
38 import org.kuali.rice.coreservice.framework.parameter.ParameterService;
39 import org.kuali.rice.krad.util.GlobalVariables;
40 import org.kuali.rice.krad.util.ObjectUtils;
41
42 import java.util.ArrayList;
43 import java.util.List;
44
45 public class InvoiceProcessItemValidation extends GenericValidation {
46
47 private PurapService purapService;
48 private PurApItem itemForValidation;
49 private AttributedDocumentEvent event;
50 private CompositeValidation reviewAccountingLineValidation;
51 private InvoiceDocument invoiceDocument;
52 private PurApAccountingLine invoiceAccountingLine;
53
54 @Override
55 public boolean validate(AttributedDocumentEvent event) {
56 boolean valid = true;
57 this.event = event;
58
59 InvoiceDocument invoiceDocument = (InvoiceDocument) event.getDocument();
60 InvoiceItem invoiceItem = (InvoiceItem) itemForValidation;
61
62 valid &= validateEachItem(invoiceDocument, invoiceItem);
63
64 return valid;
65
66 }
67
68
69
70
71
72
73
74
75 protected boolean validateEachItem(InvoiceDocument invoiceDocument, InvoiceItem item) {
76 boolean valid = true;
77 String identifierString = item.getItemIdentifierString();
78 valid &= validateItem(invoiceDocument, item, identifierString);
79 return valid;
80 }
81
82
83
84
85
86
87
88
89
90
91 public boolean validateItem(InvoiceDocument invoiceDocument, InvoiceItem item, String identifierString) {
92 boolean valid = true;
93
94 if (!purapService.isFullDocumentEntryCompleted(invoiceDocument)) {
95 if (item.getItemType().isLineItemIndicator()) {
96 valid &= validateAboveTheLineItems(item, identifierString, invoiceDocument.isReceivingDocumentRequiredIndicator());
97 }
98 valid &= validateItemWithoutAccounts(item, identifierString);
99 }
100
101 valid &= validateProrationType(invoiceDocument);
102 valid &= validateItemAccounts(invoiceDocument, item, identifierString);
103 return valid;
104 }
105
106 protected boolean validateProrationType(InvoiceDocument invoiceDocument) {
107 boolean isValid = true;
108 OleInvoiceDocument document = (OleInvoiceDocument) invoiceDocument;
109 List<OleInvoiceItem> items = document.getItems();
110 boolean additionalItemPresent = false;
111 KualiDecimal additionalCharge = KualiDecimal.ZERO;
112 for (OleInvoiceItem invoiceItem : items) {
113 if (invoiceItem.getItemType().isAdditionalChargeIndicator() && invoiceItem.getExtendedPrice() != null &&
114 !invoiceItem.getExtendedPrice().isZero()) {
115 additionalCharge = additionalCharge.add(invoiceItem.getExtendedPrice());
116 additionalItemPresent = true;
117 }
118 }
119 if (additionalItemPresent && ((document.getProrateBy() == null) ||
120 (!document.isProrateDollar() && !document.isProrateManual() && !document.isProrateQty() && !document.isNoProrate()))) {
121 GlobalVariables.getMessageMap().putErrorForSectionId(OleSelectConstant.INVOICE_ADDITIONAL_ITEM_SECTION_ID,
122 OLEKeyConstants.ERROR_REQUIRED, PurapConstants.PRQSDocumentsStrings.PRORATION_TYPE);
123 isValid &= false;
124
125 }
126
127
128
129
130
131
132
133
134
135 return isValid;
136 }
137
138
139
140
141
142
143
144 protected boolean validateAboveTheLineItems(InvoiceItem item, String identifierString, boolean isReceivingDocumentRequiredIndicator) {
145 boolean valid = true;
146
147
148 if (ObjectUtils.isNotNull(item.getItemQuantity())) {
149
150
151
152
153
154 if (!isReceivingDocumentRequiredIndicator) {
155
156
157
158
159 }
160 }
161
162 if (ObjectUtils.isNotNull(item.getExtendedPrice()) && item.getExtendedPrice().isPositive()) {
163
164
165 if (ObjectUtils.isNull(item.getItemQuantity()) || item.getItemQuantity().isZero()) {
166
167
168 valid = false;
169 GlobalVariables.getMessageMap().putError(PurapConstants.ITEM_TAB_ERROR_PROPERTY, PurapKeyConstants.ERROR_ITEM_QUANTITY_REQUIRED, ItemFields.INVOICE_QUANTITY, identifierString, ItemFields.OPEN_QUANTITY);
170 }
171 }
172
173
174 if ((ObjectUtils.isNull(item.getInvoice().getPurapDocumentIdentifier())) || (PurapConstants.InvoiceStatuses.APPDOC_IN_PROCESS.equals(item.getInvoice().getApplicationDocumentStatus()))) {
175
176 if ((item.getItemType().isAmountBasedGeneralLedgerIndicator()) && ((item.getExtendedPrice() != null) && item.getExtendedPrice().isNonZero())) {
177 if (item.getPoOutstandingAmount() == null || item.getPoOutstandingAmount().isZero()) {
178 valid = false;
179 GlobalVariables.getMessageMap().putError(PurapConstants.ITEM_TAB_ERROR_PROPERTY, PurapKeyConstants.ERROR_ITEM_AMOUNT_ALREADY_PAID, identifierString);
180 }
181 }
182 }
183
184 return valid;
185 }
186
187
188
189
190
191
192
193 public boolean validateItemWithoutAccounts(InvoiceItem item, String identifierString) {
194 boolean valid = true;
195 if (ObjectUtils.isNotNull(item.getItemUnitPrice()) && (new KualiDecimal(item.getItemUnitPrice())).isNonZero() && item.isAccountListEmpty()) {
196 valid = false;
197 GlobalVariables.getMessageMap().putError(PurapConstants.ITEM_TAB_ERROR_PROPERTY, PurapKeyConstants.ERROR_ITEM_ACCOUNTING_INCOMPLETE, identifierString);
198 }
199 return valid;
200 }
201
202
203
204
205
206
207
208
209
210
211 public boolean validateItemAccounts(InvoiceDocument invoiceDocument, InvoiceItem item, String identifierString) {
212 boolean valid = true;
213 List<PurApAccountingLine> accountingLines = item.getSourceAccountingLines();
214 KualiDecimal itemTotal = item.getTotalAmount();
215 KualiDecimal accountTotal = KualiDecimal.ZERO;
216 KualiDecimal prorateSurcharge = KualiDecimal.ZERO;
217 OleInvoiceItem invoiceItem = (OleInvoiceItem) item;
218 if (invoiceItem.getItemType().isQuantityBasedGeneralLedgerIndicator() && invoiceItem.getExtendedPrice() != null && invoiceItem.getExtendedPrice().compareTo(KualiDecimal.ZERO) != 0) {
219 if (invoiceItem.getItemSurcharge() != null && invoiceItem.getItemTypeCode().equals("ITEM")) {
220 prorateSurcharge = new KualiDecimal(invoiceItem.getItemSurcharge()).multiply(invoiceItem.getItemQuantity());
221 }
222 itemTotal = itemTotal.subtract(prorateSurcharge);
223 }
224 for (PurApAccountingLine accountingLine : accountingLines) {
225 if (accountingLine.getAmount().isZero()) {
226 if (!canApproveAccountingLinesWithZeroAmount()) {
227 GlobalVariables.getMessageMap().putError(PurapConstants.ITEM_TAB_ERROR_PROPERTY, PurapKeyConstants.ERROR_ITEM_ACCOUNTING_AMOUNT_INVALID, itemForValidation.getItemIdentifierString());
228 valid &= false;
229 }
230 }
231 valid &= reviewAccountingLineValidation(invoiceDocument, accountingLine);
232 accountTotal = accountTotal.add(accountingLine.getAmount());
233 }
234 if (purapService.isFullDocumentEntryCompleted(invoiceDocument)) {
235
236 if (accountTotal.compareTo(itemTotal) != 0) {
237 valid = false;
238 GlobalVariables.getMessageMap().putError(PurapConstants.ITEM_TAB_ERROR_PROPERTY, PurapKeyConstants.ERROR_ITEM_ACCOUNTING_AMOUNT_TOTAL, identifierString);
239 }
240 }
241 return valid;
242 }
243
244 public CompositeValidation getReviewAccountingLineValidation() {
245 return reviewAccountingLineValidation;
246 }
247
248 public void setReviewAccountingLineValidation(CompositeValidation reviewAccountingLineValidation) {
249 this.reviewAccountingLineValidation = reviewAccountingLineValidation;
250 }
251
252 public PurapService getPurapService() {
253 return purapService;
254 }
255
256 public void setPurapService(PurapService purapService) {
257 this.purapService = purapService;
258 }
259
260 public PurApItem getItemForValidation() {
261 return itemForValidation;
262 }
263
264 public void setItemForValidation(PurApItem itemForValidation) {
265 this.itemForValidation = itemForValidation;
266 }
267
268 protected boolean reviewAccountingLineValidation(InvoiceDocument document, PurApAccountingLine accountingLine) {
269 boolean valid = true;
270 List<Validation> gauntlet = new ArrayList<Validation>();
271 this.invoiceDocument = document;
272 this.invoiceAccountingLine = accountingLine;
273
274 createGauntlet(reviewAccountingLineValidation);
275
276 for (Validation validation : gauntlet) {
277 valid &= validation.validate(event);
278 }
279
280 return valid;
281 }
282
283 protected void createGauntlet(CompositeValidation validation) {
284 for (Validation val : validation.getValidations()) {
285 if (val instanceof CompositeValidation) {
286 createGauntlet((CompositeValidation) val);
287 } else if (val instanceof BusinessObjectDataDictionaryValidation) {
288 addParametersToValidation((BusinessObjectDataDictionaryValidation) val);
289 } else if (val instanceof AccountingLineAmountPositiveValidation) {
290
291 } else if (val instanceof AccountingLineDataDictionaryValidation) {
292 addParametersToValidation((AccountingLineDataDictionaryValidation) val);
293 } else if (val instanceof AccountingLineValuesAllowedValidationHutch) {
294 addParametersToValidation((AccountingLineValuesAllowedValidationHutch) val);
295 } else {
296 throw new IllegalStateException("Validations in the InvoiceProcessItemValidation must contain specific instances of validation");
297 }
298 }
299 }
300
301
302
303
304
305
306
307
308 public boolean canApproveAccountingLinesWithZeroAmount() {
309 boolean canApproveLine = false;
310
311
312 String approveZeroAmountLine = SpringContext.getBean(ParameterService.class).getParameterValueAsString(OleParameterConstants.PURCHASING_DOCUMENT.class, PurapParameterConstants.APPROVE_ACCOUNTING_LINES_WITH_ZERO_DOLLAR_AMOUNT_IND);
313
314 if ("Y".equalsIgnoreCase(approveZeroAmountLine)) {
315 return true;
316 }
317
318 return canApproveLine;
319 }
320
321 protected void addParametersToValidation(BusinessObjectDataDictionaryValidation validation) {
322 validation.setBusinessObjectForValidation(this.invoiceAccountingLine);
323 }
324
325 protected void addParametersToValidation(AccountingLineAmountPositiveValidation validation) {
326 validation.setAccountingDocumentForValidation(this.invoiceDocument);
327 validation.setAccountingLineForValidation(this.invoiceAccountingLine);
328 }
329
330 protected void addParametersToValidation(AccountingLineDataDictionaryValidation validation) {
331 validation.setAccountingLineForValidation(this.invoiceAccountingLine);
332 }
333
334 protected void addParametersToValidation(AccountingLineValuesAllowedValidationHutch validation) {
335 validation.setAccountingDocumentForValidation(this.invoiceDocument);
336 validation.setAccountingLineForValidation(this.invoiceAccountingLine);
337 }
338
339
340
341
342
343
344 protected AttributedDocumentEvent getEvent() {
345 return event;
346 }
347
348
349
350
351
352
353 protected void setEvent(AttributedDocumentEvent event) {
354 this.event = event;
355 }
356
357
358
359
360
361
362 protected InvoiceDocument getPreqDocument() {
363 return invoiceDocument;
364 }
365
366
367
368
369
370
371 protected void setPreqDocument(InvoiceDocument invoiceDocument) {
372 this.invoiceDocument = invoiceDocument;
373 }
374
375
376
377
378
379
380 protected PurApAccountingLine getPreqAccountingLine() {
381 return invoiceAccountingLine;
382 }
383
384
385
386
387
388
389 protected void setPreqAccountingLine(PurApAccountingLine invoiceAccountingLine) {
390 this.invoiceAccountingLine = invoiceAccountingLine;
391 }
392
393 }