1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.kuali.ole.sys.businessobject;
17
18 import java.sql.Date;
19 import java.util.Arrays;
20 import java.util.Collections;
21 import java.util.HashMap;
22 import java.util.HashSet;
23 import java.util.List;
24 import java.util.Map;
25 import java.util.Set;
26
27 import org.kuali.ole.coa.businessobject.Account;
28 import org.kuali.ole.coa.businessobject.ObjectCode;
29 import org.kuali.ole.sys.context.SpringContext;
30 import org.kuali.ole.sys.document.AccountingDocument;
31 import org.kuali.ole.sys.document.service.AccountPresenceService;
32 import org.kuali.rice.core.api.datetime.DateTimeService;
33 import org.kuali.rice.kew.api.exception.WorkflowException;
34 import org.kuali.rice.krad.document.Document;
35 import org.kuali.rice.krad.service.DocumentService;
36 import org.kuali.rice.krad.util.ObjectUtils;
37
38
39
40
41
42 public class AccountingLineOverride {
43 private static final org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(AccountingLineOverride.class);
44
45
46
47
48 public static final class CODE {
49 public static final String NONE = "NONE";
50 public static final String EXPIRED_ACCOUNT = "EXPIRED_ACCOUNT";
51 public static final String NON_BUDGETED_OBJECT = "NON_BUDGETED_OBJECT";
52 public static final String TRANSACTION_EXCEEDS_REMAINING_BUDGET = "TRANSACTION_EXCEEDS_REMAINING_BUDGET";
53 public static final String EXPIRED_ACCOUNT_AND_NON_BUDGETED_OBJECT = "EXPIRED_ACCOUNT_AND_NON_BUDGETED_OBJECT";
54 public static final String NON_BUDGETED_OBJECT_AND_TRANSACTION_EXCEEDS_REMAINING_BUDGET = "NON_BUDGETED_OBJECT_AND_TRANSACTION_EXCEEDS_REMAINING_BUDGET";
55 public static final String EXPIRED_ACCOUNT_AND_TRANSACTION_EXCEEDS_REMAINING_BUDGET = "EXPIRED_ACCOUNT_AND_TRANSACTION_EXCEEDS_REMAINING_BUDGET";
56 public static final String EXPIRED_ACCOUNT_AND_NON_BUDGETED_OBJECT_AND_TRANSACTION_EXCEEDS_REMAINING_BUDGET = "EXPIRED_ACCOUNT_AND_NON_BUDGETED_OBJECT_AND_TRANSACTION_EXCEEDS_REMAINING_BUDGET";
57 public static final String NON_FRINGE_ACCOUNT_USED = "NON_FRINGE_ACCOUNT_USED";
58 public static final String EXPIRED_ACCOUNT_AND_NON_FRINGE_ACCOUNT_USED = "EXPIRED_ACCOUNT_AND_NON_FRINGE_ACCOUNT_USED";
59 }
60
61
62
63
64 public static final class COMPONENT {
65 public static final Integer EXPIRED_ACCOUNT = new Integer(1);
66 public static final Integer NON_BUDGETED_OBJECT = new Integer(2);
67 public static final Integer TRANSACTION_EXCEEDS_REMAINING_BUDGET = new Integer(3);
68 public static final Integer NON_FRINGE_ACCOUNT_USED = new Integer(8);
69 }
70
71
72
73
74
75 public static final List<String> REFRESH_FIELDS = Collections.unmodifiableList(Arrays.asList(new String[] { "account", "objectCode" }));
76
77
78
79
80 private static final Map<String, AccountingLineOverride> codeToOverrideMap = new HashMap<String, AccountingLineOverride>();
81
82
83
84
85 private static final Map componentsToOverrideMap = new HashMap();
86
87 static {
88
89 new AccountingLineOverride(CODE.NONE, new Integer[] {});
90 new AccountingLineOverride(CODE.EXPIRED_ACCOUNT,
91
92 new Integer[] { COMPONENT.EXPIRED_ACCOUNT });
93 new AccountingLineOverride(CODE.NON_BUDGETED_OBJECT, new Integer[] { COMPONENT.NON_BUDGETED_OBJECT });
94 new AccountingLineOverride(CODE.TRANSACTION_EXCEEDS_REMAINING_BUDGET, new Integer[] { COMPONENT.TRANSACTION_EXCEEDS_REMAINING_BUDGET });
95 new AccountingLineOverride(CODE.EXPIRED_ACCOUNT_AND_NON_BUDGETED_OBJECT, new Integer[] { COMPONENT.EXPIRED_ACCOUNT, COMPONENT.NON_BUDGETED_OBJECT });
96 new AccountingLineOverride(CODE.NON_BUDGETED_OBJECT_AND_TRANSACTION_EXCEEDS_REMAINING_BUDGET, new Integer[] { COMPONENT.NON_BUDGETED_OBJECT, COMPONENT.TRANSACTION_EXCEEDS_REMAINING_BUDGET });
97 new AccountingLineOverride(CODE.EXPIRED_ACCOUNT_AND_TRANSACTION_EXCEEDS_REMAINING_BUDGET, new Integer[] { COMPONENT.EXPIRED_ACCOUNT, COMPONENT.TRANSACTION_EXCEEDS_REMAINING_BUDGET });
98 new AccountingLineOverride(CODE.EXPIRED_ACCOUNT_AND_NON_BUDGETED_OBJECT_AND_TRANSACTION_EXCEEDS_REMAINING_BUDGET, new Integer[] { COMPONENT.EXPIRED_ACCOUNT, COMPONENT.NON_BUDGETED_OBJECT, COMPONENT.TRANSACTION_EXCEEDS_REMAINING_BUDGET });
99 new AccountingLineOverride(CODE.NON_FRINGE_ACCOUNT_USED, new Integer[] { COMPONENT.NON_FRINGE_ACCOUNT_USED });
100 new AccountingLineOverride(CODE.EXPIRED_ACCOUNT_AND_NON_FRINGE_ACCOUNT_USED, new Integer[] { COMPONENT.EXPIRED_ACCOUNT, COMPONENT.NON_FRINGE_ACCOUNT_USED });
101 }
102
103 private final String code;
104 private final Set components;
105
106
107
108
109
110
111
112 private AccountingLineOverride(String myCode, Integer[] myComponents) {
113 code = myCode;
114 components = componentsAsSet(myComponents);
115 codeToOverrideMap.put(code, this);
116 componentsToOverrideMap.put(components, this);
117 }
118
119
120
121
122
123
124
125 public boolean hasComponent(Integer component) {
126 return components.contains(component);
127 }
128
129
130
131
132
133
134 public String getCode() {
135 return code;
136 }
137
138
139
140
141
142
143 private Set getComponents() {
144 return components;
145 }
146
147
148
149
150 @Override
151 public String toString() {
152 return "AccountingLineOverride (code " + code + ", components " + components + ")";
153 }
154
155
156
157
158
159
160
161
162
163
164 public AccountingLineOverride mask(AccountingLineOverride mask) {
165 Set key = maskComponents(mask);
166 if (!isValidComponentSet(key)) {
167 throw new IllegalArgumentException("invalid component set " + key);
168 }
169 return valueOf(key);
170 }
171
172
173
174
175
176
177
178 private Set maskComponents(AccountingLineOverride mask) {
179 Set retval = new HashSet(components);
180 retval.retainAll(mask.getComponents());
181 return retval;
182 }
183
184
185
186
187
188
189
190
191 public boolean isValidMask(AccountingLineOverride mask) {
192 return isValidComponentSet(maskComponents(mask));
193 }
194
195
196
197
198
199
200
201 public static boolean isValidCode(String code) {
202 return codeToOverrideMap.containsKey(code);
203 }
204
205
206
207
208
209
210
211
212 public static boolean isValidComponentSet(Integer[] components) {
213 return isValidComponentSet(componentsAsSet(components));
214 }
215
216 private static boolean isValidComponentSet(Set components) {
217 return componentsToOverrideMap.containsKey(components);
218 }
219
220
221
222
223
224
225
226
227 public static AccountingLineOverride valueOf(String code) {
228 if (!isValidCode(code)) {
229 throw new IllegalArgumentException("invalid code " + code);
230 }
231 return (AccountingLineOverride) codeToOverrideMap.get(code);
232 }
233
234
235
236
237
238
239
240
241 public static AccountingLineOverride valueOf(Integer[] components) {
242 Set key = componentsAsSet(components);
243 if (!isValidComponentSet(key)) {
244 throw new IllegalArgumentException("invalid component set " + key);
245 }
246 return valueOf(key);
247 }
248
249 public static AccountingLineOverride valueOf(Set components) {
250 return (AccountingLineOverride) componentsToOverrideMap.get(components);
251 }
252
253 private static Set componentsAsSet(Integer[] components) {
254 return Collections.unmodifiableSet(new HashSet(Arrays.asList(components)));
255 }
256
257
258
259
260
261
262 public static void populateFromInput(AccountingLine line) {
263
264
265 Set overrideInputComponents = new HashSet();
266 if (line.getAccountExpiredOverride()) {
267 overrideInputComponents.add(COMPONENT.EXPIRED_ACCOUNT);
268 }
269 if (line.isObjectBudgetOverride()) {
270 overrideInputComponents.add(COMPONENT.NON_BUDGETED_OBJECT);
271 }
272 if (!isValidComponentSet(overrideInputComponents)) {
273
274 }
275 line.setOverrideCode(valueOf(overrideInputComponents).getCode());
276 }
277
278
279
280
281
282
283
284
285 public static void processForOutput(AccountingDocument document ,AccountingLine line) {
286 AccountingLineOverride fromCurrentCode = valueOf(line.getOverrideCode());
287 AccountingLineOverride needed = determineNeededOverrides(document,line);
288 line.setAccountExpiredOverride(fromCurrentCode.hasComponent(COMPONENT.EXPIRED_ACCOUNT));
289 line.setAccountExpiredOverrideNeeded(needed.hasComponent(COMPONENT.EXPIRED_ACCOUNT));
290 line.setObjectBudgetOverride(fromCurrentCode.hasComponent(COMPONENT.NON_BUDGETED_OBJECT));
291 line.setObjectBudgetOverrideNeeded(needed.hasComponent(COMPONENT.NON_BUDGETED_OBJECT));
292 }
293
294
295
296
297
298
299
300 public static AccountingLineOverride determineNeededOverrides(AccountingDocument document ,AccountingLine line) {
301 boolean isDocumentFinalOrProcessed = false;
302 if(ObjectUtils.isNotNull(document)) {
303 AccountingDocument accountingDocument = (AccountingDocument) document;
304 isDocumentFinalOrProcessed = accountingDocument.isDocumentFinalOrProcessed();
305 }
306
307 Set neededOverrideComponents = new HashSet();
308 if (needsExpiredAccountOverride(line, isDocumentFinalOrProcessed)) {
309 neededOverrideComponents.add(COMPONENT.EXPIRED_ACCOUNT);
310 }
311 if (needsObjectBudgetOverride(line.getAccount(), line.getObjectCode())) {
312 neededOverrideComponents.add(COMPONENT.NON_BUDGETED_OBJECT);
313 }
314
315 if (!isValidComponentSet(neededOverrideComponents)) {
316
317 }
318 return valueOf(neededOverrideComponents);
319 }
320
321
322
323
324
325
326
327 public static boolean needsExpiredAccountOverride(Account account) {
328 return !ObjectUtils.isNull(account) && account.isActive() && account.isExpired();
329 }
330
331
332
333
334
335
336
337 public static boolean needsExpiredAccountOverride(AccountingLine line, boolean isDocumentFinalOrProcessed ) {
338 if(isDocumentFinalOrProcessed){
339 if(CODE.EXPIRED_ACCOUNT.equals(line.getOverrideCode())) {
340 return true;
341 }
342 else {
343 return false;
344 }
345 }
346 else {
347 return !ObjectUtils.isNull(line.getAccount()) && line.getAccount().isActive() && line.getAccount().isExpired();
348 }
349 }
350
351
352
353
354
355
356
357 public static boolean needsNonFringAccountOverride(Account account) {
358 return !ObjectUtils.isNull(account) && account.isActive() && !account.isAccountsFringesBnftIndicator();
359 }
360
361
362
363
364
365
366
367 public static boolean needsObjectBudgetOverride(Account account, ObjectCode objectCode) {
368 return !ObjectUtils.isNull(account) && !ObjectUtils.isNull(objectCode) && account.isActive() && !SpringContext.getBean(AccountPresenceService.class).isObjectCodeBudgetedForAccountPresence(account, objectCode);
369 }
370
371 public static Document getDocument(AccountingLine line) {
372 Document document = null;
373 try {
374 document = SpringContext.getBean(DocumentService.class).getByDocumentHeaderId(line.getDocumentNumber());
375
376 }catch(WorkflowException exception) {
377 LOG.error("Unable to locate document for documentId :: " + line.getDocumentNumber() );
378 }
379
380 return document;
381 }
382 }