/** * The sum of all CORP accounting lines on the document * * @see * org.kuali.kfs.sys.batch.service.PaymentSourceToExtractService#getPaymentAmount(org.kuali.kfs.sys.document.PaymentSource) */ @Override public KualiDecimal getPaymentAmount(TEMReimbursementDocument document) { KualiDecimal amount = KualiDecimal.ZERO; for (TemSourceAccountingLine line : (List<TemSourceAccountingLine>) document.getSourceAccountingLines()) { if (StringUtils.equals(line.getCardType(), TemConstants.TRAVEL_TYPE_CORP)) { amount = amount.add(line.getAmount()); } } return amount; }
/** * Determines if a) the document is at the PaymentMethod route node; and b) the accountingLine is * for a travel advance * * @param document a travel document * @param accountingLine the accounting line to validate * @return true if the advance payment/payment method is correct and accessibility should not be * checked; false otherwise */ protected boolean isAdvancePaymentMethodException( Document document, TemSourceAccountingLine accountingLine) { return StringUtils.equals( TemConstants.TRAVEL_ADVANCE_ACCOUNTING_LINE_TYPE_CODE, accountingLine.getFinancialDocumentLineTypeCode()) && document .getDocumentHeader() .getWorkflowDocument() .getCurrentNodeNames() .contains(KFSConstants.RouteLevelNames.PAYMENT_METHOD); }
/** * Only build account details for corporate card accounting lines * * @see * org.kuali.kfs.module.tem.document.service.TravelPaymentsHelperService#buildGenericPaymentAccountDetails(java.util.List) */ protected List<PaymentAccountDetail> buildPaymentAccountDetails( List<? extends AccountingLine> accountingLines) { List<PaymentAccountDetail> details = new ArrayList<PaymentAccountDetail>(); for (AccountingLine al : accountingLines) { final TemSourceAccountingLine accountingLine = (TemSourceAccountingLine) al; if (StringUtils.equals(accountingLine.getCardType(), TemConstants.TRAVEL_TYPE_CORP)) { PaymentAccountDetail pad = new PaymentAccountDetail(); pad.setFinChartCode(accountingLine.getChartOfAccountsCode()); pad.setAccountNbr(accountingLine.getAccountNumber()); if (!StringUtils.isBlank(accountingLine.getSubAccountNumber())) { pad.setSubAccountNbr(accountingLine.getSubAccountNumber()); } else { pad.setSubAccountNbr(KFSConstants.getDashSubAccountNumber()); } pad.setFinObjectCode(accountingLine.getFinancialObjectCode()); if (!StringUtils.isBlank(accountingLine.getFinancialSubObjectCode())) { pad.setFinSubObjectCode(accountingLine.getFinancialSubObjectCode()); } else { pad.setFinSubObjectCode(KFSConstants.getDashFinancialSubObjectCode()); } if (!StringUtils.isBlank(accountingLine.getOrganizationReferenceId())) { pad.setOrgReferenceId(accountingLine.getOrganizationReferenceId()); } if (!StringUtils.isBlank(accountingLine.getProjectCode())) { pad.setProjectCode(accountingLine.getProjectCode()); } else { pad.setProjectCode(KFSConstants.getDashProjectCode()); } pad.setAccountNetAmount(accountingLine.getAmount()); details.add(pad); } } return details; }
/** * Builds the PaymentDetail for the given reimbursable travel & entertainment document * * @param document the reimbursable travel & entertainment document to create a payment for * @param processRunDate the date when the extraction is occurring * @return a PaymentDetail to add to the PaymentGroup */ protected PaymentDetail buildPaymentDetail( TEMReimbursementDocument document, Date processRunDate) { if (LOG.isDebugEnabled()) { LOG.debug("buildPaymentDetail() started"); } PaymentDetail pd = new PaymentDetail(); if (StringUtils.isNotEmpty(document.getDocumentHeader().getOrganizationDocumentNumber())) { pd.setOrganizationDocNbr(document.getDocumentHeader().getOrganizationDocumentNumber()); } pd.setCustPaymentDocNbr(document.getDocumentNumber()); pd.setInvoiceDate(new java.sql.Date(processRunDate.getTime())); pd.setOrigInvoiceAmount(getPaymentAmount(document)); pd.setInvTotDiscountAmount(KualiDecimal.ZERO); pd.setInvTotOtherCreditAmount(KualiDecimal.ZERO); pd.setInvTotOtherDebitAmount(KualiDecimal.ZERO); pd.setInvTotShipAmount(KualiDecimal.ZERO); pd.setNetPaymentAmount(getPaymentAmount(document)); pd.setPrimaryCancelledPayment(Boolean.FALSE); pd.setFinancialDocumentTypeCode(getAchCheckDocumentType(document)); pd.setFinancialSystemOriginCode(KFSConstants.ORIGIN_CODE_KUALI); pd.setPurchaseOrderNbr(document.getTravelDocumentIdentifier()); pd.setOrganizationDocNbr(document.getTravelDocumentIdentifier()); int line = 0; PaymentNoteText pnt = new PaymentNoteText(); pnt.setCustomerNoteLineNbr(new KualiInteger(line++)); final String travelerId = (!ObjectUtils.isNull(document.getTemProfile()) ? (!ObjectUtils.isNull(document.getTemProfile().getPrincipal()) ? document.getTemProfile().getPrincipal().getPrincipalName() : document.getTemProfile().getCustomerNumber()) : document.getDocumentNumber()); // they got this far without a payee id? that really // probably shouldn't happen pnt.setCustomerNoteText( "Info: " + travelerId + " " + document.getTemProfile().getPhoneNumber()); pd.addNote(pnt); final String text = document.getDocumentHeader().getDocumentDescription(); if (!StringUtils.isBlank(text)) { pnt = getPaymentSourceHelperService().buildNoteForCheckStubText(text, line); if (LOG.isDebugEnabled()) { LOG.debug("Creating check stub text note: " + pnt.getCustomerNoteText()); } pd.addNote(pnt); } // Handle accounts, but only corporate card accounting lines List<TemSourceAccountingLine> corporateCardLines = new ArrayList<TemSourceAccountingLine>(); for (TemSourceAccountingLine accountingLine : (List<TemSourceAccountingLine>) document.getSourceAccountingLines()) { if (StringUtils.equals(TemConstants.TRAVEL_TYPE_CORP, accountingLine.getCardType())) { corporateCardLines.add(accountingLine); } } final List<PaymentAccountDetail> paymentAccounts = buildPaymentAccountDetails(corporateCardLines); for (PaymentAccountDetail pad : paymentAccounts) { pd.addAccountDetail(pad); } return pd; }
/** * @see * org.kuali.kfs.sys.document.validation.Validation#validate(org.kuali.kfs.sys.document.validation.event.AttributedDocumentEvent) */ @SuppressWarnings("rawtypes") @Override public boolean validate(AttributedDocumentEvent event) { final Person currentUser = GlobalVariables.getUserSession().getPerson(); TemSourceAccountingLine line = null; if (event instanceof UpdateAccountingLineEvent) { line = (TemSourceAccountingLine) ((UpdateAccountingLineEvent) event).getUpdatedAccountingLine(); } else { line = (TemSourceAccountingLine) ((AccountingLineEvent) event).getAccountingLine(); } List<String> holdErrors = new ArrayList<String>(); holdErrors.addAll(GlobalVariables.getMessageMap().getErrorPath()); GlobalVariables.getMessageMap().clearErrorPath(); TravelDocument travelDocument = (TravelDocument) event.getDocument(); final boolean canUpdate = isAtTravelNode(event.getDocument().getDocumentHeader().getWorkflowDocument()) || isAdvancePaymentMethodException( event.getDocument(), line); // Are we at the travel node? If so, there's a chance that accounting lines // changed; if they did, that // was a permission granted to the travel manager so we should allow it. Also, if we're at // PaymentMethod and the line is an advance accounting line, that's allowed to boolean valid = true; String errorPath = TemPropertyConstants.NEW_SOURCE_ACCTG_LINE; for (TemSourceAccountingLine sourceLine : (List<TemSourceAccountingLine>) travelDocument.getSourceAccountingLines()) { if (line.equals(sourceLine)) { errorPath = "document." + TemPropertyConstants.SOURCE_ACCOUNTING_LINE + "[" + travelDocument.getSourceAccountingLines().indexOf(line) + "]"; break; } } // Test added accounting lines for null values and if there is an access change. valid = getTravelDocumentService().validateSourceAccountingLines(travelDocument, false); if ((!travelDocument .getAppDocStatus() .equalsIgnoreCase(TemConstants.TRAVEL_DOC_APP_DOC_STATUS_INIT)) && (!travelDocument .getAppDocStatus() .equalsIgnoreCase(TemConstants.TravelAuthorizationStatusCodeKeys.IN_PROCESS)) && (!travelDocument .getAppDocStatus() .equalsIgnoreCase(TemConstants.TravelAuthorizationStatusCodeKeys.CHANGE_IN_PROCESS))) { if (!line.getAccount() .getAccountFiscalOfficerUser() .getPrincipalId() .equals(currentUser.getPrincipalId()) && !canUpdate) { GlobalVariables.getMessageMap() .putError( KFSPropertyConstants.ACCOUNT_NUMBER, TemKeyConstants.ERROR_TA_FISCAL_OFFICER_ACCOUNT, line.getAccountNumber()); return false; } } GlobalVariables.getMessageMap().addToErrorPath(errorPath); // skip accounting line validation for TA if (!(event.getDocument() instanceof TravelAuthorizationDocument)) { if (ObjectUtils.isNotNull(line.getObjectTypeCode())) { // check to make sure they're the same List<AccountingDistribution> list = getAccountingDistributionService().buildDistributionFrom(travelDocument); List<AccountingLineDistributionKey> distributionList = new ArrayList<AccountingLineDistributionKey>(); List<String> expectedObjectCodes = new ArrayList<String>(); for (AccountingDistribution dist : list) { distributionList.add( new AccountingLineDistributionKey(dist.getObjectCode(), dist.getCardType())); expectedObjectCodes.add(dist.getObjectCode()); } final String expectedObjectCodesString = StringUtils.join(expectedObjectCodes, ", "); if (!distributionList.contains( new AccountingLineDistributionKey(line.getFinancialObjectCode(), line.getCardType()))) { GlobalVariables.getMessageMap() .putError( TravelAuthorizationFields.FIN_OBJ_CD, TemKeyConstants.ERROR_TEM_ACCOUNTING_LINES_OBJECT_CODE_CARD_TYPE, line.getFinancialObjectCode(), line.getCardType(), expectedObjectCodesString); valid &= false; } } } if (line.getAmount().isLessEqual(KualiDecimal.ZERO) && !travelDocument.getBlanketTravel()) { GlobalVariables.getMessageMap() .putError( KFSPropertyConstants.AMOUNT, KFSKeyConstants.ERROR_CUSTOM, "Amount must be greater than zero."); valid &= false; } if (valid) { // Fly America validation TravelDocument document = (TravelDocument) event.getDocument(); List<TemExpense> allExpenses = new ArrayList<TemExpense>(); allExpenses.addAll(document.getImportedExpenses()); allExpenses.addAll(document.getActualExpenses()); if (allExpenses.size() > 0) { boolean hasAttachment = false; boolean showFlyAmerica = false; for (Note note : document.getNotes()) { if (note.getAttachment() != null) { hasAttachment = true; break; } } boolean isCGEnabled = getParameterService() .getParameterValueAsBoolean( KFSConstants.CoreModuleNamespaces.CHART, KFSConstants.RouteLevelNames.ACCOUNT, KFSConstants.ChartApcParms.ACCOUNT_FUND_GROUP_DENOTES_CG); if (isCGEnabled) { for (TemExpense expense : allExpenses) { if (expense.getExpenseTypeCode().equals(TemConstants.ExpenseTypes.AIRFARE)) { Map<String, Object> fieldValues = new HashMap<String, Object>(); fieldValues.put(KRADPropertyConstants.CODE, TemConstants.ExpenseTypes.AIRFARE); fieldValues.put(KRADPropertyConstants.NAME, expense.getTravelCompanyCodeName()); TravelCompanyCode travelCompany = getBusinessObjectService().findByPrimaryKey(TravelCompanyCode.class, fieldValues); if (travelCompany != null && travelCompany.isForeignCompany()) { String financialObjectCode = expense.getExpenseTypeObjectCode() != null ? expense.getExpenseTypeObjectCode().getFinancialObjectCode() : null; if (travelDocument instanceof TravelAuthorizationDocument && expense instanceof ActualExpense) { if (document.getTripType() != null) { financialObjectCode = document.getTripType().getEncumbranceObjCode(); } } if (financialObjectCode != null && financialObjectCode.equals(line.getFinancialObjectCode())) { String cg = getParameterService() .getParameterValueAsString( KFSConstants.CoreModuleNamespaces.CHART, KFSConstants.RouteLevelNames.ACCOUNT, KFSConstants.ChartApcParms.ACCOUNT_CG_DENOTING_VALUE); if (line.getAccount() == null) { line.refreshReferenceObject(KFSPropertyConstants.ACCOUNT); } if (line.getAccount().getSubFundGroup() == null) { line.refreshReferenceObject(KFSPropertyConstants.SUB_FUND_GROUP); } if (line.getAccount().getSubFundGroup().getFundGroupCode().equals(cg)) { showFlyAmerica = true; } } } } } } // Fly America error has been triggered, determine what accounting line to show it on. if (showFlyAmerica && !hasAttachment) { boolean newLine = true; for (TemSourceAccountingLine sourceLine : (List<TemSourceAccountingLine>) travelDocument.getSourceAccountingLines()) { if (line.equals(sourceLine)) { newLine = false; } } // if line is a new accounting line or a current one being saved/submitted in the // document. // figure out where the new accounting line will be added and set the error to that line # if (newLine) { GlobalVariables.getMessageMap().clearErrorPath(); int newIndex = document .getSourceAccountingLine(document.getSourceAccountingLines().size() - 1) .getSequenceNumber() + 1; errorPath = "document." + TemPropertyConstants.SOURCE_ACCOUNTING_LINE + "[" + newIndex + "]"; GlobalVariables.getMessageMap().addToErrorPath(errorPath); } GlobalVariables.getMessageMap() .putError( KFSPropertyConstants.ACCOUNT_NUMBER, TemKeyConstants.ERROR_ACCOUNTING_LINE_CG); } } } GlobalVariables.getMessageMap().clearErrorPath(); GlobalVariables.getMessageMap().getErrorPath().addAll(holdErrors); return valid; }