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 }