View Javadoc
1   /*
2    * The Kuali Financial System, a comprehensive financial management system for higher education.
3    * 
4    * Copyright 2005-2014 The Kuali Foundation
5    * 
6    * This program is free software: you can redistribute it and/or modify
7    * it under the terms of the GNU Affero General Public License as
8    * published by the Free Software Foundation, either version 3 of the
9    * License, or (at your option) any later version.
10   * 
11   * This program is distributed in the hope that it will be useful,
12   * but WITHOUT ANY WARRANTY; without even the implied warranty of
13   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14   * GNU Affero General Public License for more details.
15   * 
16   * You should have received a copy of the GNU Affero General Public License
17   * along with this program.  If not, see <http://www.gnu.org/licenses/>.
18   */
19  package org.kuali.kfs.module.tem.businessobject;
20  
21  import java.math.BigDecimal;
22  import java.sql.Date;
23  import java.sql.Timestamp;
24  import java.util.LinkedHashMap;
25  
26  import javax.persistence.Column;
27  import javax.persistence.Entity;
28  import javax.persistence.GeneratedValue;
29  import javax.persistence.Id;
30  import javax.persistence.JoinColumn;
31  import javax.persistence.ManyToOne;
32  import javax.persistence.SequenceGenerator;
33  import javax.persistence.Table;
34  
35  import org.kuali.kfs.module.tem.TemConstants;
36  import org.kuali.kfs.module.tem.TemConstants.TravelParameters;
37  import org.kuali.kfs.module.tem.TemParameterConstants;
38  import org.kuali.kfs.module.tem.document.TravelDocument;
39  import org.kuali.kfs.module.tem.document.service.MileageRateService;
40  import org.kuali.kfs.module.tem.document.web.struts.TravelFormBase;
41  import org.kuali.kfs.sys.context.SpringContext;
42  import org.kuali.kfs.sys.util.KfsDateUtils;
43  import org.kuali.rice.core.api.util.type.KualiDecimal;
44  import org.kuali.rice.coreservice.framework.parameter.ParameterService;
45  import org.kuali.rice.kns.util.KNSGlobalVariables;
46  import org.kuali.rice.krad.bo.PersistableBusinessObjectBase;
47  import org.kuali.rice.krad.util.ObjectUtils;
48  
49  @Entity
50  @Table(name = "TEM_PER_DIEM_EXP_T")
51  public class PerDiemExpense extends PersistableBusinessObjectBase {
52  
53      @Id
54      @GeneratedValue(generator = "TEM_PER_DIEM_EXP_ID_SEQ")
55      @SequenceGenerator(name = "TEM_PER_DIEM_EXP_ID_SEQ", sequenceName = "TEM_PER_DIEM_EXP_ID_SEQ", allocationSize = 5)
56      @Column(name = "ID", nullable = false)
57      private Integer id;
58      private String documentNumber;
59      private String countryState;
60      private String county;
61      private String primaryDestination;
62      //boolean flag if it gets disabled due to duplicate
63      private Boolean breakfast = Boolean.TRUE;
64      private Boolean lunch = Boolean.TRUE;
65      private Boolean dinner = Boolean.TRUE;
66      private Boolean personal = Boolean.FALSE;
67      private Boolean incidentalsWithMealsOnly;
68  
69      private KualiDecimal breakfastValue = KualiDecimal.ZERO;
70      private KualiDecimal lunchValue = KualiDecimal.ZERO;
71      private KualiDecimal dinnerValue = KualiDecimal.ZERO;
72      private KualiDecimal incidentalsValue = KualiDecimal.ZERO;
73  
74      private Integer primaryDestinationId;
75      private PrimaryDestination primaryDest;
76      private PerDiem perDiem;
77  
78      private Integer miles = new Integer(0);
79      private Timestamp mileageDate;
80      private ExpenseType mileageRateExpenseType;
81      private String mileageRateExpenseTypeCode;
82  
83      private String accommodationTypeCode;
84      private String accommodationName;
85      private String accommodationPhoneNum;
86      private String accommodationAddress;
87      private AccommodationType accommodationType;
88  
89      private KualiDecimal lodging = KualiDecimal.ZERO;
90      private boolean prorated = false;
91  
92      public Integer getId() {
93          return id;
94      }
95  
96      public void setId(Integer id) {
97          this.id = id;
98      }
99  
100     @Column(name = "FDOC_NBR", length = 14, nullable = false)
101     public String getDocumentNumber() {
102         return documentNumber;
103     }
104 
105     public void setDocumentNumber(String documentNumber) {
106         this.documentNumber = documentNumber;
107     }
108 
109     @Column(name = "COUNTRY", length = 100, nullable = false)
110     public String getCountryState() {
111         return countryState;
112     }
113 
114     public void setCountryState(String countryState) {
115         this.countryState = countryState;
116     }
117 
118     @Column(name = "COUNTY_CD", length = 100, nullable = false)
119     public String getCounty() {
120         return county;
121     }
122 
123     public void setCounty(String county) {
124         this.county = county;
125     }
126 
127     @Column(name = "PRI_DEST", length = 100, nullable = false)
128     public String getPrimaryDestination() {
129         return primaryDestination;
130     }
131 
132     public void setPrimaryDestination(String primaryDestination) {
133         this.primaryDestination = primaryDestination;
134     }
135 
136     @Column(name = "BREAKFAST_IND", nullable = false, length = 1)
137     public Boolean getBreakfast() {
138         return breakfast;
139     }
140 
141     public void setBreakfast(Boolean breakfast) {
142         this.breakfast = breakfast;
143     }
144 
145     @Column(name = "LUNCH_IND", nullable = false, length = 1)
146     public Boolean getLunch() {
147         return lunch;
148     }
149 
150     public void setLunch(Boolean lunch) {
151         this.lunch = lunch;
152     }
153 
154     @Column(name = "DINNER_IND", nullable = false, length = 1)
155     public Boolean getDinner() {
156         return dinner;
157     }
158 
159     public void setDinner(Boolean dinner) {
160         this.dinner = dinner;
161     }
162 
163     /**
164      * Gets the perDiemId attribute.
165      *
166      * @return Returns the perDiemId.
167      */
168     public Integer getPrimaryDestinationId() {
169         return primaryDestinationId;
170     }
171 
172     /**
173      * Sets the perDiemId attribute value.
174      *
175      * @param perDiemId The perDiemId to set.
176      */
177     public void setPrimaryDestinationId(Integer primaryDestinationId) {
178         this.primaryDestinationId = primaryDestinationId;
179     }
180 
181     public PrimaryDestination getPrimaryDest() {
182         return primaryDest;
183     }
184 
185     public void setPrimaryDest(PrimaryDestination primaryDest) {
186         this.primaryDest = primaryDest;
187     }
188 
189     /**
190      * Gets the perDiem attribute.
191      *
192      * @return Returns the perDiem.
193      */
194     /*public PerDiem getPerDiem() {
195         return perDiem;
196     }*/
197 
198     /**
199      * Sets the perDiem attribute value.
200      *
201      * @param perDiem The perDiem to set.
202      */
203     /*public void setPerDiem(PerDiem perDiem) {
204         this.perDiem = perDiem;
205 
206         setupCustomPerDiem();
207     }*/
208 
209     /**
210      * This method gets the accommodation type code associated with this day
211      *
212      * @return accoomodation type code
213      */
214     @Column(name = "ACCOM_TYP_CD", length = 4)
215     public String getAccommodationTypeCode() {
216         return accommodationTypeCode;
217     }
218 
219     /**
220      * This method sets the accommodation type code for this day
221      *
222      * @param accommodationTypeCode
223      */
224     public void setAccommodationTypeCode(String accommodationTypeCode) {
225         this.accommodationTypeCode = accommodationTypeCode;
226     }
227 
228     /**
229      * This method returns the current accommodation Type for this TripDetailEstimate
230      *
231      * @return accommodation Type
232      */
233     @ManyToOne
234     @JoinColumn(name = "ACCOM_TYP_CD")
235     public AccommodationType getAccommodationType() {
236         return accommodationType;
237     }
238 
239     /**
240      * This method is only used for when the object is initially populated from OJB
241      *
242      * @param accommodationType
243      */
244     public void setAccommodationType(AccommodationType accommodationType) {
245         this.accommodationType = accommodationType;
246     }
247 
248     /**
249      * This method returns the name of the accommodation for this day
250      *
251      * @return accommodation name
252      */
253     @Column(name = "ACCOM_NM")
254     public String getAccommodationName() {
255         return accommodationName;
256     }
257 
258     /**
259      * This method sets the accommodation name for this day
260      *
261      * @param accommodationName
262      */
263     public void setAccommodationName(String accommodationName) {
264         this.accommodationName = accommodationName;
265     }
266 
267     /**
268      * This method returns the accommodation's phone
269      *
270      * @return the phone number for the accommodation
271      */
272     @Column(name = "ACCOM_PH")
273     public String getAccommodationPhoneNum() {
274         return accommodationPhoneNum;
275     }
276 
277     /**
278      * This method sets the accommodation phone number
279      *
280      * @param accommodationPhoneNum
281      */
282     public void setAccommodationPhoneNum(String accommodationPhoneNum) {
283         this.accommodationPhoneNum = accommodationPhoneNum;
284     }
285 
286     /**
287      * This method returns the accommodation's address
288      *
289      * @return accommodation's address
290      */
291     @Column(name = "ACCOM_ADDRESS")
292     public String getAccommodationAddress() {
293         return accommodationAddress;
294     }
295 
296     /**
297      * This method sets the accommodation's address
298      *
299      * @param accommodationAddress
300      */
301     public void setAccommodationAddress(String accommodationAddress) {
302         this.accommodationAddress = accommodationAddress;
303     }
304 
305     /**
306      * This method gets the lodging cost for this day. This method does not take into account personal expenses. Use getLodgingTotal() for that.
307      *
308      * @return lodging cost
309      */
310     @Column(name = "LODGING", precision = 19, scale = 2)
311     public KualiDecimal getLodging() {
312         if (ObjectUtils.isNotNull(lodging) && this.lodging.isGreaterThan(KualiDecimal.ZERO)) {
313             return lodging;
314         }
315 
316         return KualiDecimal.ZERO;
317     }
318 
319     /**
320      * @return the amount of lodging, without logic that may force it back to zero
321      */
322     public KualiDecimal getUnfilteredLodging() {
323         return lodging;
324     }
325 
326     /**
327      * Matching setter for getUnfilteredLoding, functionally equivalent to setLodging
328      * @param lodging
329      */
330     public void setUnfilteredLodging(KualiDecimal lodging) {
331         this.lodging = lodging;
332     }
333 
334     /**
335      * This method sets the lodging cost for this day
336      *
337      * @param lodging
338      */
339     public void setLodging(KualiDecimal lodging) {
340         this.lodging = lodging;
341     }
342 
343     @Column(name = "MILES", nullable = false)
344     public Integer getMiles() {
345         if (ObjectUtils.isNotNull(miles) && miles > 0) {
346             return miles;
347         }
348 
349         return 0;
350     }
351 
352     public void setMiles(Integer miles) {
353         this.miles = miles;
354     }
355 
356     public Integer getUnfilteredMiles() {
357         return miles;
358     }
359 
360     public void setUnfilteredMiles(Integer miles) {
361         this.miles = miles;
362     }
363 
364     /**
365      * Gets the breakfastValue attribute.
366      *
367      * @return Returns the breakfastValue.
368      */
369     public KualiDecimal getBreakfastValue() {
370         if (ObjectUtils.isNotNull(breakfastValue) && this.breakfastValue.isGreaterThan(KualiDecimal.ZERO)) {
371             return breakfastValue;
372         }
373 
374         return KualiDecimal.ZERO;
375     }
376 
377     /**
378      * Sets the breakfastValue attribute value.
379      *
380      * @param breakfastValue The breakfastValue to set.
381      */
382     public void setBreakfastValue(KualiDecimal breakfastValue) {
383         this.breakfastValue = breakfastValue;
384     }
385 
386     public KualiDecimal getUnfilteredBreakfastValue() {
387         return this.breakfastValue;
388     }
389 
390     public void setUnfilteredBreakfastValue(KualiDecimal breakfastValue) {
391         this.breakfastValue = breakfastValue;
392     }
393 
394     /**
395      * Gets the lunchValue attribute.
396      *
397      * @return Returns the lunchValue.
398      */
399     public KualiDecimal getLunchValue() {
400         if (ObjectUtils.isNotNull(lunchValue) && this.lunchValue.isGreaterThan(KualiDecimal.ZERO)) {
401             return lunchValue;
402         }
403 
404         return KualiDecimal.ZERO;
405     }
406 
407     /**
408      * Sets the lunchValue attribute value.
409      *
410      * @param lunchValue The lunchValue to set.
411      */
412     public void setLunchValue(KualiDecimal lunchValue) {
413         this.lunchValue = lunchValue;
414     }
415 
416     public KualiDecimal getUnfilteredLunchValue() {
417         return this.lunchValue;
418     }
419 
420     public void setUnfilteredLunchValue(KualiDecimal lunchValue) {
421         this.lunchValue = lunchValue;
422     }
423 
424     /**
425      * Gets the dinnerValue attribute.
426      *
427      * @return Returns the dinnerValue.
428      */
429     public KualiDecimal getDinnerValue() {
430         if (ObjectUtils.isNotNull(dinnerValue) && this.dinnerValue.isGreaterThan(KualiDecimal.ZERO)) {
431             return dinnerValue;
432         }
433 
434         return KualiDecimal.ZERO;
435     }
436 
437     /**
438      * Sets the dinnerValue attribute value.
439      *
440      * @param dinnerValue The dinnerValue to set.
441      */
442     public void setDinnerValue(KualiDecimal dinnerValue) {
443         this.dinnerValue = dinnerValue;
444     }
445 
446     public KualiDecimal getUnfilteredDinnerValue() {
447         return this.dinnerValue;
448     }
449 
450     public void setUnfilteredDinnerValue(KualiDecimal dinnerValue) {
451         this.dinnerValue = dinnerValue;
452     }
453 
454     @ManyToOne
455     @JoinColumn(name = "MILEAGE_RT_EXP_TYP_CD")
456     public ExpenseType getMileageRateExpenseType() {
457         return mileageRateExpenseType;
458     }
459 
460     public void setMileageRateExpenseType(ExpenseType mileageRateExpenseType) {
461         this.mileageRateExpenseType = mileageRateExpenseType;
462     }
463 
464     @Column(name = "MILEAGE_RT_EXP_TYP_CD")
465     public String getMileageRateExpenseTypeCode() {
466         return mileageRateExpenseTypeCode;
467     }
468 
469     public void setMileageRateExpenseTypeCode(String mileageRateExpenseTypeCode) {
470         this.mileageRateExpenseTypeCode = mileageRateExpenseTypeCode;
471     }
472 
473     public MileageRate getMileageRate(java.sql.Date effectiveDate) {
474         return SpringContext.getBean(MileageRateService.class).findMileageRateByExpenseTypeCodeAndDate(getMileageRateExpenseTypeCode(), effectiveDate);
475     }
476 
477     /**
478      * Determines if the mileage date for this per diem expense matches the range for the given mileage rate
479      * @param mileageRate the mileage rate to check the mileage date against
480      * @return true if the mileage date matches, false otherwise
481      */
482     protected boolean isMileageDateWithinMileageRateRange(MileageRate mileageRate) {
483         final Date fromDate = mileageRate.getActiveFromDate();
484         final Date toDate = mileageRate.getActiveToDate();
485 
486         return (KfsDateUtils.isSameDay(fromDate, getMileageDate()) || fromDate.before(getMileageDate())) && (KfsDateUtils.isSameDay(toDate, getMileageDate()) || toDate.after(getMileageDate()));
487     }
488 
489     public KualiDecimal getMileageTotal() {
490         KualiDecimal total = KualiDecimal.ZERO;
491         if (KNSGlobalVariables.getKualiForm() instanceof TravelFormBase) {
492             final TravelFormBase travelForm = (TravelFormBase)KNSGlobalVariables.getKualiForm();
493             if (travelForm == null) {
494                 return KualiDecimal.ZERO;
495             }
496             final TravelDocument travelDocument = travelForm.getTravelDocument();
497             return getMileageTotalForDocument(travelDocument);
498         }
499 
500         return total;
501     }
502 
503     protected KualiDecimal getMileageTotalForDocument(TravelDocument travelDocument) {
504         KualiDecimal total = KualiDecimal.ZERO;
505         if (!personal) {
506             if (travelDocument == null) {
507                 return KualiDecimal.ZERO;
508             }
509             final java.sql.Date effectiveDate = travelDocument.getEffectiveDateForMileageRate(this);
510 
511             final MileageRate rate = getMileageRate(effectiveDate);
512             if (ObjectUtils.isNotNull(rate) && ObjectUtils.isNotNull(this.miles) && this.miles > 0) {
513                 total = new KualiDecimal(new BigDecimal(miles).multiply(rate.getRate()));
514             }
515         }
516 
517         return total;
518     }
519 
520     public KualiDecimal getDailyTotal() {
521         KualiDecimal total = KualiDecimal.ZERO;
522         if (!personal) {
523             total = total.add(getMileageTotal());
524             total = total.add(getLodging());
525             total = total.add(getMealsAndIncidentals());
526         }
527 
528         return total;
529     }
530 
531     public KualiDecimal getDailyTotalForDocument(TravelDocument travelDoc) {
532         KualiDecimal total = KualiDecimal.ZERO;
533         if (!personal) {
534             total = total.add(getMileageTotalForDocument(travelDoc));
535             total = total.add(getLodging());
536             total = total.add(getMealsAndIncidentals());
537         }
538 
539         return total;
540     }
541 
542     /**
543      *
544      * This method gets the mealsTotal with
545      * @return
546      */
547     public KualiDecimal getMealsTotal() {
548         KualiDecimal total = KualiDecimal.ZERO;
549         if (!personal) {
550             if (breakfast) {
551                 total = total.add(this.getBreakfastValue());
552             }
553             if (lunch) {
554                 total = total.add(this.getLunchValue());
555             }
556             if (dinner) {
557                 total = total.add(this.getDinnerValue());
558             }
559         }
560         return total;
561     }
562 
563     /**
564      *
565      * This method gets the Lodging Total if it is not a personal expense.
566      * @return
567      */
568     public KualiDecimal getLodgingTotal() {
569         if (!personal) {
570             return this.getLodging();
571         }
572         return KualiDecimal.ZERO;
573     }
574 
575     /**
576      * Retrieve the Mileage date of per diem
577      *
578      * CLEANUP: mileage date should be the per diem expense date
579      *
580      * @return mileage date
581      */
582     @Column(name = "MLG_DT")
583     public Timestamp getMileageDate() {
584         return mileageDate;
585     }
586 
587     public KualiDecimal getMealsAndIncidentals() {
588         KualiDecimal total = KualiDecimal.ZERO;
589         if (!personal) {
590             total = total.add(getMealsTotal());
591             total = total.add(getIncidentalsValue());
592         }
593         return total;
594     }
595 
596 
597     public static KualiDecimal calculateMealsAndIncidentalsProrated(KualiDecimal total, Integer perDiemPercent) {
598         KualiDecimal percent = new KualiDecimal(perDiemPercent).divide(new KualiDecimal(100));
599         total = total.multiply(percent);
600         return total;
601     }
602 
603     /**
604      *
605      * This method split mealsAndIncidentals into breakfast, lunch, dinner and incidentals (overriding the existing breakfast, lunch, dinner and incidentals values).
606      * @param mealsAndIncidentals
607      */
608     public void setMealsAndIncidentals(KualiDecimal mealsAndIncidentals) {
609         KualiDecimal meal = mealsAndIncidentals.divide(new KualiDecimal(4));
610         setBreakfastValue(meal);
611         setLunchValue(meal);
612         setDinnerValue(meal);
613         setIncidentalsValue(mealsAndIncidentals.subtract(getMealsTotal()));
614     }
615 
616     /**
617      * This method returns whether or not this is a personal expense or not (true for personal expense, false otherwise)
618      *
619      * @return true for personal expense, false otherwise
620      */
621     @Column(name = "PERSONAL", nullable = false, length = 1)
622     public Boolean getPersonal() {
623         return personal;
624     }
625 
626     /**
627      * This method sets true if this is a personal expense
628      *
629      * @param true for personal expense
630      */
631     public void setPersonal(Boolean personal) {
632         this.personal = personal;
633     }
634 
635     /**
636      * Assign the Mileage date of per diem
637      *
638      * @param mileageDate as Date
639      */
640     public void setMileageDate(final Timestamp mileageDate) {
641         this.mileageDate = mileageDate;
642     }
643 
644     @SuppressWarnings("rawtypes")
645     protected LinkedHashMap toStringMapper_RICE20_REFACTORME() {
646         LinkedHashMap map = new LinkedHashMap();
647         map.put("id", id);
648         map.put("countryState", this.countryState);
649         map.put("county", this.county);
650         map.put("primaryDestination", this.primaryDestination);
651 
652         return map;
653     }
654 
655     public KualiDecimal getDefaultMealsAndIncidentals() {
656         KualiDecimal total = KualiDecimal.ZERO;
657         if (!personal && this.perDiem != null) {
658             if (breakfast) {
659                 total = total.add(this.perDiem.getBreakfast());
660             }
661             if (lunch) {
662                 total = total.add(this.perDiem.getLunch());
663             }
664             if (dinner) {
665                 total = total.add(this.perDiem.getDinner());
666             }
667 
668             // finally add in the incidentals
669             if (getIncludeIncidentals()) {
670                 total = total.add(this.perDiem.getIncidentals());
671             }
672         }
673         return total;
674     }
675 
676     public boolean isCustomPerDiem() {
677         return primaryDestinationId == null || this.primaryDestinationId == TemConstants.CUSTOM_PRIMARY_DESTINATION_ID;
678     }
679 
680     /**
681      * This method checks for incidentals inclusion to the mealsAndIncidentals calculation.
682      *
683      * @return
684      */
685     public Boolean getIncludeIncidentals() {
686         return !(!breakfast && !lunch && !dinner && getIncidentalsWithMealsOnly());
687     }
688 
689     public Boolean getIncidentalsWithMealsOnly() {
690         if (incidentalsWithMealsOnly == null) {
691             final boolean incidentalsWithMealsOnlyInd = SpringContext.getBean(ParameterService.class).getParameterValueAsBoolean(TemParameterConstants.TEM_DOCUMENT.class, TravelParameters.INCIDENTALS_WITH_MEALS_IND, Boolean.FALSE);
692 
693             incidentalsWithMealsOnly = incidentalsWithMealsOnlyInd;
694         }
695 
696         return incidentalsWithMealsOnly;
697     }
698 
699     public void setIncidentalsWithMealsOnly(Boolean incidentalsWithMealsOnly) {
700         this.incidentalsWithMealsOnly = incidentalsWithMealsOnly;
701     }
702 
703     /**
704      * This method returns incidentalsValue affected by INCIDENTALS_WITH_MEALS_IND parameter
705      *
706      * @return
707      */
708     public KualiDecimal getIncidentalsValue() {
709         if (getIncludeIncidentals()) {
710             if (ObjectUtils.isNotNull(incidentalsValue) && this.incidentalsValue.isGreaterThan(KualiDecimal.ZERO)) {
711                 return incidentalsValue;
712             }
713         }
714 
715         return KualiDecimal.ZERO;
716     }
717 
718     public void setIncidentalsValue(KualiDecimal incidentalsValue) {
719         this.incidentalsValue = incidentalsValue;
720     }
721 
722     public KualiDecimal getUnfilteredIncidentalsValue() {
723         return this.incidentalsValue;
724     }
725 
726     public void setUnfilteredIncidentalsValue(KualiDecimal incidentalsValue) {
727         this.incidentalsValue = incidentalsValue;
728     }
729 
730     public boolean isProrated() {
731         if(isCustomPerDiem()){
732             return false;
733         }
734 
735         return prorated;
736     }
737 
738     public void setProrated(boolean prorated) {
739         this.prorated = prorated;
740     }
741 
742     /**
743      * Gets the countryStateText attribute.
744      *
745      * @return Returns the countryStateText
746      */
747 
748     public String getCountryStateText() {
749         return countryState;
750     }
751 
752     /**
753      * Sets the countryStateText attribute.
754      *
755      * @param countryStateText The countryStateText to set.
756      */
757     public void setCountryStateText(String countryState) {
758         this.countryState = countryState;
759     }
760 
761 
762 }