/**
   * 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));
  }
  /**
   * @see
   *     org.kuali.kfs.module.endow.document.validation.impl.EndowmentTransactionLinesDocumentBaseRules#processAddTransactionLineRules(org.kuali.kfs.module.endow.document.EndowmentTransactionLinesDocument,
   *     org.kuali.kfs.module.endow.businessobject.EndowmentTransactionLine)
   */
  @Override
  public boolean processAddTransactionLineRules(
      EndowmentTransactionLinesDocument document, EndowmentTransactionLine line) {

    AssetIncreaseDocument assetIncreaseDoc = (AssetIncreaseDocument) document;
    EndowmentTransactionSecurity endowmentTransactionSecurity =
        assetIncreaseDoc.getTargetTransactionSecurity();
    boolean isValid = super.processAddTransactionLineRules(document, line);

    if (isValid) {

      if (isSecurityCodeEmpty(assetIncreaseDoc, false)) {
        return false;
      }
      if (!validateSecurityCode(assetIncreaseDoc, false)) {
        return false;
      }
      if (isValid) {
        isValid &= validateSecurityClassCodeTypeNotLiability(assetIncreaseDoc, false);
      }

      // Checks if Security is Active
      isValid &= isSecurityActive(assetIncreaseDoc, false);
    }

    return isValid;
  }
  /**
   * Validates that transactionLineSizeGreaterThanZero returns true if the document has at least one
   * target transaction line.
   */
  public void testDocumentHasAtLeastOneTransactionLine_True() {
    EndowmentTransactionLine endowmentTransactionLine =
        EndowmentTransactionLineFixture.ENDOWMENT_TRANSACTIONAL_LINE_INCOME
            .createEndowmentTransactionLine(false);
    document.addTargetTransactionLine((EndowmentTargetTransactionLine) endowmentTransactionLine);

    assertTrue(rule.transactionLineSizeGreaterThanZero(document, false));
  }
  /** Validates that validateSecurityCode returns false when an invalid security is set. */
  public void testValidateSecurity_False() {
    EndowmentTargetTransactionSecurity targetTransactionSecurity =
        new EndowmentTargetTransactionSecurity();
    targetTransactionSecurity.setSecurityID(EndowTestConstants.INVALID_SECURITY_ID);

    document.setTargetTransactionSecurity(targetTransactionSecurity);

    assertFalse(rule.validateSecurityCode(document, false));
  }
  /**
   * @see
   *     org.kuali.rice.kns.rules.DocumentRuleBase#processCustomRouteDocumentBusinessRules(org.kuali.rice.kns.document.Document)
   */
  public boolean processCustomRouteDocumentBusinessRules(Document document) {
    AssetIncreaseDocument assetIncreaseDoc = (AssetIncreaseDocument) document;
    EndowmentTransactionSecurity endowmentTransactionSecurity =
        assetIncreaseDoc.getTargetTransactionSecurity();

    // Validate at least one Tx was entered.
    if (!transactionLineSizeGreaterThanZero(assetIncreaseDoc, false)) return false;

    boolean isValid = super.processCustomRouteDocumentBusinessRules(document);

    if (isValid) {

      if (isSecurityCodeEmpty(assetIncreaseDoc, false)) {
        return false;
      }
      if (!validateSecurityCode(assetIncreaseDoc, false)) {
        return false;
      }

      // Checks if Security is Active
      isValid &= isSecurityActive(assetIncreaseDoc, false);

      if (isValid) {
        isValid &= validateSecurityClassCodeTypeNotLiability(assetIncreaseDoc, false);
      }

      if (isRegistrationCodeEmpty(assetIncreaseDoc, false)) {
        return false;
      }
      if (!validateRegistrationCode(assetIncreaseDoc, false)) {

        return false;
      }
      // Checks if registration code is active
      isValid &= isRegistrationCodeActive(assetIncreaseDoc, false);
    }

    if (isValid) {
      isValid =
          validateTaxLotsCostAndTransactionAmountLessOrEqualToSecurityCommitment(assetIncreaseDoc);
    }

    return isValid;
  }
  /**
   * Validates that validateRegistrationCode returns false when a valid registration code is set.
   */
  public void testValidateRegistration_False() {

    EndowmentTargetTransactionSecurity targetTransactionSecurity =
        new EndowmentTargetTransactionSecurity();
    targetTransactionSecurity.setRegistrationCode(EndowTestConstants.INVALID_REGISTRATION_CODE);

    document.setTargetTransactionSecurity(targetTransactionSecurity);

    assertFalse(rule.validateRegistrationCode(document, true));
  }
  /**
   * Creates an Asset Increase document
   *
   * @return an Asset Increase document
   * @throws WorkflowException
   */
  private AssetIncreaseDocument createAssetIncreaseDocument() throws WorkflowException {

    // create an asset increase document
    document =
        (AssetIncreaseDocument)
            EndowmentTransactionDocumentFixture.ENDOWMENT_TRANSACTIONAL_DOCUMENT_ASSET_INCREASE
                .createEndowmentTransactionDocument(AssetIncreaseDocument.class);
    document.getDocumentHeader().setDocumentDescription("This is a test Asset Increase document.");

    return document;
  }
  /** Validates that validateRegistrationCode returns true when a valid registration code is set. */
  public void testValidateRegistration_True() {

    // add security details
    RegistrationCode registrationCode =
        RegistrationCodeFixture.REGISTRATION_CODE_RECORD.createRegistrationCode();

    EndowmentTargetTransactionSecurity targetTransactionSecurity =
        new EndowmentTargetTransactionSecurity();
    targetTransactionSecurity.setRegistrationCode(registrationCode.getCode());
    targetTransactionSecurity.setRegistrationCodeObj(registrationCode);

    document.setTargetTransactionSecurity(targetTransactionSecurity);

    assertTrue(rule.validateRegistrationCode(document, false));
  }
  /** 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));
  }
  /**
   * 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));
  }
  /**
   * If the SECURITY_ID has a class code type A (Alternative Investments), the system must validate
   * that the total END_SEC_T: SEC_CVAL for the SECURITY_ID plus the END_TRAN_LN_T:TRAN_AMT does not
   * exceed the value in END_SEC_T: CMTMNT_AMT for the Security. If it does, the transaction should
   * not be allowed.
   *
   * @return true if valid, false otherwise
   */
  protected boolean validateTaxLotsCostAndTransactionAmountLessOrEqualToSecurityCommitment(
      AssetIncreaseDocument assetIncreaseDocument) {
    boolean isValid = true;

    if (assetIncreaseDocument.getTargetTransactionSecurity() != null
        && assetIncreaseDocument.getTargetTransactionSecurity().getSecurity() != null
        && assetIncreaseDocument.getTargetTransactionSecurity().getSecurity().getClassCode() != null
        && EndowConstants.ClassCodeTypes.ALTERNATIVE_INVESTMENT.equalsIgnoreCase(
            assetIncreaseDocument
                .getTargetTransactionSecurity()
                .getSecurity()
                .getClassCode()
                .getClassCodeType())) {

      BigDecimal totalTransactionLinesAmt = BigDecimal.ZERO;
      BigDecimal securityCommitmentAmt = BigDecimal.ZERO;
      BigDecimal securityCarryValue = BigDecimal.ZERO;

      if (assetIncreaseDocument.getTargetTransactionLines() != null) {
        for (EndowmentTransactionLine transactionLine :
            assetIncreaseDocument.getTargetTransactionLines()) {

          // add to total amount
          totalTransactionLinesAmt =
              totalTransactionLinesAmt.add(
                  transactionLine.getTransactionAmount().bigDecimalValue());
        }
      }

      if (assetIncreaseDocument.getTargetTransactionSecurity() != null
          && assetIncreaseDocument.getTargetTransactionSecurity().getSecurity() != null) {
        if (assetIncreaseDocument.getTargetTransactionSecurity().getSecurity().getCommitmentAmount()
            != null) {
          securityCommitmentAmt =
              assetIncreaseDocument
                  .getTargetTransactionSecurity()
                  .getSecurity()
                  .getCommitmentAmount();
        }
        if (assetIncreaseDocument.getTargetTransactionSecurity().getSecurity().getCarryValue()
            != null) {
          securityCarryValue =
              assetIncreaseDocument.getTargetTransactionSecurity().getSecurity().getCarryValue();
        }
      }

      isValid =
          (securityCarryValue.add(totalTransactionLinesAmt)).compareTo(securityCommitmentAmt) <= 0;

      if (!isValid) {
        putFieldError(
            getErrorPrefix(assetIncreaseDocument.getTargetTransactionLine(0), 0)
                + EndowPropertyConstants.TRANSACTION_LINE_TRANSACTION_AMOUNT,
            EndowKeyConstants.EndowmentTransactionDocumentConstants
                .ERROR_TRANSACTION_SECURITY_COMMITMENT_AMT);
      }
    }

    return isValid;
  }