1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.kuali.ole.module.purap.util;
17
18 import org.apache.commons.lang.StringUtils;
19 import org.apache.commons.lang.builder.ToStringBuilder;
20 import org.apache.commons.lang.enums.Enum;
21 import org.apache.log4j.Logger;
22 import org.kuali.ole.module.purap.PurapConstants;
23 import org.kuali.ole.module.purap.businessobject.PurApAccountingLine;
24 import org.kuali.ole.module.purap.businessobject.PurchaseOrderItem;
25 import org.kuali.ole.module.purap.businessobject.ReceivingThreshold;
26 import org.kuali.ole.module.purap.document.PurchaseOrderDocument;
27 import org.kuali.ole.module.purap.document.service.ThresholdService;
28 import org.kuali.ole.module.purap.service.PurapAccountingService;
29 import org.kuali.ole.sys.OLEPropertyConstants;
30 import org.kuali.ole.sys.context.SpringContext;
31 import org.kuali.rice.core.api.util.type.KualiDecimal;
32
33 import java.util.*;
34
35
36
37
38 public class ThresholdHelper {
39
40
41
42
43 private static Logger LOG = Logger.getLogger(ThresholdHelper.class);
44
45 public static final ThresholdCriteria CHART = new ThresholdCriteria("CHART");
46 public static final ThresholdCriteria CHART_AND_ACCOUNTTYPE = new ThresholdCriteria("CHART_AND_ACCOUNT-TYPE");
47 public static final ThresholdCriteria CHART_AND_SUBFUND = new ThresholdCriteria("CHART_AND_SUB-FUND");
48 public static final ThresholdCriteria CHART_AND_COMMODITYCODE = new ThresholdCriteria("CHART_AND_COMMODITY-CODE");
49 public static final ThresholdCriteria CHART_AND_OBJECTCODE = new ThresholdCriteria("CHART_AND_OBJECT-CODE");
50 public static final ThresholdCriteria CHART_AND_ORGANIZATIONCODE = new ThresholdCriteria("CHART_AND_ORGANIZATION-CODE");
51 public static final ThresholdCriteria CHART_AND_VENDOR = new ThresholdCriteria("CHART_AND_VENDOR");
52
53
54
55
56 private PurapAccountingService purapAccountingService;
57 private ThresholdService thresholdService;
58
59 private List<ThresholdSummary> chartCodeSummary = new ArrayList();
60 private List<ThresholdSummary> chartCodeAndFundSummary = new ArrayList();
61 private List<ThresholdSummary> chartCodeAndSubFundSummary = new ArrayList();
62 private List<ThresholdSummary> chartCodeAndCommodityCodeSummary = new ArrayList();
63 private List<ThresholdSummary> chartCodeAndObjectCodeSummary = new ArrayList();
64 private List<ThresholdSummary> chartCodeAndOrgCodeSummary = new ArrayList();
65 private List<ThresholdSummary> chartCodeAndVendorSummary = new ArrayList();
66
67 private ThresholdSummary thresholdSummary;
68 private ReceivingThreshold receivingThreshold;
69
70 private boolean allItemsNonQty;
71
72 public ThresholdHelper(PurchaseOrderDocument document) {
73 purapAccountingService = SpringContext.getBean(PurapAccountingService.class);
74 thresholdService = SpringContext.getBean(ThresholdService.class);
75 setupForThresholdCheck(document);
76 }
77
78 private void setupForThresholdCheck(PurchaseOrderDocument document) {
79
80 allItemsNonQty = checkForNonQtyItems(document);
81
82 if (allItemsNonQty) {
83 return;
84 }
85
86 List<SummaryAccount> accounts = purapAccountingService.generateSummaryAccounts(document);
87
88 if (accounts != null) {
89
90 for (SummaryAccount account : accounts) {
91
92 updateThresholdSummary(CHART, account);
93 updateThresholdSummary(CHART_AND_ACCOUNTTYPE, account);
94 updateThresholdSummary(CHART_AND_SUBFUND, account);
95 updateThresholdSummary(CHART_AND_OBJECTCODE, account);
96 updateThresholdSummary(CHART_AND_ORGANIZATIONCODE, account);
97
98 processVendorForThresholdSummary(account,
99 document.getVendorHeaderGeneratedIdentifier().toString(),
100 document.getVendorDetailAssignedIdentifier().toString());
101
102 }
103 }
104
105 processCommodityCodeForThreshold(document.getItems());
106
107 }
108
109 private boolean checkForNonQtyItems(PurchaseOrderDocument document) {
110 List<PurchaseOrderItem> items = document.getItems();
111
112 for (int i = 0; i < items.size(); i++) {
113 if (!items.get(i).getItemType().isAdditionalChargeIndicator() &&
114 !StringUtils.equals(items.get(i).getItemTypeCode(), PurapConstants.ItemTypeCodes.ITEM_TYPE_SERVICE_CODE)) {
115 return false;
116 }
117 }
118 return true;
119 }
120
121 private void updateThresholdSummary(ThresholdCriteria thresholdCriteria,
122 SummaryAccount account) {
123
124 if (thresholdCriteria != CHART_AND_COMMODITYCODE &&
125 thresholdCriteria != CHART_AND_VENDOR) {
126
127 ThresholdSummary thresholdSummary = new ThresholdSummary(thresholdCriteria);
128 thresholdSummary.setProperty(ThresholdField.CHART_OF_ACCOUNTS_CODE,
129 account.getAccount().getChartOfAccountsCode());
130
131 if (thresholdCriteria == CHART_AND_ACCOUNTTYPE) {
132 account.getAccount().refreshReferenceObject(OLEPropertyConstants.ACCOUNT);
133 if (StringUtils.isEmpty(account.getAccount().getAccount().getAccountTypeCode())) {
134 return;
135 }
136 thresholdSummary.setProperty(ThresholdField.ACCOUNT_TYPE_CODE,
137 account.getAccount().getAccount().getAccountTypeCode());
138
139 } else if (thresholdCriteria == CHART_AND_SUBFUND) {
140 account.getAccount().refreshReferenceObject(OLEPropertyConstants.ACCOUNT);
141 if (StringUtils.isEmpty(account.getAccount().getAccount().getSubFundGroupCode())) {
142 return;
143 }
144 thresholdSummary.setProperty(ThresholdField.SUBFUND_GROUP_CODE,
145 account.getAccount().getAccount().getSubFundGroupCode());
146 } else if (thresholdCriteria == CHART_AND_OBJECTCODE) {
147 if (StringUtils.isEmpty(account.getAccount().getFinancialObjectCode())) {
148 return;
149 }
150 thresholdSummary.setProperty(ThresholdField.FINANCIAL_OBJECT_CODE,
151 account.getAccount().getFinancialObjectCode());
152 } else if (thresholdCriteria == CHART_AND_ORGANIZATIONCODE) {
153 account.getAccount().refreshReferenceObject(OLEPropertyConstants.ACCOUNT);
154 if (StringUtils.isEmpty(account.getAccount().getAccount().getOrganizationCode())) {
155 return;
156 }
157 thresholdSummary.setProperty(ThresholdField.ORGANIZATION_CODE,
158 account.getAccount().getAccount().getOrganizationCode());
159 }
160
161 thresholdSummary.addTotalAmount(account.getAccount().getAmount());
162 addToSummaryList(thresholdSummary);
163 }
164 }
165
166 private void addToSummaryList(ThresholdSummary thresholdSummary) {
167
168 List<ThresholdSummary> summaryList = getThresholdSummaryCollection(thresholdSummary.getThresholdCriteria());
169
170 boolean matchFound = false;
171 for (int i = 0; i < summaryList.size(); i++) {
172 if (thresholdSummary.equals(summaryList.get(i))) {
173 summaryList.get(i).addTotalAmount(thresholdSummary.getTotalAmount());
174 matchFound = true;
175 break;
176 }
177 }
178
179 if (!matchFound) {
180 summaryList.add(thresholdSummary);
181 }
182 }
183
184 private List<ThresholdSummary> getThresholdSummaryCollection(ThresholdCriteria thresholdCriteria) {
185
186 if (thresholdCriteria == CHART) {
187 return chartCodeSummary;
188 } else if (thresholdCriteria == CHART_AND_ACCOUNTTYPE) {
189 return chartCodeAndFundSummary;
190 } else if (thresholdCriteria == CHART_AND_SUBFUND) {
191 return chartCodeAndSubFundSummary;
192 } else if (thresholdCriteria == CHART_AND_COMMODITYCODE) {
193 return chartCodeAndCommodityCodeSummary;
194 } else if (thresholdCriteria == CHART_AND_OBJECTCODE) {
195 return chartCodeAndObjectCodeSummary;
196 } else if (thresholdCriteria == CHART_AND_ORGANIZATIONCODE) {
197 return chartCodeAndOrgCodeSummary;
198 } else if (thresholdCriteria == CHART_AND_VENDOR) {
199 return chartCodeAndVendorSummary;
200 }
201
202 throw new RuntimeException("Invalid ThresholdCriteria Enum - " + thresholdCriteria);
203 }
204
205 private void processVendorForThresholdSummary(SummaryAccount account,
206 String vendorHeaderGeneratedIdentifier,
207 String vendorDetailAssignedIdentifier) {
208
209 ThresholdSummary thresholdSummary = new ThresholdSummary(CHART_AND_VENDOR);
210 thresholdSummary.setProperty(ThresholdField.CHART_OF_ACCOUNTS_CODE, account.getAccount().getChartOfAccountsCode());
211 thresholdSummary.setProperty(ThresholdField.VENDOR_HEADER_GENERATED_ID, vendorHeaderGeneratedIdentifier);
212 thresholdSummary.setProperty(ThresholdField.VENDOR_DETAIL_ASSIGNED_ID, vendorDetailAssignedIdentifier);
213 thresholdSummary.addTotalAmount(account.getAccount().getAmount());
214
215 addToSummaryList(thresholdSummary);
216
217 }
218
219 private void processCommodityCodeForThreshold(List<PurchaseOrderItem> items) {
220 if (items != null) {
221 for (PurchaseOrderItem item : items) {
222 if (item.isItemActiveIndicator()) {
223 List<PurApAccountingLine> accountingLines = item.getSourceAccountingLines();
224 for (int i = 0; i < accountingLines.size(); i++) {
225 if (StringUtils.isNotBlank(item.getPurchasingCommodityCode())) {
226 ThresholdSummary thresholdSummary = new ThresholdSummary(CHART_AND_COMMODITYCODE);
227 thresholdSummary.setProperty(ThresholdField.CHART_OF_ACCOUNTS_CODE, accountingLines.get(i).getChartOfAccountsCode());
228 thresholdSummary.setProperty(ThresholdField.COMMODITY_CODE, item.getPurchasingCommodityCode());
229 thresholdSummary.addTotalAmount(item.getExtendedPrice());
230 addToSummaryList(thresholdSummary);
231 }
232 }
233 }
234 }
235 }
236 }
237
238 public boolean isReceivingDocumentRequired() {
239
240
241 if (allItemsNonQty) {
242 return false;
243 }
244
245 for (ThresholdCriteria thresholdEnum : ThresholdCriteria.getEnumList()) {
246 boolean result = isReceivingDocumentRequired(thresholdEnum);
247 if (result) {
248 return true;
249 }
250 }
251
252 return false;
253 }
254
255
256
257
258
259 public boolean isReceivingDocumentRequired(ThresholdCriteria thresholdEnum) {
260
261 List<ThresholdSummary> summaryList = getThresholdSummaryCollection(thresholdEnum);
262
263 if (summaryList != null) {
264 for (ThresholdSummary summary : summaryList) {
265 Collection collection = null;
266
267 if (thresholdEnum == CHART) {
268 collection = thresholdService.findByChart(summary.getProperty(ThresholdField.CHART_OF_ACCOUNTS_CODE));
269 } else if (thresholdEnum == CHART_AND_ACCOUNTTYPE) {
270 collection = thresholdService.findByChartAndFund(summary.getProperty(ThresholdField.CHART_OF_ACCOUNTS_CODE),
271 summary.getProperty(ThresholdField.ACCOUNT_TYPE_CODE));
272 } else if (thresholdEnum == CHART_AND_SUBFUND) {
273 collection = thresholdService.findByChartAndSubFund(summary.getProperty(ThresholdField.CHART_OF_ACCOUNTS_CODE),
274 summary.getProperty(ThresholdField.SUBFUND_GROUP_CODE));
275 } else if (thresholdEnum == CHART_AND_COMMODITYCODE) {
276 collection = thresholdService.findByChartAndCommodity(summary.getProperty(ThresholdField.CHART_OF_ACCOUNTS_CODE),
277 summary.getProperty(ThresholdField.COMMODITY_CODE));
278 } else if (thresholdEnum == CHART_AND_OBJECTCODE) {
279 collection = thresholdService.findByChartAndObjectCode(summary.getProperty(ThresholdField.CHART_OF_ACCOUNTS_CODE),
280 summary.getProperty(ThresholdField.FINANCIAL_OBJECT_CODE));
281 } else if (thresholdEnum == CHART_AND_ORGANIZATIONCODE) {
282 collection = thresholdService.findByChartAndOrg(summary.getProperty(ThresholdField.CHART_OF_ACCOUNTS_CODE),
283 summary.getProperty(ThresholdField.ORGANIZATION_CODE));
284 } else if (thresholdEnum == CHART_AND_VENDOR) {
285 collection = thresholdService.findByChartAndVendor(summary.getProperty(ThresholdField.CHART_OF_ACCOUNTS_CODE),
286 summary.getProperty(ThresholdField.VENDOR_HEADER_GENERATED_ID),
287 summary.getProperty(ThresholdField.VENDOR_DETAIL_ASSIGNED_ID));
288 }
289
290 if (collection != null) {
291 for (ReceivingThreshold threshold : (List<ReceivingThreshold>) collection) {
292 if (threshold.getThresholdAmount() == null || threshold.getThresholdAmount().isLessThan(summary.getTotalAmount())) {
293 thresholdSummary = summary;
294 receivingThreshold = threshold;
295 return true;
296 }
297 }
298 }
299 }
300 }
301
302 return false;
303
304 }
305
306 public ThresholdSummary getThresholdSummary() {
307 return thresholdSummary;
308 }
309
310 public ReceivingThreshold getReceivingThreshold() {
311 return receivingThreshold;
312 }
313
314 public class ThresholdSummary {
315
316 private ThresholdCriteria thresholdCriteria;
317 private Map<ThresholdField, String> property2Value = new HashMap<ThresholdField, String>();
318 private KualiDecimal totalAmount = KualiDecimal.ZERO;
319
320 ThresholdSummary(ThresholdCriteria thresholdCriteria) {
321 this.thresholdCriteria = thresholdCriteria;
322 }
323
324 void setProperty(ThresholdField thresholdField,
325 String fieldValue) {
326 if (!isValidProperty(thresholdField)) {
327 throw new RuntimeException("Property[" + thresholdField + "] not allowed for the threshold criteria[" + thresholdCriteria + "]");
328 }
329
330 property2Value.put(thresholdField, fieldValue);
331 }
332
333 String getProperty(ThresholdField thresholdEnum) {
334 return property2Value.get(thresholdEnum);
335 }
336
337 public ThresholdCriteria getThresholdCriteria() {
338 return thresholdCriteria;
339 }
340
341 public String getThresholdCriteriaName() {
342 return thresholdCriteria.getName();
343 }
344
345 public KualiDecimal getTotalAmount() {
346 return totalAmount;
347 }
348
349 void addTotalAmount(KualiDecimal totalAmount) {
350 if (totalAmount != null) {
351 this.totalAmount = this.totalAmount.add(totalAmount);
352 }
353 }
354
355 boolean isValidProperty(ThresholdField thresholdField) {
356
357 if (getThresholdCriteria() == CHART &&
358 ThresholdField.CHART_OF_ACCOUNTS_CODE == thresholdField) {
359 return true;
360 } else if ((getThresholdCriteria() == CHART_AND_ACCOUNTTYPE) &&
361 (ThresholdField.CHART_OF_ACCOUNTS_CODE == thresholdField ||
362 ThresholdField.ACCOUNT_TYPE_CODE == thresholdField)) {
363 return true;
364 } else if ((getThresholdCriteria() == CHART_AND_SUBFUND) &&
365 (ThresholdField.CHART_OF_ACCOUNTS_CODE == thresholdField ||
366 ThresholdField.SUBFUND_GROUP_CODE == thresholdField)) {
367 return true;
368 } else if ((getThresholdCriteria() == CHART_AND_COMMODITYCODE) &&
369 (ThresholdField.CHART_OF_ACCOUNTS_CODE == thresholdField ||
370 ThresholdField.COMMODITY_CODE == thresholdField)) {
371 return true;
372 } else if ((getThresholdCriteria() == CHART_AND_OBJECTCODE) &&
373 (ThresholdField.CHART_OF_ACCOUNTS_CODE == thresholdField ||
374 ThresholdField.FINANCIAL_OBJECT_CODE == thresholdField)) {
375 return true;
376 } else if ((getThresholdCriteria() == CHART_AND_ORGANIZATIONCODE) &&
377 (ThresholdField.CHART_OF_ACCOUNTS_CODE == thresholdField ||
378 ThresholdField.ORGANIZATION_CODE == thresholdField)) {
379 return true;
380 } else if ((getThresholdCriteria() == CHART_AND_VENDOR) &&
381 (ThresholdField.CHART_OF_ACCOUNTS_CODE == thresholdField ||
382 ThresholdField.VENDOR_HEADER_GENERATED_ID == thresholdField ||
383 ThresholdField.VENDOR_DETAIL_ASSIGNED_ID == thresholdField)) {
384 return true;
385 }
386
387 return false;
388 }
389
390 @Override
391 public boolean equals(Object obj) {
392
393 if (obj != null) {
394
395 if (!(obj instanceof ThresholdSummary)) {
396 return false;
397 }
398
399 ThresholdSummary thresholdItem = (ThresholdSummary) obj;
400
401 if (getThresholdCriteria() == thresholdItem.getThresholdCriteria()) {
402
403 if (getThresholdCriteria() == CHART) {
404
405 if (StringUtils.equals(property2Value.get(ThresholdField.CHART_OF_ACCOUNTS_CODE),
406 thresholdItem.getProperty(ThresholdField.CHART_OF_ACCOUNTS_CODE))) {
407 return true;
408 }
409
410 } else if (getThresholdCriteria() == CHART_AND_ACCOUNTTYPE) {
411
412 if (StringUtils.equals(property2Value.get(ThresholdField.CHART_OF_ACCOUNTS_CODE),
413 thresholdItem.getProperty(ThresholdField.CHART_OF_ACCOUNTS_CODE)) &&
414 StringUtils.equals(property2Value.get(ThresholdField.ACCOUNT_TYPE_CODE),
415 thresholdItem.getProperty(ThresholdField.ACCOUNT_TYPE_CODE))) {
416 return true;
417 }
418
419 } else if (getThresholdCriteria() == CHART_AND_SUBFUND) {
420
421 if (StringUtils.equals(property2Value.get(ThresholdField.CHART_OF_ACCOUNTS_CODE),
422 thresholdItem.getProperty(ThresholdField.CHART_OF_ACCOUNTS_CODE)) &&
423 StringUtils.equals(property2Value.get(ThresholdField.SUBFUND_GROUP_CODE),
424 thresholdItem.getProperty(ThresholdField.SUBFUND_GROUP_CODE))) {
425 return true;
426 }
427
428 } else if (getThresholdCriteria() == CHART_AND_COMMODITYCODE) {
429
430 if (StringUtils.equals(property2Value.get(ThresholdField.CHART_OF_ACCOUNTS_CODE),
431 thresholdItem.getProperty(ThresholdField.CHART_OF_ACCOUNTS_CODE)) &&
432 StringUtils.equals(property2Value.get(ThresholdField.COMMODITY_CODE),
433 thresholdItem.getProperty(ThresholdField.COMMODITY_CODE))) {
434 return true;
435 }
436
437 } else if (getThresholdCriteria() == CHART_AND_OBJECTCODE) {
438
439 if (StringUtils.equals(property2Value.get(ThresholdField.CHART_OF_ACCOUNTS_CODE),
440 thresholdItem.getProperty(ThresholdField.CHART_OF_ACCOUNTS_CODE)) &&
441 StringUtils.equals(property2Value.get(ThresholdField.FINANCIAL_OBJECT_CODE),
442 thresholdItem.getProperty(ThresholdField.FINANCIAL_OBJECT_CODE))) {
443 return true;
444 }
445
446 } else if (getThresholdCriteria() == CHART_AND_ORGANIZATIONCODE) {
447
448 if (StringUtils.equals(property2Value.get(ThresholdField.CHART_OF_ACCOUNTS_CODE),
449 thresholdItem.getProperty(ThresholdField.CHART_OF_ACCOUNTS_CODE)) &&
450 StringUtils.equals(property2Value.get(ThresholdField.ORGANIZATION_CODE),
451 thresholdItem.getProperty(ThresholdField.ORGANIZATION_CODE))) {
452 return true;
453 }
454
455 } else if (getThresholdCriteria() == CHART_AND_VENDOR) {
456
457 if (StringUtils.equals(property2Value.get(ThresholdField.CHART_OF_ACCOUNTS_CODE),
458 thresholdItem.getProperty(ThresholdField.CHART_OF_ACCOUNTS_CODE)) &&
459 StringUtils.equals(property2Value.get(ThresholdField.VENDOR_HEADER_GENERATED_ID),
460 thresholdItem.getProperty(ThresholdField.VENDOR_HEADER_GENERATED_ID)) &&
461 StringUtils.equals(property2Value.get(ThresholdField.VENDOR_DETAIL_ASSIGNED_ID),
462 thresholdItem.getProperty(ThresholdField.VENDOR_DETAIL_ASSIGNED_ID))) {
463 return true;
464 }
465
466 }
467 }
468 }
469 return false;
470 }
471
472 @Override
473 public String toString() {
474 ToStringBuilder stringBuilder = new ToStringBuilder(this);
475 stringBuilder.append("ThresholdCriteria", getThresholdCriteria().getName());
476 stringBuilder.append("Amount", getTotalAmount());
477 stringBuilder.append("Field2Values", property2Value);
478
479 return stringBuilder.toString();
480 }
481 }
482
483 }
484
485 final class ThresholdCriteria extends Enum {
486
487 ThresholdCriteria(String name) {
488 super(name);
489 }
490
491 public static List<ThresholdCriteria> getEnumList() {
492 return getEnumList(ThresholdCriteria.class);
493 }
494 }
495