예제 #1
0
  /**
   * @see
   *     org.kuali.kfs.module.endow.document.service.CurrentTaxLotService#getCurrentTaxLotBalanceSecurityUnitValue(String)
   *     Method to get the security unit value for the current balance tax lot record
   * @param securityId
   * @return securityUnitValue
   */
  public BigDecimal getCurrentTaxLotBalanceSecurityUnitValue(String securityId) {
    BigDecimal securityUnitValue = BigDecimal.ZERO;

    Security security = securityService.getByPrimaryKey(securityId);

    return security.getUnitValue();
  }
예제 #2
0
  /**
   * @org
   *     .kuali.kfs.module.endow.document.service.CurrentTaxLotService#getCurrentTaxLotBalancesForMatchingSecurityClassCode(String)
   */
  public Collection<CurrentTaxLotBalance> getCurrentTaxLotBalancesForMatchingSecurityClassCode(
      String securityClassCode) {
    Collection<CurrentTaxLotBalance> currentTaxLotBalances = new ArrayList();

    Collection<Security> securities = new ArrayList();

    if (StringUtils.isNotBlank(securityClassCode)) {
      Map criteria = new HashMap();

      if (dataDictionaryService.getAttributeForceUppercase(
          Security.class, EndowPropertyConstants.SECURITY_CLASS_CODE)) {
        securityClassCode = securityClassCode.toUpperCase();
      }
      criteria.put(EndowPropertyConstants.SECURITY_CLASS_CODE, securityClassCode);

      securities = businessObjectService.findMatching(Security.class, criteria);

      for (Security security : securities) {
        criteria.clear();
        criteria.put(EndowPropertyConstants.CURRENT_TAX_LOT_BALANCE_SECURITY_ID, security.getId());

        currentTaxLotBalances.addAll(
            businessObjectService.findMatching(HoldingHistory.class, criteria));
      }
    }

    return currentTaxLotBalances;
  }
  /**
   * Validates that the validateTaxLotsCostAndTransactionAmountLessOrEqualToSecurityCommitment
   * returns false when the SECURITY_ID has a class code type of A (Alternative Investments), and
   * the total END_HLDG_TAX_LOT_T: HLDG_COST for the SECURITY_ID plus the END_TRAN_LN_T: TRAN_AMT
   * exceeds the value in END_SEC_T: CMTMNT_AMT for the Security
   */
  public void testValidateTaxLotsCostAndTransactionAmountLessOrEqualToSecurityCommitment_False() {
    KEMID kemid = KemIdFixture.OPEN_KEMID_RECORD.createKemidRecord();
    // need to insert into END_HLDG_TAX_LOT_REBAL_T TABLE because of constraints....
    HoldingTaxLotRebalanceFixture.HOLDING_TAX_LOT_REBALANCE_RECORD
        .createHoldingTaxLotRebalanceRecord();
    HoldingTaxLot holdingTaxLot =
        HoldingTaxLotFixture.HOLDING_TAX_LOT_RECORD.createHoldingTaxLotRecord();
    SecurityReportingGroup reportingGroup =
        SecurityReportingGroupFixture.REPORTING_GROUP.createSecurityReportingGroup();
    EndowmentTransactionCode endowmentTransactionCode =
        EndowmentTransactionCodeFixture.INCOME_TRANSACTION_CODE.createEndowmentTransactionCode();
    ClassCode classCode =
        ClassCodeFixture.ALTERNATIVE_INVESTMENT_CLASS_CODE.createClassCodeRecord();
    Security security = SecurityFixture.ALTERNATIVE_INVEST_ACTIVE_SECURITY.createSecurityRecord();
    security.setCommitmentAmount(BigDecimal.ZERO);

    document.getTargetTransactionSecurity().setSecurityID(security.getId());
    document.getTargetTransactionSecurity().setSecurity(security);

    EndowmentTransactionLine endowmentTargetTransactionLine =
        EndowmentTransactionLineFixture.ENDOWMENT_TRANSACTIONAL_LINE_POSITIVE_AMT
            .createEndowmentTransactionLine(false);
    document.addTargetTransactionLine(
        (EndowmentTargetTransactionLine) endowmentTargetTransactionLine);

    assetIncreaseDocumentTaxLotsService.updateTransactionLineTaxLots(
        document, endowmentTargetTransactionLine);

    assertFalse(
        rule.validateTaxLotsCostAndTransactionAmountLessOrEqualToSecurityCommitment(document));
  }
예제 #4
0
  /**
   * @see
   *     org.kuali.kfs.module.endow.document.service.CurrentTaxLotService#getNextTwelveMonthsEstimatedValue(String)
   *     Method to calculate Next Twelve Months Estimated value
   * @param securityId
   * @return nextTwelveMonthsEstimatedValue
   */
  public BigDecimal getNextTwelveMonthsEstimatedValue(
      HoldingTaxLot holdingTaxLot, String securityId) {
    BigDecimal nextTweleveMonthsEstimatedValue = BigDecimal.ZERO;

    Security security = securityService.getByPrimaryKey(securityId);

    return KEMCalculationRoundingHelper.multiply(
        holdingTaxLot.getUnits(),
        security.getIncomeRate(),
        EndowConstants.Scale.SECURITY_MARKET_VALUE);
  }
예제 #5
0
  /**
   * 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;
  }
예제 #6
0
  /**
   * 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;
  }
예제 #7
0
  /**
   * @see
   *     org.kuali.kfs.module.endow.document.service.CurrentTaxLotService#getNextFiscalYearInvestmentIncome(HoldingTaxLot,
   *     String) Method to calculate next fiscal year investment income
   * @param securityId
   * @return nextFiscalyearInvestmentIncome
   */
  public BigDecimal getNextFiscalYearInvestmentIncome(
      HoldingTaxLot holdingTaxLot, String securityId) {
    BigDecimal nextFiscalyearInvestmentIncome = BigDecimal.ZERO;

    Security security = securityService.getByPrimaryKey(securityId);
    nextFiscalyearInvestmentIncome =
        KEMCalculationRoundingHelper.multiply(
            security.getNextFiscalYearDistributionAmount(),
            holdingTaxLot.getUnits(),
            EndowConstants.Scale.SECURITY_MARKET_VALUE);

    return nextFiscalyearInvestmentIncome;
  }
  /** Validates that isSecurityActive returns false when an inactive security is added. */
  public void testActiveSecurity_False() {
    // add security details
    SecurityReportingGroup reportingGroup =
        SecurityReportingGroupFixture.REPORTING_GROUP.createSecurityReportingGroup();
    EndowmentTransactionCode endowmentTransactionCode =
        EndowmentTransactionCodeFixture.INCOME_TRANSACTION_CODE.createEndowmentTransactionCode();
    ClassCode classCode = ClassCodeFixture.LIABILITY_CLASS_CODE.createClassCodeRecord();
    Security security = SecurityFixture.INACTIVE_SECURITY.createSecurityRecord();
    EndowmentTargetTransactionSecurity targetTransactionSecurity =
        new EndowmentTargetTransactionSecurity();
    targetTransactionSecurity.setSecurityID(security.getId());
    targetTransactionSecurity.setSecurity(security);

    document.setTargetTransactionSecurity(targetTransactionSecurity);

    assertFalse(rule.isSecurityActive(document, false));
  }
예제 #9
0
  /**
   * calculates the remainder of fiscal year estimated income for cash
   *
   * @param security
   * @param holdingTaxLot
   * @return amount
   */
  protected BigDecimal getRemainderOfFiscalYearEstimatedIncomeForCash(
      Security security, HoldingTaxLot holdingTaxLot) {
    BigDecimal amount = BigDecimal.ZERO;

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

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

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

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

    // rule 3.b
    if (nextIncomeDueDate.before(fiscalYearEndDate)) {
      Date lastPaymentDate = getLastPaymentDate(incomePayFrequency, fiscalYearEndDate);
      long daysToLastPayment = getTotalDaysToLastPayment(lastPaymentDate, nextIncomeDueDate);

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

    return amount;
  }
예제 #10
0
  /**
   * calculates the remainder of fiscal year estimated income for bonds
   *
   * @param security
   * @param holdingTaxLot
   * @return amount
   */
  protected BigDecimal getRemainderOfFiscalYearEstimatedIncomeForBonds(
      Security security, HoldingTaxLot holdingTaxLot) {
    BigDecimal amount = BigDecimal.ZERO;

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

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

    Date fiscalYearEndDate = getFiscalYearEndDate();

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

    int numberOfMonthsRemaining = getNumberOfMonthsRemaining(fiscalYearEndDate, nextIncomeDueDate);
    // rule 2.b
    if (nextIncomeDueDate.before(fiscalYearEndDate)
        && numberOfMonthsRemaining < EndowConstants.NUMBER_OF_MONTHS_REMAINING) {
      amount =
          KEMCalculationRoundingHelper.multiply(
              holdingTaxLot.getUnits(),
              security.getIncomeRate(),
              EndowConstants.Scale.SECURITY_MARKET_VALUE);
      amount =
          KEMCalculationRoundingHelper.divide(
              amount, BigDecimal.valueOf(2), EndowConstants.Scale.SECURITY_MARKET_VALUE);
    } else {
      amount =
          KEMCalculationRoundingHelper.multiply(
              holdingTaxLot.getUnits(),
              security.getIncomeRate(),
              EndowConstants.Scale.SECURITY_MARKET_VALUE);
    }

    return amount;
  }
예제 #11
0
  /**
   * @see
   *     org.kuali.kfs.module.endow.document.service.CurrentTaxLotService#getRemainderOfFiscalYearEstimatedIncome(HoldingTaxLot,
   *     String) Method to calculate remainder of fiscal year estimated income
   * @param securityId
   * @return remainderOfFiscalYearEstimatedIncome
   */
  public BigDecimal getRemainderOfFiscalYearEstimatedIncome(
      HoldingTaxLot holdingTaxLot, String securityId) {
    BigDecimal incomeAmount = BigDecimal.ZERO;

    Security security = securityService.getByPrimaryKey(securityId);

    String classCodeType = security.getClassCode().getClassCodeType();

    if (EndowConstants.ClassCodeTypes.ALTERNATIVE_INVESTMENT.equalsIgnoreCase(classCodeType)) {
      return BigDecimal.ZERO;
    }
    // calculations for BONDS
    if (EndowConstants.ClassCodeTypes.BOND.equalsIgnoreCase(classCodeType)) {
      return getRemainderOfFiscalYearEstimatedIncomeForBonds(security, holdingTaxLot);
    }

    // calculations for CASH
    if (EndowConstants.ClassCodeTypes.CASH_EQUIVALENTS.equalsIgnoreCase(classCodeType)) {
      return getRemainderOfFiscalYearEstimatedIncomeForCash(security, holdingTaxLot);
    }

    // calculations for LIABILITIES
    if (EndowConstants.ClassCodeTypes.LIABILITY.equalsIgnoreCase(classCodeType)) {
      return BigDecimal.ZERO;
    }

    // calculations for OTHER
    if (EndowConstants.ClassCodeTypes.OTHER.equalsIgnoreCase(classCodeType)) {
      return BigDecimal.ZERO;
    }

    // calculations for POOLED FUNDS
    if (EndowConstants.ClassCodeTypes.POOLED_INVESTMENT.equalsIgnoreCase(classCodeType)) {
      return getRemainderOfFiscalYearEstimatedIncomeForPooledFunds(security, holdingTaxLot);
    }

    // calculations for STOCKS
    if (EndowConstants.ClassCodeTypes.STOCKS.equalsIgnoreCase(classCodeType)) {
      return getRemainderOfFiscalYearEstimatedIncomeForStocks(security, holdingTaxLot);
    }

    return incomeAmount;
  }
예제 #12
0
  /**
   * @see
   *     org.kuali.kfs.module.endow.document.service.CurrentTaxLotService#getHoldingMarketValue(HoldingTaxLot,
   *     String)
   */
  public BigDecimal getHoldingMarketValue(HoldingTaxLot holdingTaxLot, String securityId) {
    BigDecimal holdingMarketValue = BigDecimal.ZERO;

    Security security = securityService.getByPrimaryKey(securityId);

    String classCodeType = security.getClassCode().getClassCodeType();

    if (EndowConstants.ClassCodeTypes.ALTERNATIVE_INVESTMENT.equalsIgnoreCase(classCodeType)) {
      String kemid = holdingTaxLot.getKemid();
      if (dataDictionaryService.getAttributeForceUppercase(
          TransactionArchive.class, EndowPropertyConstants.TRANSACTION_ARCHIVE_KEM_ID)) {
        kemid = kemid.toUpperCase();
      }
      BigDecimal totalCashActivity =
          transactionArchiveDao.getTransactionArchivesTotalCashActivity(kemid, securityId);
      return (security.getSecurityValueByMarket().subtract(totalCashActivity));
    }
    // calculations for BONDS
    if (EndowConstants.ClassCodeTypes.BOND.equalsIgnoreCase(classCodeType)) {
      holdingMarketValue =
          KEMCalculationRoundingHelper.multiply(
              holdingTaxLot.getUnits(),
              security.getUnitValue(),
              EndowConstants.Scale.SECURITY_MARKET_VALUE);
      holdingMarketValue =
          KEMCalculationRoundingHelper.divide(
              holdingMarketValue,
              BigDecimal.valueOf(100),
              EndowConstants.Scale.SECURITY_MARKET_VALUE);
      return holdingMarketValue;
    }

    // other cases...
    holdingMarketValue =
        KEMCalculationRoundingHelper.multiply(
            holdingTaxLot.getUnits(),
            security.getUnitValue(),
            EndowConstants.Scale.SECURITY_MARKET_VALUE);

    return holdingMarketValue;
  }
  /**
   * Validates that validateSecurityClassCodeTypeNotLiability returns true when a security with a
   * class code other that Liability is added.
   */
  public void testLiabilityClassCode_True() {
    // add security details
    SecurityReportingGroup reportingGroup =
        SecurityReportingGroupFixture.REPORTING_GROUP.createSecurityReportingGroup();
    EndowmentTransactionCode endowmentTransactionCode =
        EndowmentTransactionCodeFixture.INCOME_TRANSACTION_CODE.createEndowmentTransactionCode();
    ClassCode classCode = ClassCodeFixture.NOT_LIABILITY_CLASS_CODE.createClassCodeRecord();
    Security security = SecurityFixture.ACTIVE_SECURITY.createSecurityRecord();

    security.setClassCode(classCode);
    security.setSecurityClassCode(classCode.getCode());

    EndowmentTargetTransactionSecurity targetTransactionSecurity =
        new EndowmentTargetTransactionSecurity();
    targetTransactionSecurity.setSecurityID(security.getId());
    targetTransactionSecurity.setSecurity(security);

    document.getTargetTransactionSecurities().add(targetTransactionSecurity);

    assertTrue(rule.validateSecurityClassCodeTypeNotLiability(document, false));
  }
  /**
   * @see
   *     org.kuali.kfs.module.endow.document.service.UpdateTaxLotsBasedOnAccMethodAndTransSubtypeService#updateTransactionLineTaxLots(boolean,
   *     org.kuali.kfs.module.endow.document.EndowmentTaxLotLinesDocument,
   *     org.kuali.kfs.module.endow.businessobject.EndowmentTransactionLine)
   */
  public void updateTransactionLineTaxLots(
      boolean isUpdate,
      EndowmentTaxLotLinesDocument endowmentTaxLotLinesDocument,
      EndowmentTransactionLine transLine) {

    EndowmentTransactionSecurity endowmentTransactionSecurity =
        endowmentTaxLotLinesDocument.getSourceTransactionSecurity();
    String accountingMethod =
        parameterService.getParameterValueAsString(
            KfsParameterConstants.ENDOWMENT_ALL.class,
            EndowParameterKeyConstants.TAX_LOTS_ACCOUNTING_METHOD);
    Security security =
        securityService.getByPrimaryKey(endowmentTransactionSecurity.getSecurityID());

    if (ObjectUtils.isNotNull(security)) {
      // In the Asset Decrease document, if transaction sub type is non-cash and IF the user inserts
      // an amount in the
      // transaction amount, that amount along with the units sill be used to generate the
      // transaction tax lot lines. The
      // amount will not be calculated by the addition of the transaction line. In the event the
      // user has entered an amount in
      // the transaction amount field, that amount along with the units will be spread
      // proportionately among the tax lots.
      if (endowmentTaxLotLinesDocument instanceof AssetDecreaseDocument
          && EndowConstants.TransactionSubTypeCode.NON_CASH.equalsIgnoreCase(
              endowmentTaxLotLinesDocument.getTransactionSubTypeCode())
          && transLine.getTransactionAmount() != null
          && transLine.getTransactionAmount().bigDecimalValue().compareTo(BigDecimal.ZERO) != 0) {
        updateTaxLotsForSubTypeNonCashAndTransAmtNonZero(
            isUpdate, endowmentTransactionSecurity, transLine);
      } else {

        if (EndowConstants.TaxLotsAccountingMethodOptions.AVERAGE_BALANCE.equalsIgnoreCase(
                accountingMethod)
            || (EndowConstants.TaxLotsAccountingMethodOptions.FIFO.equalsIgnoreCase(
                    accountingMethod)
                && !security.getClassCode().isTaxLotIndicator())) {
          if (EndowConstants.TransactionSubTypeCode.CASH.equalsIgnoreCase(
              endowmentTaxLotLinesDocument.getTransactionSubTypeCode())) {
            updateTaxLotsForAccountingMethodAverageBalance(
                true, isUpdate, endowmentTransactionSecurity, transLine);
          }
          if (EndowConstants.TransactionSubTypeCode.NON_CASH.equalsIgnoreCase(
              endowmentTaxLotLinesDocument.getTransactionSubTypeCode())) {
            updateTaxLotsForAccountingMethodAverageBalance(
                false, isUpdate, endowmentTransactionSecurity, transLine);
            setTransactionLineTotal(transLine);
          }
        }

        if ((EndowConstants.TaxLotsAccountingMethodOptions.FIFO.equalsIgnoreCase(accountingMethod)
                || EndowConstants.TaxLotsAccountingMethodOptions.LIFO.equalsIgnoreCase(
                    accountingMethod))
            && security.getClassCode().isTaxLotIndicator()) {
          boolean isFIFO =
              EndowConstants.TaxLotsAccountingMethodOptions.FIFO.equalsIgnoreCase(accountingMethod);

          if (EndowConstants.TransactionSubTypeCode.CASH.equalsIgnoreCase(
              endowmentTaxLotLinesDocument.getTransactionSubTypeCode())) {
            updateTaxLotsForAccountingMethodFIFOorLIFO(
                true, isUpdate, isFIFO, endowmentTransactionSecurity, transLine);
          }
          if (EndowConstants.TransactionSubTypeCode.NON_CASH.equalsIgnoreCase(
              endowmentTaxLotLinesDocument.getTransactionSubTypeCode())) {
            updateTaxLotsForAccountingMethodFIFOorLIFO(
                false, isUpdate, isFIFO, endowmentTransactionSecurity, transLine);
            setTransactionLineTotal(transLine);
          }
        }
      }
    }
  }