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 }