/**
  * Sets teh corporate card payment paid date on the document to the process date
  *
  * @see
  *     org.kuali.kfs.sys.batch.service.PaymentSourceToExtractService#markAsPaid(org.kuali.kfs.sys.document.PaymentSource,
  *     java.sql.Date)
  */
 @Override
 public void markAsPaid(TEMReimbursementDocument paymentSource, Date processDate) {
   try {
     paymentSource.setCorporateCardPaymentPaidDate(processDate);
     getDocumentService()
         .saveDocument(
             paymentSource, AccountingDocumentSaveWithNoLedgerEntryGenerationEvent.class);
   } catch (WorkflowException we) {
     LOG.error(
         "encountered workflow exception while attempting to save Disbursement Voucher: "
             + paymentSource.getDocumentNumber()
             + " "
             + we);
     throw new RuntimeException(we);
   }
 }
 /**
  * Sets the corporate card payment extracted date on the document
  *
  * @see
  *     org.kuali.kfs.sys.batch.service.PaymentSourceToExtractService#markAsExtracted(org.kuali.kfs.sys.document.PaymentSource,
  *     java.sql.Date)
  */
 @Override
 public void markAsExtracted(
     TEMReimbursementDocument document, Date sqlProcessRunDate, KualiInteger paymentGroupId) {
   try {
     document.setCorporateCardPaymentExtractDate(sqlProcessRunDate);
     associatePaymentGroupWithCreditCardData(document, paymentGroupId);
     getDocumentService()
         .saveDocument(document, AccountingDocumentSaveWithNoLedgerEntryGenerationEvent.class);
   } catch (WorkflowException we) {
     LOG.error(
         "Could not save TEMReimbursementDocument document #"
             + document.getDocumentNumber()
             + ": "
             + we);
     throw new RuntimeException(we);
   }
 }
 /**
  * Sets the corporate card payment cancel date to the given cancel date and handles the entry
  * cancellation for the payment
  *
  * @see
  *     org.kuali.kfs.sys.batch.service.PaymentSourceToExtractService#cancelPayment(org.kuali.kfs.sys.document.PaymentSource,
  *     java.sql.Date)
  */
 @Override
 public void cancelPayment(TEMReimbursementDocument paymentSource, Date cancelDate) {
   if (paymentSource.getCorporateCardPaymentCancelDate() == null) {
     try {
       paymentSource.setCorporateCardPaymentCancelDate(cancelDate);
       getPaymentSourceHelperService().handleEntryCancellation(paymentSource, this);
       // save the document
       getDocumentService()
           .saveDocument(
               paymentSource, AccountingDocumentSaveWithNoLedgerEntryGenerationEvent.class);
     } catch (WorkflowException we) {
       LOG.error(
           "encountered workflow exception while attempting to save Disbursement Voucher: "
               + paymentSource.getDocumentNumber()
               + " "
               + we);
       throw new RuntimeException(we);
     }
   }
 }
 /**
  * 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;
 }
  /**
   * @see
   *     org.kuali.kfs.sys.batch.service.PaymentSourceToExtractService#retrievePaymentSourcesByCampus(boolean)
   */
  @Override
  public Map<String, List<TEMReimbursementDocument>> retrievePaymentSourcesByCampus(
      boolean immediatesOnly) {
    if (LOG.isDebugEnabled()) {
      LOG.debug("retrievePaymentSourcesByCampus() started");
    }

    final boolean disburseCorporateCardPayments =
        getParameterService()
            .getParameterValueAsBoolean(
                TemParameterConstants.TEM_DOCUMENT.class,
                TemConstants.TravelParameters.CORPORATE_CARD_PAYMENT_IND);
    if (!disburseCorporateCardPayments) {
      return new HashMap<
          String, List<TEMReimbursementDocument>>(); // can't disburse payments? then don't find any
      // documents to disburse
    }

    Map<String, List<TEMReimbursementDocument>> documentsByCampus =
        new HashMap<String, List<TEMReimbursementDocument>>();
    final List<TEMReimbursementDocument> reimbursables =
        retrieveAllCorporateCardDocuments(immediatesOnly);
    Map<String, String> initiatorCampuses = new HashMap<String, String>();
    for (TEMReimbursementDocument document : reimbursables) {
      if (document.isCorporateCardPayable() && shouldExtractPayment(document)) {
        final String campusCode =
            getTravelPaymentsHelperService().findCampusForDocument(document, initiatorCampuses);
        if (!StringUtils.isBlank(campusCode)) {
          List<TEMReimbursementDocument> documentsForCampus = documentsByCampus.get(campusCode);
          if (documentsForCampus == null) {
            documentsForCampus = new ArrayList<TEMReimbursementDocument>();
            documentsByCampus.put(campusCode, documentsForCampus);
          }
          documentsForCampus.add(document);
        }
      }
    }
    return documentsByCampus;
  }
 /**
  * Associates the given payment group id with every historical travel expense that represents a
  * corporate card charge on the given document
  *
  * @param document the document to update
  * @param paymentGroupNumber the payment group id to update the historical expenses with
  */
 protected void associatePaymentGroupWithCreditCardData(
     TEMReimbursementDocument document, KualiInteger paymentGroupNumber) {
   for (HistoricalTravelExpense expense : document.getHistoricalTravelExpenses()) {
     if (expense.getCreditCardStagingData() != null) {
       if (StringUtils.equals(
           expense.getCreditCardStagingData().getCreditCardAgency().getTravelCardTypeCode(),
           TemConstants.TRAVEL_TYPE_CORP)) {
         expense.getCreditCardStagingData().setPaymentGroupId(paymentGroupNumber);
         getBusinessObjectService().save(expense.getCreditCardStagingData());
       }
     }
   }
 }
 /**
  * Looks through the imported expenses on the document to find a corporate card record which has a
  * credit card agency - returns that
  *
  * @param document a document to find a corporate card vendor for
  * @return the id of the found vendor or null if nothing was found
  */
 protected CreditCardAgency getCorporateCreditCardAgency(TEMReimbursementDocument document) {
   for (ImportedExpense importedExpense : document.getImportedExpenses()) {
     if (StringUtils.equals(importedExpense.getCardType(), TemConstants.TRAVEL_TYPE_CORP)
         && !ObjectUtils.isNull(importedExpense.getHistoricalTravelExpense())) {
       importedExpense
           .getHistoricalTravelExpense()
           .refreshReferenceObject(TemPropertyConstants.CREDIT_CARD_AGENCY);
       if (!ObjectUtils.isNull(importedExpense.getHistoricalTravelExpense().getCreditCardAgency())
           && !StringUtils.isBlank(
               importedExpense
                   .getHistoricalTravelExpense()
                   .getCreditCardAgency()
                   .getVendorNumber())) {
         return importedExpense.getHistoricalTravelExpense().getCreditCardAgency();
       }
     }
   }
   return null;
 }
  /**
   * 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.batch.service.PaymentSourceToExtractService#createPaymentGroup(org.kuali.kfs.sys.document.PaymentSource,
   *     java.sql.Date)
   */
  @Override
  public PaymentGroup createPaymentGroup(TEMReimbursementDocument document, Date processRunDate) {
    if (LOG.isDebugEnabled()) {
      LOG.debug("createPaymentGroupForReimbursable() started");
    }

    final boolean disburseCorporateCardPayments =
        getParameterService()
            .getParameterValueAsBoolean(
                TemParameterConstants.TEM_DOCUMENT.class,
                TemConstants.TravelParameters.CORPORATE_CARD_PAYMENT_IND);
    if (!disburseCorporateCardPayments) {
      return null; // can't disburse payments? then don't create payment groups
    }

    PaymentGroup pg = new PaymentGroup();
    final CreditCardAgency creditCardAgency = getCorporateCreditCardAgency(document);
    if (creditCardAgency == null) {
      LOG.error(
          "Skipping corporate card payment for "
              + document.getDocumentNumber()
              + " because no credit card agency could be found.");
      return null;
    }
    final VendorDetail vendor = getCorporateCardVendor(creditCardAgency);
    if (vendor == null) {
      LOG.error(
          "Skipping corporate card payment for "
              + document.getDocumentNumber()
              + " because no vendor could be found.");
      return null;
    }
    final VendorAddress vendorAddress =
        getVendorService()
            .getVendorDefaultAddress(
                vendor.getVendorAddresses(),
                vendor
                    .getVendorHeader()
                    .getVendorType()
                    .getAddressType()
                    .getVendorAddressTypeCode(),
                "");

    pg.setCombineGroups(Boolean.TRUE);
    pg.setCampusAddress(Boolean.FALSE);

    pg.setCity(vendorAddress.getVendorCityName());
    pg.setCountry(vendorAddress.getVendorCountryCode());
    pg.setLine1Address(vendorAddress.getVendorLine1Address());
    pg.setLine2Address(vendorAddress.getVendorLine2Address());
    pg.setPayeeName(vendor.getVendorName());
    pg.setState(vendorAddress.getVendorStateCode());
    pg.setZipCd(vendorAddress.getVendorZipCode());
    pg.setPaymentDate(getNextDate(processRunDate));
    pg.setProcessImmediate(false);
    pg.setPymtAttachment(false);
    pg.setPymtSpecialHandling(false);
    pg.setNraPayment(false);
    pg.setBankCode(creditCardAgency.getBankCode());
    pg.setPaymentStatusCode(PdpConstants.PaymentStatusCodes.OPEN);
    if (StringUtils.equals(
        document.getTraveler().getTravelerTypeCode(), TemConstants.EMP_TRAVELER_TYP_CD)) {
      pg.setEmployeeIndicator(true);
    }
    pg.setPayeeId(vendor.getVendorNumber());
    pg.setPayeeIdTypeCd(PdpConstants.PayeeIdTypeCodes.VENDOR_ID);
    pg.setTaxablePayment(Boolean.FALSE);
    pg.setPayeeOwnerCd(vendor.getVendorHeader().getVendorOwnershipCode());

    // now add the payment detail
    final PaymentDetail paymentDetail = buildPaymentDetail(document, processRunDate);
    pg.addPaymentDetails(paymentDetail);
    paymentDetail.setPaymentGroup(pg);

    return pg;
  }