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.document.service;
20
21 import java.sql.Date;
22 import java.sql.Timestamp;
23 import java.util.Collection;
24 import java.util.List;
25 import java.util.Map;
26 import java.util.Set;
27
28 import org.kuali.kfs.integration.ar.AccountsReceivableOrganizationOptions;
29 import org.kuali.kfs.module.tem.businessobject.ActualExpense;
30 import org.kuali.kfs.module.tem.businessobject.ExpenseTypeAware;
31 import org.kuali.kfs.module.tem.businessobject.GroupTraveler;
32 import org.kuali.kfs.module.tem.businessobject.PerDiem;
33 import org.kuali.kfs.module.tem.businessobject.PerDiemExpense;
34 import org.kuali.kfs.module.tem.businessobject.SpecialCircumstances;
35 import org.kuali.kfs.module.tem.businessobject.TemExpense;
36 import org.kuali.kfs.module.tem.businessobject.TemSourceAccountingLine;
37 import org.kuali.kfs.module.tem.businessobject.TransportationModeDetail;
38 import org.kuali.kfs.module.tem.businessobject.TravelAdvance;
39 import org.kuali.kfs.module.tem.businessobject.TripType;
40 import org.kuali.kfs.module.tem.document.TEMReimbursementDocument;
41 import org.kuali.kfs.module.tem.document.TravelAuthorizationDocument;
42 import org.kuali.kfs.module.tem.document.TravelDocument;
43 import org.kuali.kfs.module.tem.document.TravelReimbursementDocument;
44 import org.kuali.rice.core.api.util.KeyValue;
45 import org.kuali.rice.core.api.util.type.KualiDecimal;
46 import org.kuali.rice.kew.api.exception.WorkflowException;
47 import org.kuali.rice.kim.api.identity.Person;
48 import org.kuali.rice.krad.document.Document;
49 import org.kuali.rice.krad.uif.field.LinkField;
50
51 /**
52 * Travel Document Service
53 */
54 public interface TravelDocumentService {
55
56 public String getMessageFrom(final String messageType, String... args);
57
58 List<SpecialCircumstances> findActiveSpecialCircumstances(String documentNumber, String documentType);
59
60 List<TravelAuthorizationDocument> findAuthorizationDocuments(final String travelDocumentNumber);
61
62 /**
63 * Retrieves the numbers of any Travel Authorization (or child) documents associated with the given trip id
64 * @param travelDocumentIdentifier the trip id to find authorizations related to
65 * @return a List of TravelAuthorization (or child!) document numbers for authorizations associated with the given trip id
66 */
67 List<String> findAuthorizationDocumentNumbers(final String travelDocumentIdentifier);
68
69 List<TravelReimbursementDocument> findReimbursementDocuments(final String travelDocumentIdentifier);
70
71 /**
72 * Updates the perdiem items in a {@link TravelReimbursementDocument}. Can be used on an empty {@link Collection}. This means
73 * that if there are no perdiem items, it will recreate. Perfect do all stupid method.
74 *
75 * @param documentNumber is the original document number for reference to link the {@link Collection} items to
76 * @param perDiemList is the {@link List} that holds the per diem items. Please let this not be null
77 * @param perDiemId is the id of the {@link PerDiem} object used for this item
78 * @param start is the {@link Date} for the start of the trip
79 * @param end is the {@link Date} for the end of the trip
80 */
81 void updatePerDiemItemsFor(final TravelDocument document, final List<PerDiemExpense> perDiemList, final Integer perDiemId, final Timestamp start, final Timestamp end);
82
83 /**
84 * Wrapper function to retrieve by document number
85 *
86 * @param document
87 * @return
88 * @throws WorkflowException
89 */
90 Map<String, List<Document>> getDocumentsRelatedTo(final TravelDocument document) throws WorkflowException;
91
92 /**
93 * Get DV, TA, TAA, TAC, TR, and AV documents related to the given <code>documentNumber</code>. travel document either
94 * have a TEM document number or they have the value of the <code>travelDocumentIdentifier</code> in their organization doc
95 * ids.
96 *
97 * @param documentNumber
98 * @return
99 * @throws WorkflowException
100 */
101 Map<String, List<Document>> getDocumentsRelatedTo(final String documentNumber) throws WorkflowException;
102
103 /**
104 * Get related document lists filtering by the document type
105 *
106 * @param document
107 * @param documentType
108 * @return
109 */
110 List<Document> getDocumentsRelatedTo(final TravelDocument document, String... documentType);
111
112
113 /**
114 * @deprecated This method is no longer called and will be removed in KFS 6.0.
115 *
116 * This method will add fyi notes to initiator when document is cancelled, closed, etc.
117 *
118 * @param document
119 */
120 @Deprecated
121 void addAdHocFYIRecipient(final Document document);
122
123 /**
124 * This method will add fyi notes to initiator when document is cancelled, closed, etc.
125 *
126 * @param document
127 * @param initiatorUserId
128 */
129 void addAdHocFYIRecipient(final Document document, String initiatorUserId);
130
131 /**
132 * This method will add notes to initiator when document is cancelled, closed, etc.
133 *
134 * @param document
135 * @param initiatorUserId
136 */
137 void addAdHocRecipient(Document document, String initiatorUserId, String actionRequested);
138
139 void routeToFiscalOfficer(final TravelDocument document, final String noteText) throws WorkflowException, Exception;
140
141 /**
142 * This method copies the per diem expense object
143 *
144 * @param perDiemExpense
145 * @return the copied per diem expense
146 */
147 PerDiemExpense copyPerDiemExpense(PerDiemExpense perDiemExpense);
148
149 /**
150 * This method calculates mileage and returns calculated value
151 *
152 * @param actualExpense
153 * @return mileageAmount
154 */
155 KualiDecimal calculateMileage(ActualExpense actualExpense);
156
157 /**
158 *
159 */
160 public void handleNewActualExpense(final ActualExpense newActualExpenseLine);
161
162 /**
163 * This method calculates the daily total for a given per diem mileage expense
164 *
165 * @param perDiemMilaeage
166 * @return a map for each expense (mileage, lodging, per diem)
167 */
168 Map<String, KualiDecimal> calculateDailyTotal(PerDiemExpense perDiemMilaeage);
169
170 /**
171 * This method calculates the daily totals for a list of per diem mileage expenses
172 *
173 * @param perDiemExpenses
174 * @return a list of mapped totals
175 */
176 List<Map<String, KualiDecimal>> calculateDailyTotals(List<PerDiemExpense> perDiemExpenses);
177
178 /**
179 * This method copies from one per diem mileage down the rest of the list
180 *
181 * @param travelDocument the travel document (with begin or end dates) to help determine how much of the per diem expense to copy down
182 * @param copyIndex
183 * @param perDiemExpenses
184 * @return the modified list of perDiemExpenses back
185 */
186 void copyDownPerDiemExpense(TravelDocument travelDocument, int copyIndex, List<PerDiemExpense> perDiemExpenses);
187
188 /**
189 * Determines if an object with an expense type is that of a "hosted" meal. In TEM a hosted meal is a meal that has been
190 * provided by a hosting institution and cannot be taken as a reimbursement.
191 *
192 * @param havingExpenseType has an expense type to check for meal hosting
193 * @return true if the expense is a hosted meal or not
194 */
195 boolean isHostedMeal(final ExpenseTypeAware havingExpenseType);
196
197 /**
198 * Check to see if the user has the travel manager role assigned to them
199 *
200 * @param user
201 * @return true if the user is a travel manager, false otherwise
202 */
203 public boolean isTravelManager(final Person user);
204
205 public Integer calculateProratePercentage(PerDiemExpense perDiemExpense, String perDiemCalcMethod, Timestamp tripEnd);
206
207 public boolean isOpen(TravelDocument document);
208
209 public boolean isProcessed(TravelDocument document);
210
211 public boolean isFinal(TravelDocument document);
212
213 /**
214 * Check if the Travel authorization document has been successfully processed
215 *
216 * @param document
217 * @return
218 */
219 public boolean isTravelAuthorizationProcessed(TravelAuthorizationDocument document);
220
221 /**
222 * Check if the Travel authroization document is processed AND is open for reimbursement in the app doc status
223 *
224 * @param document
225 * @return
226 */
227 public boolean isTravelAuthorizationOpened(TravelAuthorizationDocument document);
228
229 public boolean isUnsuccessful(TravelDocument document);
230
231 public Integer calculatePerDiemPercentageFromTimestamp(PerDiemExpense perDiemExpense, Timestamp tripEnd);
232
233 public KualiDecimal getAmountDueFromInvoice(String documentNumber, KualiDecimal requestedAmount);
234
235 public TravelAuthorizationDocument findCurrentTravelAuthorization(TravelDocument document);
236
237 public TravelDocument findRootForTravelReimbursement(String travelDocumentIdentifier);
238
239 public KualiDecimal getTotalCumulativeReimbursements(TravelDocument document);
240
241 public KualiDecimal getTotalAuthorizedEncumbrance(TravelDocument document);
242
243 public boolean isResponsibleForAccountsOn(final TravelDocument document, String principalId);
244
245 public boolean checkNonEmployeeTravelerTypeCode(String travelerTypeCode);
246
247 /**
248 * This is a ajax method, will be used to retrieve all states based on the country code passed
249 *
250 * @param countryCode
251 * @return String
252 */
253 public String getAllStates(final String countryCode);
254
255 /**
256 * Copies group travelers and sets new document number
257 */
258 public List<GroupTraveler> copyGroupTravelers(List<GroupTraveler> groupTravelers, String documentNumber);
259
260 /**
261 * Copies other travel expenses and sets new document number
262 */
263 public List<? extends TemExpense> copyActualExpenses(List<? extends TemExpense> actualExpenses, String documentNumber);
264
265 /**
266 * Copies per diem expenses and sets new document number
267 */
268 public List<PerDiemExpense> copyPerDiemExpenses(List<PerDiemExpense> perDiemExpenses, String documentNumber);
269
270 /**
271 * Copies travel advances and sets new document number
272 */
273 public List<TravelAdvance> copyTravelAdvances(List<TravelAdvance> travelAdvances, String documentNumber);
274
275 /**
276 * Copies special circumstances and sets new document number
277 */
278 public List<SpecialCircumstances> copySpecialCircumstances(List<SpecialCircumstances> specialCircumstancesList, String documentNumber);
279
280 /**
281 * Copies transportation mode details and sets new document number
282 */
283 public List<TransportationModeDetail> copyTransportationModeDetails(List<TransportationModeDetail> transportationModeDetails, String documentNumber);
284
285 /**
286 *
287 * @param document
288 */
289 public void showNoTravelAuthorizationError(TravelReimbursementDocument document);
290
291 /**
292 *
293 * This method gets the total of all advances given for the trip relating to the travel document.
294 * @param travelDocument
295 * @return {@linK KualiDecimal} that is the total of all advances
296 */
297 KualiDecimal getAdvancesTotalFor(final TravelDocument travelDocument);
298
299 /**
300 * get all outstanding travel advances by the given invoice document numbers. The advances must have not been used to generate
301 * taxable ramification
302 *
303 * @param arInvoiceDocNumbers the given AR invoice document numbers
304 * @return a list of outstanding travel advances
305 */
306
307 List<TravelAdvance> getOutstandingTravelAdvanceByInvoice(Set<String> arInvoiceDocNumber);
308
309 String retrieveAddressFromLocationCode(String locationCode);
310
311 /**
312 * Remove the imported expense from the document (though DB)
313 *
314 * @param document
315 */
316 public void detachImportedExpenses(TravelDocument document);
317
318 /**
319 * Adding the imported expense to the document (in the DB)
320 *
321 * @param document
322 */
323 public void attachImportedExpenses(TravelDocument document);
324
325 public boolean checkHoldGLPEs(TravelDocument document);
326
327 public void revertOriginalDocument(TravelDocument travelDocument, String status);
328
329 /**
330 * find the latest taxable ramification notification date
331 *
332 * @return the latest taxable ramification notification date
333 */
334 Date findLatestTaxableRamificationNotificationDate();
335
336 /**
337 * Perform validation on accounting lines that have already been entered, but have the potential to have bad data inserted into the db.
338 * @param TravelDocument
339 * @return
340 * true if valid, false otherwise
341 */
342 public boolean validateSourceAccountingLines(TravelDocument travelDocument, boolean addToErrorPath);
343
344 /**
345 * Get the Generic document type name of the travel document
346 *
347 * TA(not TAC, TAA), TR, ENT, RELO
348 *
349 * @param document
350 * @return
351 */
352 public String getDocumentType(TravelDocument document);
353
354 /**
355 *
356 * This method creates a key-value pair of MileageRates that are valid for the searchDate.
357 * @param searchDate
358 * @return
359 */
360 List<KeyValue> getMileageRateKeyValues(Date searchDate);
361
362 /**
363 * Import {@link GroupTraveler} instances into a {@link TravelDocument} via CSV data
364 *
365 * @param document to add {@link GroupTraveler} instances to
366 * @param csvData
367 * @throws Exception when there's an error parsing the CSV data
368 */
369 List<GroupTraveler> importGroupTravelers(final TravelDocument document, final String csvData) throws Exception;
370
371 /**
372 *
373 * This method imports the file and convert it to a list of objects (of the class specified in the parameter)
374 * @param formFile
375 * @param c
376 * @param attributeNames
377 * @param tabErrorKey
378 * @return
379 */
380 <T> List<T> importFile(final String fileContents, final Class<T> c, final String[] attributeNames,
381 final Map<String,List<String>> defaultValues, final Integer[] attributeMaxLength, final String tabErrorKey);
382
383 /**
384 * Returns all travel advances associated with the passed in trip id
385 * @param travelDocumentIdentifier the trip id of the reimbursement
386 * @return a List of all TravelAdvances associated with that trip
387 */
388 public List<TravelAdvance> getTravelAdvancesForTrip(String travelDocumentIdentifier);
389
390 /**
391 * @return the default AR organization options for TEM documents
392 */
393 public AccountsReceivableOrganizationOptions getOrgOptions();
394
395 /**
396 * This method searches to make sure that the expense entered doesn't already exist
397 * If they exist, disable them in the per diem table and notify the user.
398 * @param trDocument
399 * the current doc.
400 * @param actualExpense
401 * the expense in question
402 */
403 public void disableDuplicateExpenses(TravelDocument trDocument, ActualExpense actualExpense);
404
405 /**
406 * Sets the meal and incidental amounts on the given per diem expense
407 * @param expense the expense to set amounts on
408 * @param perDiem the per diem record amounts are based off of
409 * @param tripType the trip type being taken
410 * @param tripEnd the end time of the trip
411 * @param shouldProrate whether this expense should be prorated
412 */
413 public void setPerDiemMealsAndIncidentals(PerDiemExpense expense, PerDiem perDiem, TripType tripType, Timestamp tripEnd, boolean shouldProrate);
414
415 /**
416 *
417 * This method gets the parent travel document by travel document identifier
418 * This means: the current TA which is the authorization of the trip; or if no TA is present, the root TR, ENT, or RELO document
419 * @param travelDocumentIdentifier
420 * @return
421 */
422 public TravelDocument getParentTravelDocument(String travelDocumentIdentifier);
423
424 /**
425 * Returns the root travel document by the travel document identifier. This is the progenitor document of the trip - either the first TA,
426 * first TR, first ENT, or first RELO which began the trip
427 * It does not retrieve the workflow document of the associated document
428 * @param travelDocumentIdentifier
429 * @return the root document of the trip
430 */
431 public TravelDocument getRootTravelDocumentWithoutWorkflowDocument(String travelDocumentIdentifier);
432
433 /**
434 * This method retrieves a list of approved documents related to a travelDocumentIdentifier. It will grab the most current TA (TAA, TAC)
435 * and all TR, ENT, and RELO for the given identifier.
436 *
437 * @param travelDocumentIdentifier
438 * @return
439 */
440 public Collection<String> getApprovedTravelDocumentNumbersByTrip(String travelDocumentIdentifier);
441
442 /**
443 * This method determines whether a document is in the correct state for reconciling external vendor charges.
444 *
445 * @param travelDocument
446 * @return
447 */
448 public boolean isDocumentStatusValidForReconcilingCharges(TravelDocument travelDocument);
449
450 /**
451 * find matching trips for the same traveler, dates
452 *
453 */
454 public List<String> findMatchingTrips(TravelDocument document);
455
456 /**
457 * If a value on a per diem expense has been zero'd out, this method will restore it to its default value
458 * @param document the document with per diem expenses
459 * @param property the property to restore
460 */
461 public void restorePerDiemProperty(TravelDocument document, String property);
462
463 /**
464 * This smooshes the accounting lines which will do advance clearing. Here, since we're replacing the object code, we'll smooth together all accounting lines
465 * which have the same chart - account - sub-acount.
466 * @param originalAccountingLines the List of accounting lines to smoosh
467 * @return the smooshed accounting lines
468 */
469 public List<TemSourceAccountingLine> smooshAccountingLinesToSubAccount(List<TemSourceAccountingLine> originalAccountingLines);
470
471 /**
472 * Generates a list of agency links for the document. If property config.document.travelRelocation.agencySites.enable is false,
473 * then an empty list will be returned; otherwise uses values from the url.document.travelRelocation.agencySites, customized by
474 * the customizeAgencyLink method
475 * @param travelDocument the travel document we're currently building a link for
476 * @return a List of links to external agencies
477 */
478 public List<LinkField> getAgencyLinks(TravelDocument travelDocument);
479
480 /**
481 * A hook which allows implementers to customize an agency link. Currently, it will just see if the config.document.travelRelocation.agencySites.include.tripId
482 * is set to true; if so, it will append ?tripId= the trip id
483 * @param travelDocument the travel document we are creating agency links for
484 * @param agencyName the name of the agency
485 * @param link the current link text
486 * @return the customized link text
487 */
488 public String customizeAgencyLink(TravelDocument travelDocument, String agencyName, String link);
489
490 /**
491 * Checks whether the TEMReimbursementDocument require traveler's approval routing based on its travel arranger's profile.
492 * @param trDoc the TEMReimbursementDocument to be checked
493 * @return true if the trDoc requires traveler's approval; false otherwise
494 */
495 public boolean requiresTravelerApproval(TEMReimbursementDocument trDoc);
496
497 /**
498 * Checks whether the TravelAuthorizationDocument require traveler's approval routing based on its travel arranger's profile.
499 * @param taDoc the TravelAuthorizationDocument to be checked
500 * @return true if the taDoc requires traveler's approval; false otherwise
501 */
502 public boolean requiresTravelerApproval(TravelAuthorizationDocument taDoc);
503
504 /**
505 * Checks whether the TravelDocument's initiator is the traveler him/herself (if not, then the initiator is one of the arranger).
506 * @param travelDoc the TravelDocument to be checked
507 * @return true if the TravelDocument's initiator is the traveler.
508 */
509 public boolean isInitiatorTraveler(TravelDocument travelDoc);
510
511 }