/**
   * @see
   *     org.kuali.kfs.module.ar.document.service.AccountsReceivableTaxService#getPostalCodeForTaxation(org.kuali.kfs.module.ar.document.CustomerInvoiceDocument)
   */
  @Override
  public String getPostalCodeForTaxation(CustomerInvoiceDocument document) {

    String postalCode = null;
    String customerNumber = document.getAccountsReceivableDocumentHeader().getCustomerNumber();
    Integer shipToAddressIdentifier = document.getCustomerShipToAddressIdentifier();

    // if customer number or ship to address id isn't provided, go to org options
    if (ObjectUtils.isNotNull(shipToAddressIdentifier) && StringUtils.isNotEmpty(customerNumber)) {

      CustomerAddressService customerAddressService =
          SpringContext.getBean(CustomerAddressService.class);
      CustomerAddress customerShipToAddress =
          customerAddressService.getByPrimaryKey(customerNumber, shipToAddressIdentifier);
      if (ObjectUtils.isNotNull(customerShipToAddress)) {
        postalCode = customerShipToAddress.getCustomerZipCode();
      }
    } else {
      Map<String, String> criteria = new HashMap<String, String>();
      criteria.put("chartOfAccountsCode", document.getBillByChartOfAccountCode());
      criteria.put("organizationCode", document.getBilledByOrganizationCode());
      OrganizationOptions organizationOptions =
          (OrganizationOptions)
              businessObjectService.findByPrimaryKey(OrganizationOptions.class, criteria);

      if (ObjectUtils.isNotNull(organizationOptions)) {
        postalCode = organizationOptions.getOrganizationPostalZipCode();
      }
    }
    return postalCode;
  }
  /**
   * @see
   *     org.kuali.kfs.module.ar.document.service.InvoiceRecurrenceService#isInvoiceApproved(String)
   */
  @Override
  public boolean isInvoiceApproved(String invoiceNumber) {
    boolean success = true;

    if (ObjectUtils.isNull(invoiceNumber)) {
      return success;
    }

    CustomerInvoiceDocument customerInvoiceDocument = null;
    try {
      customerInvoiceDocument =
          (CustomerInvoiceDocument)
              SpringContext.getBean(DocumentService.class).getByDocumentHeaderId(invoiceNumber);
    } catch (WorkflowException e) {

    }
    if (ObjectUtils.isNotNull(customerInvoiceDocument)) {
      WorkflowDocument workflowDocument =
          customerInvoiceDocument.getDocumentHeader().getWorkflowDocument();
      if (!(workflowDocument.isApproved())) {
        success = false;
      }
    } else {
      success = false;
    }
    return success;
  }
  public boolean processSyncModularBusinessRules(Document document) {
    if (!(document instanceof BudgetDocument)) {
      return false;
    }

    boolean valid = true;

    BudgetDocument budgetDocument = (BudgetDocument) document;

    GlobalVariables.getMessageMap().addToErrorPath("document");

    List budgetPeriods = budgetDocument.getBudget().getBudgetPeriods();
    if (ObjectUtils.isNotNull(budgetPeriods) || budgetPeriods.size() >= 1) {
      BudgetPeriod period1 = (BudgetPeriod) budgetPeriods.get(0);
      if (ObjectUtils.isNull(period1.getBudgetLineItems())
          || period1.getBudgetLineItems().isEmpty()) {
        valid = false;
      }
    } else {
      valid = false;
    }

    if (!valid) {
      GlobalVariables.getMessageMap()
          .putError("modularBudget", KeyConstants.ERROR_NO_DETAILED_BUDGET);
    }

    GlobalVariables.getMessageMap().removeFromErrorPath("document");

    return valid;
  }
 /**
  * @see
  *     org.kuali.rice.kns.web.struts.action.KualiLookupAction#execute(org.apache.struts.action.ActionMapping,
  *     org.apache.struts.action.ActionForm, javax.servlet.http.HttpServletRequest,
  *     javax.servlet.http.HttpServletResponse)
  */
 @Override
 public ActionForward execute(
     ActionMapping mapping,
     ActionForm form,
     HttpServletRequest request,
     HttpServletResponse response)
     throws Exception {
   String sortIndexParameter = request.getParameter("d-16544-s");
   if (sortIndexParameter != null) {
     // to store how many times user clicks sort links
     Integer clickedSession =
         ObjectUtils.isNull(
                 GlobalVariables.getUserSession()
                     .retrieveObject(ArConstants.NUM_SORT_INDEX_CLICK_SESSION_KEY))
             ? new Integer(1)
             : (Integer)
                 GlobalVariables.getUserSession()
                     .retrieveObject(ArConstants.NUM_SORT_INDEX_CLICK_SESSION_KEY);
     if (ObjectUtils.isNotNull(
             GlobalVariables.getUserSession().retrieveObject(ArConstants.SORT_INDEX_SESSION_KEY))
         && GlobalVariables.getUserSession()
             .retrieveObject(ArConstants.SORT_INDEX_SESSION_KEY)
             .toString()
             .equals(sortIndexParameter)) {
       GlobalVariables.getUserSession()
           .addObject(
               ArConstants.NUM_SORT_INDEX_CLICK_SESSION_KEY, new Integer(clickedSession + 1));
     }
     GlobalVariables.getUserSession()
         .addObject(ArConstants.SORT_INDEX_SESSION_KEY, sortIndexParameter);
   }
   return super.execute(mapping, form, request, response);
 }
  /**
   * @param searchCriteria
   * @param fieldsForLookup
   */
  protected void buildReportForSearchCriteia(
      List<ContractsGrantsReportSearchCriteriaDataHolder> searchCriteria, Map fieldsForLookup) {
    DataDictionaryService dataDictionaryService =
        SpringContext.getBean(DataDictionaryService.class);
    for (Object field : fieldsForLookup.keySet()) {

      String fieldString = (ObjectUtils.isNull(field)) ? "" : field.toString();
      String valueString =
          (ObjectUtils.isNull(fieldsForLookup.get(field)))
              ? ""
              : fieldsForLookup.get(field).toString();

      if (!fieldString.equals("")
          && !valueString.equals("")
          && !CGConstants.ReportsConstants.reportSearchCriteriaExceptionList.contains(
              fieldString)) {
        ContractsGrantsReportSearchCriteriaDataHolder criteriaData =
            new ContractsGrantsReportSearchCriteriaDataHolder();
        String label = dataDictionaryService.getAttributeLabel(Award.class, fieldString);
        criteriaData.setSearchFieldLabel(label);
        criteriaData.setSearchFieldValue(valueString);
        searchCriteria.add(criteriaData);
      }
    }
  }
Exemple #6
0
  /**
   * Gets the payee's email address from KIM data if the payee type is Employee or Entity;
   * otherwise, returns the stored field value.
   *
   * @return Returns the payeeEmailAddress
   */
  public String getPayeeEmailAddress() {
    // for Employee, retrieve from Person table by employee ID
    if (StringUtils.equalsIgnoreCase(payeeIdentifierTypeCode, PayeeIdTypeCodes.EMPLOYEE)) {
      Person person =
          SpringContext.getBean(PersonService.class).getPersonByEmployeeId(payeeIdNumber);
      if (ObjectUtils.isNotNull(person)) {
        return person.getEmailAddress();
      }
    }
    // for Entity, retrieve from Entity table by entity ID then from Person table
    else if (StringUtils.equalsIgnoreCase(payeeIdentifierTypeCode, PayeeIdTypeCodes.ENTITY)) {
      if (ObjectUtils.isNotNull(payeeIdNumber)) {
        EntityDefault entity =
            KimApiServiceLocator.getIdentityService().getEntityDefault(payeeIdNumber);
        if (ObjectUtils.isNotNull(entity)) {
          List<Principal> principals = entity.getPrincipals();
          if (principals.size() > 0 && ObjectUtils.isNotNull(principals.get(0))) {
            String principalId = principals.get(0).getPrincipalId();
            Person person = SpringContext.getBean(PersonService.class).getPerson(principalId);
            if (ObjectUtils.isNotNull(person)) {
              return person.getEmailAddress();
            }
          }
        }
      }
    }

    // otherwise returns the field value
    return payeeEmailAddress;
  }
  /**
   * Set Multiple system capital asset transaction type code and asset numbers.
   *
   * @param poId
   * @param purApDocs
   */
  protected void setMultipleSystemFromPurAp(
      Integer poId,
      List<PurchasingAccountsPayableDocument> purApDocs,
      String capitalAssetSystemStateCode) {
    List<CapitalAssetSystem> capitalAssetSystems =
        this.getPurchaseOrderService().retrieveCapitalAssetSystemsForMultipleSystem(poId);
    if (ObjectUtils.isNotNull(capitalAssetSystems) && !capitalAssetSystems.isEmpty()) {
      // PurAp doesn't support multiple system asset information for KFS3.0. It works as one system
      // for 3.0.
      CapitalAssetSystem capitalAssetSystem = capitalAssetSystems.get(0);
      if (ObjectUtils.isNotNull(capitalAssetSystem)) {
        String capitalAssetTransactionType = getCapitalAssetTransTypeForOneSystem(poId);
        // if modify existing asset, acquire the assets from Purap
        List<ItemCapitalAsset> purApCapitalAssets = null;
        if (PurapConstants.CapitalAssetSystemStates.MODIFY.equalsIgnoreCase(
            capitalAssetSystemStateCode)) {
          purApCapitalAssets =
              getAssetsFromItemCapitalAsset(capitalAssetSystem.getItemCapitalAssets());
        }

        // set TransactionTypeCode, itemCapitalAssets and system identifier for each item
        for (PurchasingAccountsPayableDocument purApDoc : purApDocs) {
          setItemAssetsCamsTransaction(
              capitalAssetSystem.getCapitalAssetSystemIdentifier(),
              capitalAssetTransactionType,
              purApCapitalAssets,
              purApDoc.getPurchasingAccountsPayableItemAssets());
        }
      }
    }
  }
 /**
  * This method calculates the total credits for the customers.
  *
  * @param cgMapByCustomer
  * @param knownCustomers
  */
 private void calculateTotalCreditsForCustomers(
     Map<String, List<ContractsGrantsInvoiceDocument>> cgMapByCustomer,
     Map<String, ContractsAndGrantsAgingReport> knownCustomers) {
   Set<String> customerIds = cgMapByCustomer.keySet();
   KualiDecimal credits = KualiDecimal.ZERO;
   for (String customer : customerIds) {
     ContractsAndGrantsAgingReport agingReportDetail =
         pickContractsGrantsAgingReportDetail(knownCustomers, customer);
     List<ContractsGrantsInvoiceDocument> cgDocs = cgMapByCustomer.get(customer);
     if (ObjectUtils.isNotNull(cgDocs) && !cgDocs.isEmpty()) {
       credits = KualiDecimal.ZERO;
       for (ContractsGrantsInvoiceDocument cgDoc : cgDocs) {
         Collection<CustomerCreditMemoDocument> creditDocs =
             customerCreditMemoDocumentService.getCustomerCreditMemoDocumentByInvoiceDocument(
                 cgDoc.getDocumentNumber());
         if (ObjectUtils.isNotNull(creditDocs) && !creditDocs.isEmpty()) {
           for (CustomerCreditMemoDocument cm : creditDocs) {
             for (CustomerCreditMemoDetail cmDetail : cm.getCreditMemoDetails()) {
               credits = credits.add(cmDetail.getCreditMemoItemTotalAmount());
             }
           }
         }
       }
     }
     agingReportDetail.setTotalCredits(credits);
     totalCredits = totalCredits.add(credits);
   }
 }
  /**
   * @see org.kuali.kfs.sys.document.FinancialSystemMaintainable#populateChartOfAccountsCodeFields()
   *     <p>Special treatment is needed to populate the chart code from the account number field in
   *     IndirectCostRecoveryRateDetails, as the potential reference account doesn't exist in the
   *     collection due to wild cards, which also needs special handling.
   */
  @Override
  protected void populateChartOfAccountsCodeFields() {
    // calling super method in case there're reference accounts/collections other than ICR rates
    super.populateChartOfAccountsCodeFields();

    PersistableBusinessObject bo = getBusinessObject();
    AccountService acctService = SpringContext.getBean(AccountService.class);
    PersistableBusinessObject newAccount =
        getNewCollectionLine(KFSPropertyConstants.INDIRECT_COST_RECOVERY_RATE_DETAILS);
    String accountNumber =
        (String) ObjectUtils.getPropertyValue(newAccount, KFSPropertyConstants.ACCOUNT_NUMBER);
    String coaCode = null;

    // if accountNumber is wild card, populate chart code with the same wild card
    if (GeneralLedgerConstants.PosterService.SYMBOL_USE_EXPENDITURE_ENTRY.equals(accountNumber)
        || GeneralLedgerConstants.PosterService.SYMBOL_USE_ICR_FROM_ACCOUNT.equals(accountNumber)) {
      coaCode = accountNumber;
    }
    // otherwise do the normal account lookup
    else {
      Account account = acctService.getUniqueAccountForAccountNumber(accountNumber);
      if (ObjectUtils.isNotNull(account)) {
        coaCode = account.getChartOfAccountsCode();
      }
    }

    // populate chart code field
    try {
      ObjectUtils.setObjectProperty(
          newAccount, KFSPropertyConstants.CHART_OF_ACCOUNTS_CODE, coaCode);
    } catch (Exception e) {
      LOG.error(
          "Error in setting property value for " + KFSPropertyConstants.CHART_OF_ACCOUNTS_CODE);
    }
  }
  /**
   * Update Traveler information (name, id, network id) after looking up the Profile
   *
   * @param refreshCaller
   * @param fieldValues
   * @param document
   */
  protected void updateFieldsFromProfileRefresh(
      String refreshCaller, Map fieldValues, MaintenanceDocument document) {

    if (StringUtils.isNotEmpty(refreshCaller)
        && refreshCaller.equals(TemConstants.TEM_PROFILE_LOOKUPABLE)) {

      AgencyStagingDataMaintainable newMaintainable =
          (AgencyStagingDataMaintainable) document.getNewMaintainableObject();
      AgencyStagingData agencyData = (AgencyStagingData) newMaintainable.getBusinessObject();

      TemProfile profile = agencyData.getProfile();
      if (ObjectUtils.isNotNull(profile)) {
        if (StringUtils.isNotEmpty(profile.getEmployeeId())) {
          agencyData.setTravelerId(profile.getEmployeeId());
        } else if (StringUtils.isNotEmpty(profile.getCustomerNumber())) {
          agencyData.setTravelerId(profile.getCustomerNumber());
        } else {
          agencyData.setTravelerId("");
        }

        agencyData.setTravelerName(profile.getFirstName() + " " + profile.getLastName());

        if (ObjectUtils.isNotNull(profile.getPrincipal())) {
          agencyData.setTravelerNetworkId(profile.getPrincipal().getPrincipalName());
        } else {
          agencyData.setTravelerNetworkId("");
        }
      }
    }
  }
  /**
   * @see
   *     org.kuali.kfs.module.ar.document.service.CustomerInvoiceDocumentService#loadCustomerAddressesForCustomerInvoiceDocument(org.kuali.kfs.module.ar.document.CustomerInvoiceDocument)
   */
  @Override
  public void loadCustomerAddressesForCustomerInvoiceDocument(
      CustomerInvoiceDocument customerInvoiceDocument) {
    // if address identifier is provided, try to refresh customer address data
    if (ObjectUtils.isNotNull(customerInvoiceDocument.getAccountsReceivableDocumentHeader())) {
      CustomerAddress customerShipToAddress =
          customerAddressService.getByPrimaryKey(
              customerInvoiceDocument.getAccountsReceivableDocumentHeader().getCustomerNumber(),
              customerInvoiceDocument.getCustomerShipToAddressIdentifier());
      CustomerAddress customerBillToAddress =
          customerAddressService.getByPrimaryKey(
              customerInvoiceDocument.getAccountsReceivableDocumentHeader().getCustomerNumber(),
              customerInvoiceDocument.getCustomerBillToAddressIdentifier());

      if (ObjectUtils.isNotNull(customerShipToAddress)) {
        customerInvoiceDocument.setCustomerShipToAddress(customerShipToAddress);
        customerInvoiceDocument.setCustomerShipToAddressOnInvoice(customerShipToAddress);
      }

      if (ObjectUtils.isNotNull(customerBillToAddress)) {
        customerInvoiceDocument.setCustomerBillToAddress(customerBillToAddress);
        customerInvoiceDocument.setCustomerBillToAddressOnInvoice(customerBillToAddress);
      }
    }
  }
  /**
   * Validates a single collection activity document detail object.
   *
   * @param event The object to get validated.
   * @return Returns true if all validations succeed otherwise false.
   */
  public boolean validateEvent(Event event) {
    MessageMap errorMap = GlobalVariables.getMessageMap();

    boolean isValid = true;

    int originalErrorCount = errorMap.getErrorCount();
    // call the DD validation which checks basic data integrity
    SpringContext.getBean(DictionaryValidationService.class).validateBusinessObject(event);
    isValid = (errorMap.getErrorCount() == originalErrorCount);

    if (ObjectUtils.isNotNull(event.isFollowup())
        && event.isFollowup()
        && event.getFollowupDate() == null) {
      errorMap.putError(
          ArPropertyConstants.EventFields.FOLLOW_UP_DATE,
          ArKeyConstants.CollectionActivityDocumentErrors.ERROR_FOLLOW_UP_DATE_REQUIRED);
      isValid = false;
    }
    if (ObjectUtils.isNotNull(event.isCompleted())
        && event.isCompleted()
        && event.getCompletedDate() == null) {
      errorMap.putError(
          ArPropertyConstants.EventFields.COMPLETED_DATE,
          ArKeyConstants.CollectionActivityDocumentErrors.ERROR_COMPLETED_DATE_REQUIRED);
      isValid = false;
    }
    return isValid;
  }
  /**
   * @see
   *     org.kuali.kfs.module.ar.document.service.CustomerInvoiceDocumentService#checkIfInvoiceNumberIsFinal(java.lang.String)
   */
  @Override
  public boolean checkIfInvoiceNumberIsFinal(String invDocumentNumber) {
    boolean isSuccess = true;
    if (StringUtils.isBlank(invDocumentNumber)) {
      isSuccess &= false;
    } else {
      CustomerInvoiceDocument customerInvoiceDocument =
          getInvoiceByInvoiceDocumentNumber(invDocumentNumber);

      if (ObjectUtils.isNull(customerInvoiceDocument)) {
        isSuccess &= false;
      } else {
        Document doc = null;
        try {
          doc = documentService.getByDocumentHeaderId(invDocumentNumber);
        } catch (WorkflowException e) {
          isSuccess &= false;
        }
        if (ObjectUtils.isNull(doc)
            || ObjectUtils.isNull(doc.getDocumentHeader())
            || doc.getDocumentHeader().getWorkflowDocument() == null
            || !(doc.getDocumentHeader().getWorkflowDocument().isApproved()
                || doc.getDocumentHeader().getWorkflowDocument().isProcessed())) {
          isSuccess &= false;
        }
      }
    }
    return isSuccess;
  }
  /**
   * @see
   *     org.kuali.kfs.module.ar.document.service.InvoiceRecurrenceService#isValidMaximumNumberOfRecurrences(int,String)
   */
  @Override
  public boolean isValidMaximumNumberOfRecurrences(
      Integer totalRecurrenceNumber, String intervalCode) {

    if (ObjectUtils.isNull(intervalCode) || ObjectUtils.isNull(totalRecurrenceNumber)) {
      return true;
    }
    Integer maximumRecurrencesByInterval;
    if (ObjectUtils.isNotNull(intervalCode)) {
      List<String> maximumRecurrences =
          new ArrayList<String>(
              SpringContext.getBean(ParameterService.class)
                  .getSubParameterValuesAsString(
                      InvoiceRecurrence.class,
                      ArConstants.MAXIMUM_RECURRENCES_BY_INTERVAL,
                      intervalCode));
      if (maximumRecurrences.size() > 0 && StringUtils.isNotBlank(maximumRecurrences.get(0))) {
        maximumRecurrencesByInterval = Integer.valueOf(maximumRecurrences.get(0));
        if (totalRecurrenceNumber > maximumRecurrencesByInterval) {
          return false;
        }
      }
    }
    return true;
  }
  @Override
  public void recalculateCustomerCreditMemoDocument(
      CustomerCreditMemoDocument customerCreditMemoDocument,
      boolean blanketApproveDocumentEventFlag) {
    KualiDecimal customerCreditMemoDetailItemAmount;
    BigDecimal itemQuantity;

    String invDocumentNumber =
        customerCreditMemoDocument.getFinancialDocumentReferenceInvoiceNumber();
    List<CustomerCreditMemoDetail> customerCreditMemoDetails =
        customerCreditMemoDocument.getCreditMemoDetails();

    if (!blanketApproveDocumentEventFlag) {
      customerCreditMemoDocument.resetTotals();
    }

    for (CustomerCreditMemoDetail customerCreditMemoDetail : customerCreditMemoDetails) {
      // no data entered for the current credit memo detail -> no processing needed
      itemQuantity = customerCreditMemoDetail.getCreditMemoItemQuantity();
      customerCreditMemoDetailItemAmount = customerCreditMemoDetail.getCreditMemoItemTotalAmount();
      if (ObjectUtils.isNull(itemQuantity)
          && ObjectUtils.isNull(customerCreditMemoDetailItemAmount)) {
        if (!blanketApproveDocumentEventFlag) {
          customerCreditMemoDetail.setDuplicateCreditMemoItemTotalAmount(null);
        }
        continue;
      }

      // if item amount was entered, it takes precedence, if not, use the item quantity to re-calc
      // amount
      if (ObjectUtils.isNotNull(customerCreditMemoDetailItemAmount)) {
        customerCreditMemoDetail.recalculateBasedOnEnteredItemAmount(customerCreditMemoDocument);
      } // if item quantity was entered
      else {
        customerCreditMemoDetail.recalculateBasedOnEnteredItemQty(customerCreditMemoDocument);
        if (!blanketApproveDocumentEventFlag) {
          customerCreditMemoDetailItemAmount =
              customerCreditMemoDetail.getCreditMemoItemTotalAmount();
        }
      }

      if (!blanketApproveDocumentEventFlag) {
        customerCreditMemoDetail.setDuplicateCreditMemoItemTotalAmount(
            customerCreditMemoDetailItemAmount);
        boolean isCustomerInvoiceDetailTaxable =
            accountsReceivableTaxService.isCustomerInvoiceDetailTaxable(
                customerCreditMemoDocument.getInvoice(),
                customerCreditMemoDetail.getCustomerInvoiceDetail());
        customerCreditMemoDocument.recalculateTotals(
            customerCreditMemoDetailItemAmount, isCustomerInvoiceDetailTaxable);
      }
    }

    //  force the docHeader docTotal
    customerCreditMemoDocument
        .getFinancialSystemDocumentHeader()
        .setFinancialDocumentTotalAmount(customerCreditMemoDocument.getCrmTotalAmount());
  }
  /**
   * This method checks that an invoice paid applied is for a valid amount.
   *
   * @param invoicePaidApplied
   * @return
   */
  public static boolean validateInvoicePaidApplied(
      InvoicePaidApplied invoicePaidApplied,
      String fieldName,
      PaymentApplicationDocument document) {
    boolean isValid = true;

    invoicePaidApplied.refreshReferenceObject("invoiceDetail");
    if (ObjectUtils.isNull(invoicePaidApplied)
        || ObjectUtils.isNull(invoicePaidApplied.getInvoiceDetail())) {
      return true;
    }
    KualiDecimal amountOwed = invoicePaidApplied.getInvoiceDetail().getAmountOpen();
    KualiDecimal amountPaid = invoicePaidApplied.getInvoiceItemAppliedAmount();

    if (ObjectUtils.isNull(amountOwed)) {
      amountOwed = KualiDecimal.ZERO;
    }
    if (ObjectUtils.isNull(amountPaid)) {
      amountPaid = KualiDecimal.ZERO;
    }

    // Can't pay more than you owe.
    if (!amountPaid.isLessEqual(amountOwed)) {
      isValid = false;
      LOG.debug(
          "InvoicePaidApplied is not valid. Amount to be applied exceeds amount outstanding.");
      GlobalVariables.getMessageMap()
          .putError(
              fieldName,
              ArKeyConstants.PaymentApplicationDocumentErrors
                  .AMOUNT_TO_BE_APPLIED_EXCEEDS_AMOUNT_OUTSTANDING);
    }

    // Can't apply more than the amount received via the related CashControlDocument
    if (amountPaid.isGreaterThan(document.getTotalFromControl())) {
      isValid = false;
      LOG.debug(
          "InvoicePaidApplied is not valid. Cannot apply more than cash control total amount.");
      GlobalVariables.getMessageMap()
          .putError(
              fieldName,
              ArKeyConstants.PaymentApplicationDocumentErrors
                  .CANNOT_APPLY_MORE_THAN_CASH_CONTROL_TOTAL_AMOUNT);
    }

    //  cant apply negative amounts
    if (amountPaid.isNegative() && !document.hasCashControlDocument()) {
      isValid = false;
      LOG.debug("InvoicePaidApplied is not valid. Amount to be applied must be positive.");
      GlobalVariables.getMessageMap()
          .putError(
              fieldName,
              ArKeyConstants.PaymentApplicationDocumentErrors
                  .AMOUNT_TO_BE_APPLIED_MUST_BE_POSTIIVE);
    }
    return isValid;
  }
 /**
  * @see
  *     org.kuali.kfs.module.ar.document.service.InvoiceRecurrenceService#isValidEndDateOrTotalRecurrenceNumber(Date,int)
  */
 @Override
 public boolean isValidEndDateOrTotalRecurrenceNumber(
     Date endDate, Integer totalRecurrenceNumber) {
   boolean success = true;
   if (ObjectUtils.isNull(endDate) && ObjectUtils.isNull(totalRecurrenceNumber)) {
     return false;
   }
   return success;
 }
  /**
   * This method validates the unapplied attribute of the document.
   *
   * @param document
   * @return
   * @throws WorkflowException
   */
  public static boolean validateNonAppliedHolding(
      PaymentApplicationDocument applicationDocument, KualiDecimal totalFromControl)
      throws WorkflowException {
    NonAppliedHolding nonAppliedHolding = applicationDocument.getNonAppliedHolding();
    if (ObjectUtils.isNull(nonAppliedHolding)) {
      return true;
    }
    if (StringUtils.isNotEmpty(nonAppliedHolding.getCustomerNumber())) {
      KualiDecimal nonAppliedAmount = nonAppliedHolding.getFinancialDocumentLineAmount();
      if (null == nonAppliedAmount) {
        nonAppliedAmount = KualiDecimal.ZERO;
      }
      boolean isValid = totalFromControl.isGreaterEqual(nonAppliedAmount);
      if (!isValid) {
        String propertyName = ArPropertyConstants.PaymentApplicationDocumentFields.UNAPPLIED_AMOUNT;
        String errorKey =
            ArKeyConstants.PaymentApplicationDocumentErrors
                .UNAPPLIED_AMOUNT_CANNOT_EXCEED_AVAILABLE_AMOUNT;
        GlobalVariables.getMessageMap().putError(propertyName, errorKey);
      }
      // The amount of the unapplied can't exceed the remaining balance to be applied
      KualiDecimal totalBalanceToBeApplied = applicationDocument.getUnallocatedBalance();
      isValid = KualiDecimal.ZERO.isLessEqual(totalBalanceToBeApplied);
      if (!isValid) {
        String propertyName = ArPropertyConstants.PaymentApplicationDocumentFields.UNAPPLIED_AMOUNT;
        String errorKey =
            ArKeyConstants.PaymentApplicationDocumentErrors
                .UNAPPLIED_AMOUNT_CANNOT_EXCEED_BALANCE_TO_BE_APPLIED;
        GlobalVariables.getMessageMap().putError(propertyName, errorKey);
      }

      //  the unapplied amount cannot be negative
      isValid = nonAppliedAmount.isPositive() || nonAppliedAmount.isZero();
      if (!isValid) {
        String propertyName = ArPropertyConstants.PaymentApplicationDocumentFields.UNAPPLIED_AMOUNT;
        String errorKey =
            ArKeyConstants.PaymentApplicationDocumentErrors.AMOUNT_TO_BE_APPLIED_MUST_BE_POSTIIVE;
        GlobalVariables.getMessageMap().putError(propertyName, errorKey);
      }
      return isValid;
    } else {
      if (ObjectUtils.isNull(nonAppliedHolding.getFinancialDocumentLineAmount())
          || KualiDecimal.ZERO.equals(nonAppliedHolding.getFinancialDocumentLineAmount())) {
        // All's OK. Both customer number and amount are empty/null.
        return true;
      } else {
        // Error. Customer number is empty but amount wasn't.
        String propertyName =
            ArPropertyConstants.PaymentApplicationDocumentFields.UNAPPLIED_CUSTOMER_NUMBER;
        String errorKey =
            ArKeyConstants.PaymentApplicationDocumentErrors
                .UNAPPLIED_AMOUNT_CANNOT_BE_EMPTY_OR_ZERO;
        GlobalVariables.getMessageMap().putError(propertyName, errorKey);
        return false;
      }
    }
  }
  /**
   * Gets the fieldInfo attribute.
   *
   * @return Returns the fieldInfo.
   */
  protected List<Map<String, String>> getFieldInfo(List<EffortCertificationDetail> detailLines) {
    LOG.debug("getFieldInfo(List<EffortCertificationDetail>) start");

    List<Map<String, String>> fieldInfo = new ArrayList<Map<String, String>>();
    EffortCertificationDocument document = (EffortCertificationDocument) this.getDocument();
    KualiDecimal totalOriginalPayrollAmount = document.getTotalOriginalPayrollAmount();

    for (EffortCertificationDetail detailLine : detailLines) {
      detailLine.refreshNonUpdateableReferences();

      Map<String, String> fieldInfoForAttribute = new HashMap<String, String>();

      fieldInfoForAttribute.put(
          KFSPropertyConstants.CHART_OF_ACCOUNTS_CODE,
          detailLine.getChartOfAccounts().getFinChartOfAccountDescription());

      String accountInfo = buildAccountInfo(detailLine.getAccount());
      fieldInfoForAttribute.put(KFSPropertyConstants.ACCOUNT_NUMBER, accountInfo);

      SubAccount subAccount = detailLine.getSubAccount();
      if (ObjectUtils.isNotNull(subAccount)) {
        fieldInfoForAttribute.put(
            KFSPropertyConstants.SUB_ACCOUNT_NUMBER, subAccount.getSubAccountName());
      }

      ObjectCode objectCode = detailLine.getFinancialObject();
      if (ObjectUtils.isNotNull(objectCode)) {
        fieldInfoForAttribute.put(
            KFSPropertyConstants.FINANCIAL_OBJECT_CODE, objectCode.getFinancialObjectCodeName());
      }

      Account sourceAccount = detailLine.getSourceAccount();
      if (ObjectUtils.isNotNull(sourceAccount)) {
        fieldInfoForAttribute.put(
            EffortPropertyConstants.SOURCE_ACCOUNT_NUMBER, sourceAccount.getAccountName());
      }

      Chart sourceChart = detailLine.getSourceChartOfAccounts();
      if (ObjectUtils.isNotNull(sourceChart)) {
        fieldInfoForAttribute.put(
            EffortPropertyConstants.SOURCE_CHART_OF_ACCOUNTS_CODE,
            sourceChart.getFinChartOfAccountDescription());
      }

      KualiDecimal originalPayrollAmount = detailLine.getEffortCertificationOriginalPayrollAmount();
      String actualOriginalPercent =
          PayrollAmountHolder.recalculateEffortPercentAsString(
              totalOriginalPayrollAmount, originalPayrollAmount);
      fieldInfoForAttribute.put(
          EffortPropertyConstants.EFFORT_CERTIFICATION_CALCULATED_OVERALL_PERCENT,
          actualOriginalPercent);

      fieldInfo.add(fieldInfoForAttribute);
    }

    return fieldInfo;
  }
 /**
  * This method returns the invoice pre tax amount
  *
  * @return
  */
 public KualiDecimal getInvoiceItemPreTaxAmount() {
   if (ObjectUtils.isNotNull(invoiceItemUnitPrice) && ObjectUtils.isNotNull(invoiceItemQuantity)) {
     BigDecimal bd = invoiceItemUnitPrice.multiply(invoiceItemQuantity);
     bd = bd.setScale(KualiDecimal.SCALE, KualiDecimal.ROUND_BEHAVIOR);
     return new KualiDecimal(bd);
   } else {
     return KualiDecimal.ZERO;
   }
 }
  @Test
  public void testExample1WithLineItems() throws Exception {
    context.checking(
        new Expectations() {
          {
            one(sponsorHierarchyService).isSponsorNihMultiplePi(NIH_SPONSOR_CODE);
            will(returnValue(true));
          }
        });

    subAward.getBudgetSubAwardPeriodDetails().get(0).setDirectCost(new ScaleTwoDecimal(150000L));
    subAward.getBudgetSubAwardPeriodDetails().get(0).setIndirectCost(new ScaleTwoDecimal(75000L));
    subAward.getBudgetSubAwardPeriodDetails().get(1).setDirectCost(new ScaleTwoDecimal(150000L));
    subAward.getBudgetSubAwardPeriodDetails().get(1).setIndirectCost(new ScaleTwoDecimal(75000L));

    for (BudgetPeriod period : budget.getBudgetPeriods()) {
      BudgetLineItem newLineItem = new BudgetLineItem();
      newLineItem.setBudgetSubAward(subAward);
      newLineItem.setSubAwardNumber(subAward.getSubAwardNumber());
      newLineItem.setDirectCost(new ScaleTwoDecimal(100L));
      newLineItem.setCostSharingAmount(new ScaleTwoDecimal(100L));
      newLineItem.setCostElement(directLt);
      newLineItem.setLineItemNumber(1);
      period.getBudgetLineItems().add(newLineItem);
      newLineItem = (BudgetLineItem) org.kuali.rice.krad.util.ObjectUtils.deepCopy(newLineItem);
      newLineItem.setCostElement(directGt);
      newLineItem.setLineItemNumber(2);
      period.getBudgetLineItems().add(newLineItem);
      newLineItem = (BudgetLineItem) org.kuali.rice.krad.util.ObjectUtils.deepCopy(newLineItem);
      newLineItem.setCostElement(indirectLt);
      newLineItem.setLineItemNumber(3);
      period.getBudgetLineItems().add(newLineItem);
      newLineItem = (BudgetLineItem) org.kuali.rice.krad.util.ObjectUtils.deepCopy(newLineItem);
      newLineItem.setCostElement(indirectGt);
      newLineItem.setLineItemNumber(4);
      period.getBudgetLineItems().add(newLineItem);
    }

    List<Map<String, ScaleTwoDecimal>> expectedResults = new ArrayList<>();
    expectedResults.add(new HashMap<>());
    expectedResults.add(new HashMap<>());
    expectedResults.add(new HashMap<>());
    expectedResults.get(0).put(indirectGt, new ScaleTwoDecimal(75000L));
    expectedResults.get(0).put(indirectLt, ScaleTwoDecimal.ZERO);
    expectedResults.get(0).put(directGt, new ScaleTwoDecimal(125000L));
    expectedResults.get(0).put(directLt, new ScaleTwoDecimal(25000L));
    expectedResults.get(1).put(indirectGt, new ScaleTwoDecimal(75000L));
    expectedResults.get(1).put(indirectLt, ScaleTwoDecimal.ZERO);
    expectedResults.get(1).put(directGt, new ScaleTwoDecimal(150000L));
    expectedResults.get(1).put(directLt, ScaleTwoDecimal.ZERO);
    service.generateSubAwardLineItems(subAward, budget);
    assertExpectedResults(expectedResults);
    assertCostShare(0);
  }
  /**
   * Get capitalAssetTransactionTypeCode for one system from PurAp.
   *
   * @param poId
   * @return
   */
  protected String getCapitalAssetTransTypeForOneSystem(Integer poId) {
    PurchaseOrderDocument poDoc = getCurrentDocumentForPurchaseOrderIdentifier(poId);
    if (ObjectUtils.isNotNull(poDoc)) {
      List<PurchasingCapitalAssetItem> capitalAssetItems = poDoc.getPurchasingCapitalAssetItems();

      if (ObjectUtils.isNotNull(capitalAssetItems) && capitalAssetItems.get(0) != null) {
        return capitalAssetItems.get(0).getCapitalAssetTransactionTypeCode();
      }
    }
    return null;
  }
 /**
  * For reimbursable documents, sets the proper payee type code and profile id after a profile
  * lookup
  */
 public void updatePayeeTypeForReimbursable() {
   if (!ObjectUtils.isNull(getTraveler())
       && !ObjectUtils.isNull(getTravelPayment())
       && !StringUtils.isBlank(getTraveler().getTravelerTypeCode())) {
     if (getTravelerService().isEmployee(getTraveler())) {
       getTravelPayment().setPayeeTypeCode(KFSConstants.PaymentPayeeTypes.EMPLOYEE);
     } else {
       getTravelPayment().setPayeeTypeCode(KFSConstants.PaymentPayeeTypes.CUSTOMER);
     }
   }
 }
  /**
   * @see
   *     org.kuali.kfs.module.ar.document.service.InvoiceRecurrenceService#isValidEndDateAndTotalRecurrenceNumber(Date,Date,int,String)
   */
  @Override
  public boolean isValidEndDateAndTotalRecurrenceNumber(
      Date recurrenceBeginDate,
      Date recurrenceEndDate,
      Integer totalRecurrenceNumber,
      String recurrenceIntervalCode) {

    if (ObjectUtils.isNull(recurrenceBeginDate)
        || ObjectUtils.isNull(recurrenceIntervalCode)
        || ObjectUtils.isNull(recurrenceEndDate)
        || ObjectUtils.isNull(totalRecurrenceNumber)) {
      return true;
    }

    Calendar beginCalendar = Calendar.getInstance();
    beginCalendar.setTime(recurrenceBeginDate);
    Date beginDate = recurrenceBeginDate;
    Calendar endCalendar = Calendar.getInstance();
    endCalendar.setTime(recurrenceEndDate);
    Date endDate = recurrenceEndDate;
    Calendar nextCalendar = Calendar.getInstance();
    Date nextDate = beginDate;

    int totalRecurrences = 0;
    int addCounter = 0;
    String intervalCode = recurrenceIntervalCode;
    if (intervalCode.equals("M")) {
      addCounter = 1;
    }
    if (intervalCode.equals("Q")) {
      addCounter = 3;
    }
    /* perform this loop while begin_date is less than or equal to end_date */
    while (!(beginDate.after(endDate))) {
      beginCalendar.setTime(beginDate);
      beginCalendar.add(Calendar.MONTH, addCounter);
      beginDate = KfsDateUtils.convertToSqlDate(beginCalendar.getTime());
      totalRecurrences++;

      nextDate = beginDate;
      nextCalendar.setTime(nextDate);
      nextCalendar.add(Calendar.MONTH, addCounter);
      nextDate = KfsDateUtils.convertToSqlDate(nextCalendar.getTime());
      if (endDate.after(beginDate) && endDate.before(nextDate)) {
        totalRecurrences++;
        break;
      }
    }
    if (totalRecurrences != totalRecurrenceNumber.intValue()) {
      return false;
    }

    return true;
  }
 /** @return a List of the CustomerInvoiceDetails associated with a given Account Number */
 @SuppressWarnings("unchecked")
 public Collection<CustomerInvoiceDetail> getCustomerInvoiceDetailsByAccountNumber(
     String accountChartCode, String accountNumber) {
   Map args = new HashMap();
   if (ObjectUtils.isNotNull(accountNumber) && StringUtils.isNotEmpty(accountNumber)) {
     args.put(KFSPropertyConstants.ACCOUNT_NUMBER, accountNumber);
   }
   if (ObjectUtils.isNotNull(accountChartCode) && StringUtils.isNotEmpty(accountChartCode)) {
     args.put(KFSPropertyConstants.CHART_OF_ACCOUNTS_CODE, accountChartCode);
   }
   return businessObjectService.findMatching(CustomerInvoiceDetail.class, args);
 }
  /**
   * calculates the remainder of fiscal year estimated income for stocks
   *
   * @param security
   * @param holdingTaxLot
   * @return amount
   */
  protected BigDecimal getRemainderOfFiscalYearEstimatedIncomeForStocks(
      Security security, HoldingTaxLot holdingTaxLot) {
    BigDecimal amount = BigDecimal.ZERO;

    if (ObjectUtils.isNull(security.getIncomeRate())
        || security.getIncomeRate().compareTo(BigDecimal.ZERO) == 0) {
      return amount;
    }

    String incomePayFrequency = security.getIncomePayFrequency();
    Date nextIncomeDueDate = security.getIncomeNextPayDate();

    if (ObjectUtils.isNull(nextIncomeDueDate)) {
      return amount;
    }

    Date fiscalYearEndDate = getFiscalYearEndDate();

    // BONDS - rule 4.a
    if (nextIncomeDueDate.after(fiscalYearEndDate)) {
      return BigDecimal.ZERO;
    }

    int numberOfMonthsRemaing = getNumberOfMonthsRemaining(fiscalYearEndDate, nextIncomeDueDate);

    if (nextIncomeDueDate.before(fiscalYearEndDate) && numberOfMonthsRemaing < 4) {
      return BigDecimal.ZERO;
    }

    long quartersLeftToFiscalYear = getQuartersLeftToFiscalYear(fiscalYearEndDate);

    // calculate holding units times security rate....
    amount =
        KEMCalculationRoundingHelper.multiply(
            holdingTaxLot.getUnits(),
            security.getIncomeRate(),
            EndowConstants.Scale.SECURITY_MARKET_VALUE);

    // now multiply the above amount by 4 to get amount for 4 quarters or for the year...
    amount =
        KEMCalculationRoundingHelper.divide(
            amount, BigDecimal.valueOf(4), EndowConstants.Scale.SECURITY_MARKET_VALUE);

    // now compute the amount for the quarters remaining in the fiscal year....
    amount =
        KEMCalculationRoundingHelper.multiply(
            amount,
            BigDecimal.valueOf(quartersLeftToFiscalYear),
            EndowConstants.Scale.SECURITY_MARKET_VALUE);

    return amount;
  }
  /**
   * Retreives a purchase order item for a given CreditMemoItem by inspecting the item type to see
   * if its above the line or below the line and returns the appropriate type.
   *
   * @param item
   * @return
   */
  protected PurchaseOrderItem getPurchaseOrderItemfromCreditMemoItem(CreditMemoItem item) {
    if (ObjectUtils.isNotNull(item.getPurapDocumentIdentifier())) {
      if (ObjectUtils.isNull(item.getPurapDocument())) {
        item.refreshReferenceObject(PurapPropertyConstants.PURAP_DOC);
      }
    }
    // ideally we should do this a different way - maybe move it all into the service or save this
    // info somehow (make sure and
    // update though)
    if (item.getPurapDocument() != null) {
      PurchaseOrderDocument po =
          ((VendorCreditMemoDocument) item.getPurapDocument()).getPurchaseOrderDocument();
      PurchaseOrderItem poi = null;
      if (item.getItemType().isLineItemIndicator()) {
        if (po.getItems() == null || po.getItems().isEmpty()) {
          po.refreshReferenceObject("items");
        }
        poi = (PurchaseOrderItem) po.getItem(item.getItemLineNumber().intValue() - 1);
      } else {
        // To get the purchaseOrderItem by given CreditMemoItem. Since the additional charge type
        // may be different in CM and
        // PO, there could be no PO Item for a given CM item.
        poi =
            (PurchaseOrderItem)
                SpringContext.getBean(PurapService.class)
                    .getBelowTheLineByType(po, item.getItemType());
      }
      if (poi != null) {
        return poi;
      } else {
        if (LOG.isDebugEnabled()) {
          LOG.debug(
              "getPurchaseOrderItemfromCreditMemoItem() Returning null because PurchaseOrderItem object for line number"
                  + item.getItemLineNumber()
                  + "or itemType "
                  + item.getItemTypeCode()
                  + " is null");
        }
        return null;
      }
    } else {

      LOG.error(
          "getPurchaseOrderItemfromCreditMemoItem() Returning null because paymentRequest object is null");
      throw new PurError(
          "Credit Memo Object in Purchase Order item line number "
              + item.getItemLineNumber()
              + "or itemType "
              + item.getItemTypeCode()
              + " is null");
    }
  }
  /**
   * calculates the remainder of fiscal year estimated income for pooled funds
   *
   * @param security
   * @param holdingTaxLot
   * @return amount
   */
  protected BigDecimal getRemainderOfFiscalYearEstimatedIncomeForPooledFunds(
      Security security, HoldingTaxLot holdingTaxLot) {
    BigDecimal amount = BigDecimal.ZERO;

    if (ObjectUtils.isNull(security.getIncomeNextPayDate())
        || ObjectUtils.isNull(security.getFrequencyCode())) {
      return amount;
    }

    Date nextIncomeDueDate = security.getIncomeNextPayDate();
    if (ObjectUtils.isNull(nextIncomeDueDate)) {
      return amount;
    }

    Date fiscalYearEndDate = getFiscalYearEndDate();

    // BONDS - rule 4.a
    if (nextIncomeDueDate.after(fiscalYearEndDate)) {
      return BigDecimal.ZERO;
    }

    // rule 4.b
    if (nextIncomeDueDate.before(fiscalYearEndDate)) {
      String incomePayFrequency = security.getIncomePayFrequency();
      if (ObjectUtils.isNull(incomePayFrequency)) {
        return amount;
      }

      Date lastPaymentDate = getLastPaymentDate(incomePayFrequency, fiscalYearEndDate);

      long paymentsRemaining =
          getTotalPaymentsRemaining(
              lastPaymentDate, fiscalYearEndDate, incomePayFrequency, nextIncomeDueDate);

      long totalNumberOfPayments = kEMService.getTotalNumberOfPaymentsForFiscalYear();

      amount =
          KEMCalculationRoundingHelper.multiply(
              holdingTaxLot.getUnits(),
              security.getIncomeRate(),
              EndowConstants.Scale.SECURITY_MARKET_VALUE);
      amount = amount.multiply(BigDecimal.valueOf(paymentsRemaining));
      amount =
          KEMCalculationRoundingHelper.divide(
              amount,
              BigDecimal.valueOf(totalNumberOfPayments),
              EndowConstants.Scale.SECURITY_MARKET_VALUE);
      amount = amount.add(holdingTaxLot.getCurrentAccrual());
    }

    return amount;
  }
  // mjmc
  // *************************************************************************************************
  private PurchaseOrderDocument copyNotesAndAttachmentsToPO(
      RequisitionDocument reqDoc, PurchaseOrderDocument poDoc) {

    purapService.saveDocumentNoValidation(poDoc);
    List<Note> notes = (List<Note>) reqDoc.getNotes();
    int noteLength = notes.size();
    if (noteLength > 0) {
      for (Note note : notes) {
        try {
          Note copyingNote =
              SpringContext.getBean(DocumentService.class)
                  .createNoteFromDocument(poDoc, note.getNoteText());
          purapService.saveDocumentNoValidation(poDoc);
          copyingNote.setNotePostedTimestamp(note.getNotePostedTimestamp());
          copyingNote.setAuthorUniversalIdentifier(note.getAuthorUniversalIdentifier());
          copyingNote.setNoteTopicText(note.getNoteTopicText());
          Attachment originalAttachment =
              SpringContext.getBean(AttachmentService.class)
                  .getAttachmentByNoteId(note.getNoteIdentifier());
          NoteExtendedAttribute noteExtendedAttribute = (NoteExtendedAttribute) note.getExtension();
          if (originalAttachment != null
              || (ObjectUtils.isNotNull(noteExtendedAttribute)
                  && noteExtendedAttribute.isCopyNoteIndicator())) {
            if (originalAttachment != null) {
              Attachment newAttachment =
                  SpringContext.getBean(AttachmentService.class)
                      .createAttachment(
                          (PersistableBusinessObject) copyingNote,
                          originalAttachment.getAttachmentFileName(),
                          originalAttachment.getAttachmentMimeTypeCode(),
                          originalAttachment.getAttachmentFileSize().intValue(),
                          originalAttachment.getAttachmentContents(),
                          originalAttachment.getAttachmentTypeCode()); // new Attachment();

              if (ObjectUtils.isNotNull(originalAttachment)
                  && ObjectUtils.isNotNull(newAttachment)) {
                copyingNote.addAttachment(newAttachment);
              }
            }

            poDoc.addNote(copyingNote);
          }

        } catch (Exception e) {
          throw new RuntimeException(e);
        }
      }
    }
    purapService.saveDocumentNoValidation(poDoc);
    return poDoc;
  } //  mjmc end
 /**
  * @see
  *     org.kuali.kfs.module.ar.document.service.InvoiceRecurrenceService#isValidRecurrenceEndDate(Date)
  */
 @Override
 public boolean isValidRecurrenceEndDate(Date beginDate, Date endDate) {
   boolean success = true;
   if (ObjectUtils.isNull(beginDate) || ObjectUtils.isNull(endDate)) {
     return success;
   }
   Timestamp beginDateTimestamp = new Timestamp(beginDate.getTime());
   Timestamp endDateTimestamp = new Timestamp(endDate.getTime());
   if ((ObjectUtils.isNotNull(endDateTimestamp))
       && (endDateTimestamp.before(beginDateTimestamp)
           || endDateTimestamp.equals(beginDateTimestamp))) {
     return false;
   }
   return success;
 }