1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.kuali.ole.fp.document.validation.impl;
17
18 import java.util.ArrayList;
19 import java.util.List;
20 import java.util.Set;
21
22 import org.apache.commons.lang.StringUtils;
23 import org.kuali.ole.fp.businessobject.DisbursementVoucherNonResidentAlienTax;
24 import org.kuali.ole.fp.businessobject.DisbursementVoucherPayeeDetail;
25 import org.kuali.ole.fp.businessobject.NonResidentAlienTaxPercent;
26 import org.kuali.ole.fp.document.DisbursementVoucherConstants;
27 import org.kuali.ole.fp.document.DisbursementVoucherDocument;
28 import org.kuali.ole.sys.OLEConstants;
29 import org.kuali.ole.sys.OLEKeyConstants;
30 import org.kuali.ole.sys.OLEPropertyConstants;
31 import org.kuali.ole.sys.OleAuthorizationConstants;
32 import org.kuali.ole.sys.context.SpringContext;
33 import org.kuali.ole.sys.document.AccountingDocument;
34 import org.kuali.ole.sys.document.validation.GenericValidation;
35 import org.kuali.ole.sys.document.validation.event.AttributedDocumentEvent;
36 import org.kuali.rice.core.api.util.type.KualiDecimal;
37 import org.kuali.rice.kim.api.identity.Person;
38 import org.kuali.rice.kns.document.authorization.TransactionalDocumentAuthorizer;
39 import org.kuali.rice.kns.document.authorization.TransactionalDocumentPresentationController;
40 import org.kuali.rice.kns.service.DocumentHelperService;
41 import org.kuali.rice.krad.bo.PersistableBusinessObject;
42 import org.kuali.rice.krad.service.BusinessObjectService;
43 import org.kuali.rice.krad.util.GlobalVariables;
44 import org.kuali.rice.krad.util.MessageMap;
45
46 public class DisbursementVoucherNonResidentAlienInformationValidation extends GenericValidation implements DisbursementVoucherConstants {
47 private static org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(DisbursementVoucherNonResidentAlienInformationValidation.class);
48
49 private AccountingDocument accountingDocumentForValidation;
50 private String validationType;
51
52
53
54
55 @Override
56 public boolean validate(AttributedDocumentEvent event) {
57 LOG.debug("validate start");
58 boolean isValid = true;
59
60 DisbursementVoucherDocument document = (DisbursementVoucherDocument) accountingDocumentForValidation;
61 DisbursementVoucherNonResidentAlienTax nonResidentAlienTax = document.getDvNonResidentAlienTax();
62 DisbursementVoucherPayeeDetail payeeDetail = document.getDvPayeeDetail();
63
64 Person financialSystemUser = GlobalVariables.getUserSession().getPerson();
65
66 List<String> taxEditMode = this.getTaxEditMode();
67 if (!payeeDetail.isDisbVchrAlienPaymentCode() || !this.hasRequiredEditMode(document, financialSystemUser, taxEditMode)) {
68 return true;
69 }
70
71 MessageMap errors = GlobalVariables.getMessageMap();
72 errors.addToErrorPath(OLEPropertyConstants.DOCUMENT);
73 errors.addToErrorPath(OLEPropertyConstants.DV_NON_RESIDENT_ALIEN_TAX);
74
75
76
77
78 if (StringUtils.isBlank(nonResidentAlienTax.getIncomeClassCode())) {
79 errors.putErrorWithoutFullErrorPath("DVNRATaxErrors", OLEKeyConstants.ERROR_REQUIRED, "Income class code");
80 return false;
81 }
82
83
84 if (StringUtils.isBlank(nonResidentAlienTax.getPostalCountryCode()) && !NRA_TAX_INCOME_CLASS_NON_REPORTABLE.equals(nonResidentAlienTax.getIncomeClassCode())) {
85 errors.putErrorWithoutFullErrorPath("DVNRATaxErrors", OLEKeyConstants.ERROR_REQUIRED, "Country code");
86 return false;
87 }
88
89
90 if(nonResidentAlienTax.getIncomeClassCode().equals(NRA_TAX_INCOME_CLASS_FELLOWSHIP) ){
91
92 }
93
94 if(nonResidentAlienTax.getIncomeClassCode().equals(NRA_TAX_INCOME_CLASS_INDEPENDENT_CONTRACTOR)){
95
96 }
97
98 if(nonResidentAlienTax.getIncomeClassCode().equals(NRA_TAX_INCOME_CLASS_ROYALTIES)){
99
100 }
101
102 if(nonResidentAlienTax.getIncomeClassCode().equals(NRA_TAX_INCOME_CLASS_NON_REPORTABLE)){
103 if( (nonResidentAlienTax.isForeignSourceIncomeCode()) || (nonResidentAlienTax.isIncomeTaxTreatyExemptCode()) ||
104 (nonResidentAlienTax.isTaxOtherExemptIndicator()) || (nonResidentAlienTax.isIncomeTaxGrossUpCode()) ||
105 (nonResidentAlienTax.isTaxUSAIDPerDiemIndicator()) || (nonResidentAlienTax.getTaxSpecialW4Amount() != null) ||
106 (nonResidentAlienTax.getReferenceFinancialDocumentNumber() != null) || (nonResidentAlienTax.getTaxNQIId() != null) ||
107 (nonResidentAlienTax.getPostalCountryCode() != null) ) {
108 String boxCode = "";
109 if(nonResidentAlienTax.isForeignSourceIncomeCode())
110 {
111 boxCode = "Foreign Source";
112 }
113 if(nonResidentAlienTax.isIncomeTaxTreatyExemptCode())
114 {
115 boxCode = "Treaty Exempt";
116 }
117 if(nonResidentAlienTax.isTaxOtherExemptIndicator())
118 {
119 boxCode = "Exempt Under Other Code";
120 }
121 if(nonResidentAlienTax.isIncomeTaxGrossUpCode())
122 {
123 boxCode = "Gross Up Payment";
124 }
125 if(nonResidentAlienTax.isTaxUSAIDPerDiemIndicator())
126 {
127 boxCode = "USAID Per Diem";
128 }
129 if(nonResidentAlienTax.getTaxSpecialW4Amount() != null)
130 {
131 boxCode = "Special W-4 Amount";
132 }
133 if(nonResidentAlienTax.getReferenceFinancialDocumentNumber() != null)
134 {
135 boxCode = "Reference Doc";
136 }
137 if(nonResidentAlienTax.getTaxNQIId() != null)
138 {
139 boxCode = "NQI Id";
140 }
141 if(nonResidentAlienTax.getPostalCountryCode() != null)
142 {
143 boxCode = "Country Code";
144 }
145 errors.putErrorWithoutFullErrorPath("DVNRATaxErrors", OLEKeyConstants.ERROR_DV_NON_REPORTABLE_ONLY, boxCode);
146 return false;
147 }
148 }
149
150
151
152
153 if (((nonResidentAlienTax.getFederalIncomeTaxPercent() == null) || (nonResidentAlienTax.getFederalIncomeTaxPercent().equals(KualiDecimal.ZERO))) && (nonResidentAlienTax.getIncomeClassCode().equals(NRA_TAX_INCOME_CLASS_NON_REPORTABLE)) ) {
154 nonResidentAlienTax.setFederalIncomeTaxPercent(KualiDecimal.ZERO);
155 }
156 else {
157 if (nonResidentAlienTax.getFederalIncomeTaxPercent() == null) {
158 errors.putErrorWithoutFullErrorPath("DVNRATaxErrors", OLEKeyConstants.ERROR_REQUIRED, "Federal tax percent");
159 return false;
160 }
161 else {
162
163 NonResidentAlienTaxPercent taxPercent = new NonResidentAlienTaxPercent();
164 taxPercent.setIncomeClassCode(nonResidentAlienTax.getIncomeClassCode());
165 taxPercent.setIncomeTaxTypeCode(FEDERAL_TAX_TYPE_CODE);
166 taxPercent.setIncomeTaxPercent(nonResidentAlienTax.getFederalIncomeTaxPercent());
167
168 NonResidentAlienTaxPercent retrievedPercent = (NonResidentAlienTaxPercent) SpringContext.getBean(BusinessObjectService.class).retrieve(taxPercent);
169 if (retrievedPercent == null) {
170 errors.putErrorWithoutFullErrorPath("DVNRATaxErrors", OLEKeyConstants.ERROR_DV_INVALID_FED_TAX_PERCENT, new String[] { nonResidentAlienTax.getFederalIncomeTaxPercent().toString(), nonResidentAlienTax.getIncomeClassCode() });
171 return false;
172 }
173 }
174 }
175 if (((nonResidentAlienTax.getStateIncomeTaxPercent() == null) || (nonResidentAlienTax.getStateIncomeTaxPercent().equals(KualiDecimal.ZERO))) && (nonResidentAlienTax.getIncomeClassCode().equals(NRA_TAX_INCOME_CLASS_NON_REPORTABLE)) ) {
176 nonResidentAlienTax.setStateIncomeTaxPercent(KualiDecimal.ZERO);
177 }
178 else {
179 if (nonResidentAlienTax.getStateIncomeTaxPercent() == null) {
180 errors.putErrorWithoutFullErrorPath("DVNRATaxErrors", OLEKeyConstants.ERROR_REQUIRED, "State tax percent");
181 return false;
182 }
183 else {
184
185 NonResidentAlienTaxPercent taxPercent = new NonResidentAlienTaxPercent();
186 taxPercent.setIncomeClassCode(nonResidentAlienTax.getIncomeClassCode());
187 taxPercent.setIncomeTaxTypeCode(STATE_TAX_TYPE_CODE);
188 taxPercent.setIncomeTaxPercent(nonResidentAlienTax.getStateIncomeTaxPercent());
189
190 PersistableBusinessObject retrievedPercent = SpringContext.getBean(BusinessObjectService.class).retrieve(taxPercent);
191 if (retrievedPercent == null) {
192 errors.putErrorWithoutFullErrorPath("DVNRATaxErrors", OLEKeyConstants.ERROR_DV_INVALID_STATE_TAX_PERCENT, nonResidentAlienTax.getStateIncomeTaxPercent().toString(), nonResidentAlienTax.getIncomeClassCode());
193 return false;
194 }
195 else {
196 if ((!document.getDvNonResidentAlienTax().getIncomeClassCode().equals(NRA_TAX_INCOME_CLASS_ROYALTIES)) && (!document.getDvNonResidentAlienTax().getIncomeClassCode().equals(NRA_TAX_INCOME_CLASS_INDEPENDENT_CONTRACTOR))) {
197
198 if ((document.getDvNonResidentAlienTax().getFederalIncomeTaxPercent().isGreaterThan(KualiDecimal.ZERO)) && (document.getDvNonResidentAlienTax().getStateIncomeTaxPercent().isZero())) {
199 errors.putErrorWithoutFullErrorPath("DVNRATaxErrors", OLEKeyConstants.ERROR_DV_STATE_INCOME_TAX_PERCENT_SHOULD_BE_GREATER_THAN_ZERO );
200 return false;
201 }
202
203 if ((document.getDvNonResidentAlienTax().getFederalIncomeTaxPercent().equals(KualiDecimal.ZERO)) && (!document.getDvNonResidentAlienTax().getStateIncomeTaxPercent().isZero())) {
204 errors.putErrorWithoutFullErrorPath("DVNRATaxErrors", OLEKeyConstants.ERROR_DV_STATE_TAX_SHOULD_BE_ZERO );
205 return false;
206 }
207 }
208 }
209 }
210 }
211
212
213
214
215
216
217 if( OneOrLessBoxesChecked(document) ) {
218
219
220 if( nonResidentAlienTax.isForeignSourceIncomeCode() ) {
221
222
223 if( (!nonResidentAlienTax.getFederalIncomeTaxPercent().equals(KualiDecimal.ZERO)) || (!nonResidentAlienTax.getStateIncomeTaxPercent().equals(KualiDecimal.ZERO)) ) {
224 errors.putErrorWithoutFullErrorPath("DVNRATaxErrors", OLEKeyConstants.ERROR_DV_NRA_TAX_WHEN_CHECKED_FEDERAL_AND_STATE_TAXES_SHOULD_BE_ZERO , "Foreign Source");
225 return false;
226 }
227
228 if((nonResidentAlienTax.isTaxUSAIDPerDiemIndicator()) || (nonResidentAlienTax.getTaxSpecialW4Amount() != null) ||
229 (nonResidentAlienTax.getReferenceFinancialDocumentNumber() != null) || (nonResidentAlienTax.getTaxNQIId() != null) ){
230 errors.putErrorWithoutFullErrorPath("DVNRATaxErrors", OLEKeyConstants.ERROR_DV_NRA_TAX_WHEN_CHECKED_CANNOT_HAVE_VALUE , "Foreign Source", "NQI Id, Reference Doc, USAID Per Diem, or Special W-4 Amount");
231 return false;
232 }
233 }
234
235
236 if( nonResidentAlienTax.isIncomeTaxTreatyExemptCode() ) {
237
238
239 if((nonResidentAlienTax.isTaxUSAIDPerDiemIndicator()) || (nonResidentAlienTax.getTaxSpecialW4Amount() != null) ||
240 (nonResidentAlienTax.getReferenceFinancialDocumentNumber() != null) || (nonResidentAlienTax.getTaxNQIId() != null) ){
241 errors.putErrorWithoutFullErrorPath("DVNRATaxErrors", OLEKeyConstants.ERROR_DV_NRA_TAX_WHEN_CHECKED_CANNOT_HAVE_VALUE , "Treaty Exempt", "NQI Id, Reference Doc, USAID Per Diem, or Special W-4 Amount");
242 return false;
243 }
244 }
245
246
247 if( nonResidentAlienTax.isIncomeTaxGrossUpCode() ) {
248
249
250
251 if( (nonResidentAlienTax.getFederalIncomeTaxPercent().equals(KualiDecimal.ZERO))) {
252 errors.putErrorWithoutFullErrorPath("DVNRATaxErrors", OLEKeyConstants.ERROR_DV_NRA_TAX_WHEN_CHECKED_FEDERAL_TAX_CANNOT_BE_ZERO, "Gross Up Payment" );
253 return false;
254 }
255
256 if((nonResidentAlienTax.isTaxUSAIDPerDiemIndicator()) || (nonResidentAlienTax.getTaxSpecialW4Amount() != null) ||
257 (nonResidentAlienTax.getReferenceFinancialDocumentNumber() != null) || (nonResidentAlienTax.getTaxNQIId() != null) ){
258 errors.putErrorWithoutFullErrorPath("DVNRATaxErrors", OLEKeyConstants.ERROR_DV_NRA_TAX_WHEN_CHECKED_CANNOT_HAVE_VALUE , "Gross Up Payment", "NQI Id, Reference Doc, USAID Per Diem, or Special W-4 Amount");
259 return false;
260 }
261 }
262
263
264 if( nonResidentAlienTax.isTaxOtherExemptIndicator() ) {
265
266
267
268 if( !(nonResidentAlienTax.getStateIncomeTaxPercent().equals(KualiDecimal.ZERO)) || !(nonResidentAlienTax.getFederalIncomeTaxPercent().equals(KualiDecimal.ZERO)) ) {
269 errors.putErrorWithoutFullErrorPath("DVNRATaxErrors", OLEKeyConstants.ERROR_DV_NRA_TAX_WHEN_CHECKED_FEDERAL_AND_STATE_TAXES_SHOULD_BE_ZERO , "Exempt Under Other Code");
270 return false;
271 }
272 }
273
274
275 if( nonResidentAlienTax.isTaxUSAIDPerDiemIndicator() ) {
276
277
278 if( !nonResidentAlienTax.getIncomeClassCode().equals(NRA_TAX_INCOME_CLASS_FELLOWSHIP) ) {
279 errors.putErrorWithoutFullErrorPath("DVNRATaxErrors", OLEKeyConstants.ERROR_DV_NRA_TAX_WHEN_CHECKED_SHOULD_BE_SELECTED, "USAID Per Diem", "Income Class Code : Fellowship");
280 return false;
281 }
282
283 if( !(nonResidentAlienTax.getStateIncomeTaxPercent().equals(KualiDecimal.ZERO)) || !(nonResidentAlienTax.getFederalIncomeTaxPercent().equals(KualiDecimal.ZERO)) ) {
284 errors.putErrorWithoutFullErrorPath("DVNRATaxErrors", OLEKeyConstants.ERROR_DV_NRA_TAX_WHEN_CHECKED_FEDERAL_AND_STATE_TAXES_SHOULD_BE_ZERO , "USAID Per Diem");
285 return false;
286 }
287
288 if( !nonResidentAlienTax.isTaxOtherExemptIndicator() ) {
289 errors.putErrorWithoutFullErrorPath("DVNRATaxErrors", OLEKeyConstants.ERROR_DV_NRA_TAX_WHEN_CHECKED_SHOULD_BE_SELECTED, "USAID Per Diem", "Exempt Under Other Code");
290 return false;
291 }
292
293 if( nonResidentAlienTax.getTaxSpecialW4Amount() != null ) {
294 errors.putErrorWithoutFullErrorPath("DVNRATaxErrors", OLEKeyConstants.ERROR_DV_NRA_TAX_WHEN_CHECKED_CANNOT_HAVE_VALUE, "USAID Per Diem", "Special W-4 Amount");
295 return false;
296 }
297 }
298
299
300 if( nonResidentAlienTax.getTaxSpecialW4Amount() != null ) {
301
302
303 if( !nonResidentAlienTax.getIncomeClassCode().equals(NRA_TAX_INCOME_CLASS_FELLOWSHIP) ) {
304 errors.putErrorWithoutFullErrorPath("DVNRATaxErrors", OLEKeyConstants.ERROR_DV_NRA_TAX_WHEN_CHECKED_SHOULD_BE_SELECTED, "Special W-4 Amount", "Income Class Code : Fellowship" );
305 return false;
306 }
307
308 if( !(nonResidentAlienTax.getStateIncomeTaxPercent().equals(KualiDecimal.ZERO)) || !(nonResidentAlienTax.getFederalIncomeTaxPercent().equals(KualiDecimal.ZERO)) ) {
309 errors.putErrorWithoutFullErrorPath("DVNRATaxErrors", OLEKeyConstants.ERROR_DV_NRA_TAX_WHEN_CHECKED_FEDERAL_AND_STATE_TAXES_SHOULD_BE_ZERO , "Special W-4 Amount");
310 return false;
311 }
312
313 if( !nonResidentAlienTax.isTaxOtherExemptIndicator() ) {
314 errors.putErrorWithoutFullErrorPath("DVNRATaxErrors", OLEKeyConstants.ERROR_DV_NRA_TAX_WHEN_CHECKED_SHOULD_BE_SELECTED, "Special W-4 Amount", "Exempt Under Other Code");
315 return false;
316 }
317
318 if( ( nonResidentAlienTax.isTaxUSAIDPerDiemIndicator() ) ) {
319 errors.putErrorWithoutFullErrorPath("DVNRATaxErrors", OLEKeyConstants.ERROR_DV_NRA_TAX_WHEN_CHECKED_CANNOT_BE_SELECTED, "Special W-4 Amount", "USAID Per Diem");
320 return false;
321 }
322 }
323
324
325 if( nonResidentAlienTax.getTaxNQIId() != null) {
326
327 }
328
329
330 if( nonResidentAlienTax.getReferenceFinancialDocumentNumber() != null) {
331
332 }
333
334 }
335
336
337
338 if(validationType!="GENERATE") {
339
340 if ((nonResidentAlienTax.getFederalIncomeTaxPercent().isNonZero() || nonResidentAlienTax.getStateIncomeTaxPercent().isNonZero())) {
341 if (StringUtils.isBlank(nonResidentAlienTax.getFinancialDocumentAccountingLineText())) {
342 errors.putErrorWithoutFullErrorPath(OLEConstants.GENERAL_NRATAX_TAB_ERRORS, OLEKeyConstants.ERROR_DV_NRA_NO_TAXLINES_GENERATED);
343 return false;
344 }
345 }
346 }
347
348 errors.removeFromErrorPath(OLEPropertyConstants.DV_NON_RESIDENT_ALIEN_TAX);
349 errors.removeFromErrorPath(OLEPropertyConstants.DOCUMENT);
350
351 return isValid;
352 }
353
354 private boolean stateAndFederalTaxesNotNull(DisbursementVoucherDocument document) {
355 if( (document.getDvNonResidentAlienTax().getFederalIncomeTaxPercent() != null) && (document.getDvNonResidentAlienTax().getStateIncomeTaxPercent() != null) ) {
356 return true;
357 }
358 return false;
359 }
360
361
362
363
364
365
366
367
368
369
370
371
372 private boolean hasRequiredEditMode(AccountingDocument accountingDocument, Person financialSystemUser, List<String> candidateEditModes) {
373 DocumentHelperService documentHelperService = SpringContext.getBean(DocumentHelperService.class);
374 TransactionalDocumentAuthorizer documentAuthorizer = (TransactionalDocumentAuthorizer) documentHelperService.getDocumentAuthorizer(accountingDocument);
375 TransactionalDocumentPresentationController presentationController = (TransactionalDocumentPresentationController) documentHelperService.getDocumentPresentationController(accountingDocument);
376
377 Set<String> presentationControllerEditModes = presentationController.getEditModes(accountingDocument);
378 Set<String> editModes = documentAuthorizer.getEditModes(accountingDocument, financialSystemUser, presentationControllerEditModes);
379
380 for (String editMode : candidateEditModes) {
381 if (editModes.contains(editMode)) {
382 return true;
383 }
384 }
385
386 return false;
387 }
388
389
390
391
392
393
394 protected List<String> getTaxEditMode() {
395 List<String> candidateEdiModes = new ArrayList<String>();
396 candidateEdiModes.add(OleAuthorizationConstants.DisbursementVoucherEditMode.TAX_ENTRY);
397
398 return candidateEdiModes;
399 }
400
401
402
403
404
405
406 public void setValidationType(String validationType) {
407 this.validationType = validationType;
408 }
409
410
411
412
413
414
415 public void setAccountingDocumentForValidation(AccountingDocument accountingDocumentForValidation) {
416 this.accountingDocumentForValidation = accountingDocumentForValidation;
417 }
418
419
420
421
422
423
424 public AccountingDocument getAccountingDocumentForValidation() {
425 return accountingDocumentForValidation;
426 }
427
428 private boolean OneOrLessBoxesChecked(DisbursementVoucherDocument document) {
429 MessageMap errors = GlobalVariables.getMessageMap();
430
431 int boxCnt = 0 ;
432 if(document.getDvNonResidentAlienTax().isForeignSourceIncomeCode()) {
433 boxCnt++;
434 }
435 if(document.getDvNonResidentAlienTax().isIncomeTaxTreatyExemptCode()) {
436 boxCnt++;
437 }
438 if(document.getDvNonResidentAlienTax().isTaxOtherExemptIndicator()) {
439 boxCnt++;
440 }
441 if(document.getDvNonResidentAlienTax().isIncomeTaxGrossUpCode()) {
442 boxCnt++;
443 }
444 if(boxCnt > 1) {
445
446 errors.putErrorWithoutFullErrorPath("DVNRATaxErrors", OLEKeyConstants.ERROR_DV_NRA_TAX_ONLY_ONE_SELECTION_ALLOWED);
447 return false;
448 }
449 else {
450 errors.removeFromErrorPath(OLEPropertyConstants.DV_NON_RESIDENT_ALIEN_TAX);
451 return true;
452 }
453 }
454 }