/**
   * Create Facts (the accounting logic) for CMB.
   *
   * <pre>
   *      BankAsset       DR      CR  (Statement)
   *      BankInTransit   DR      CR              (Payment)
   *      Charge          DR          (Charge)
   *      Interest        DR      CR  (Interest)
   * </pre>
   *
   * @param as accounting schema
   * @return Fact
   */
  @Override
  public List<Fact> createFacts(final MAcctSchema as) {
    // create Fact Header
    final Fact fact = new Fact(this, as, Fact.POST_Actual);
    // boolean isInterOrg = isInterOrg(as);

    // Header -- there may be different currency amounts

    final int AD_Org_ID = getBank_Org_ID(); // Bank Account Org
    // Lines
    for (int i = 0; i < p_lines.length; i++) {
      final DocLine_BankStatement line = (DocLine_BankStatement) p_lines[i];
      final int C_BPartner_ID = line.getC_BPartner_ID();

      // Avoid usage of clearing accounts
      // If both accounts BankAsset and BankInTransit are equal
      // then remove the posting

      MAccount acct_bank_asset = getAccount(Doc.ACCTTYPE_BankAsset, as);
      MAccount acct_bank_in_transit = getAccount(Doc.ACCTTYPE_BankInTransit, as);

      // if ((!as.isPostIfClearingEqual()) && acct_bank_asset.equals(acct_bank_in_transit) &&
      // (!isInterOrg)) {
      // don't validate interorg on banks for this - normally banks are balanced by orgs
      if ((!as.isPostIfClearingEqual()) && acct_bank_asset.equals(acct_bank_in_transit)) {
        // Not using clearing accounts
        // just post the difference (if any)

        BigDecimal amt_stmt_minus_trx = line.getStmtAmt().subtract(line.getTrxAmt());
        if (amt_stmt_minus_trx.compareTo(Env.ZERO) != 0) {

          // BankAsset DR CR (Statement minus Payment)
          final FactLine fl =
              fact.createLine(line, acct_bank_asset, line.getC_Currency_ID(), amt_stmt_minus_trx);
          if (fl != null && AD_Org_ID != 0) fl.setAD_Org_ID(AD_Org_ID);
          if (fl != null && C_BPartner_ID != 0) fl.setC_BPartner_ID(C_BPartner_ID);
        }
      }
      // Normal Adempiere behavior -- unchanged if using clearing accounts
      else {
        // BankAsset DR CR (Statement)
        {
          FactLine fl =
              fact.createLine(line, acct_bank_asset, line.getC_Currency_ID(), line.getStmtAmt());
          if (fl != null && AD_Org_ID != 0) fl.setAD_Org_ID(AD_Org_ID);
          if (fl != null && C_BPartner_ID != 0) fl.setC_BPartner_ID(C_BPartner_ID);
        }

        //
        // BankInTransit DR CR (Payment)
        {
          final List<I_C_BankStatementLine_Ref> lineReferences = line.getReferences();
          if (lineReferences.isEmpty()) {
            final FactLine fl =
                fact.createLine(
                    line, acct_bank_in_transit, line.getC_Currency_ID(), line.getTrxAmt().negate());
            if (fl != null) {
              if (C_BPartner_ID != 0) fl.setC_BPartner_ID(C_BPartner_ID);
              if (AD_Org_ID != 0) fl.setAD_Org_ID(AD_Org_ID);
              else fl.setAD_Org_ID(line.getAD_Org_ID(true)); // from payment
            }
          } else {
            for (final I_C_BankStatementLine_Ref lineRef : lineReferences) {
              final FactLine fl =
                  fact.createLine(
                      line,
                      acct_bank_in_transit,
                      lineRef.getC_Currency_ID(),
                      lineRef.getTrxAmt().negate());
              if (fl != null) {
                fl.setSubLine_ID(lineRef.getC_BankStatementLine_Ref_ID());
                fl.setC_BPartner_ID(lineRef.getC_BPartner_ID());
                if (AD_Org_ID != 0) fl.setAD_Org_ID(AD_Org_ID);
                else fl.setAD_Org_ID(line.getAD_Org_ID(lineRef.getC_Payment())); // from payment
              }
            }
          }
        }
      }

      //
      // Charge DR (Charge)
      {
        final FactLine fl;
        if (line.getChargeAmt().compareTo(Env.ZERO) > 0) {
          fl =
              fact.createLine(
                  line,
                  line.getChargeAccount(as, line.getChargeAmt().negate()),
                  line.getC_Currency_ID(),
                  null,
                  line.getChargeAmt());
        } else {
          fl =
              fact.createLine(
                  line,
                  line.getChargeAccount(as, line.getChargeAmt().negate()),
                  line.getC_Currency_ID(),
                  line.getChargeAmt().negate(),
                  null);
        }
        if (fl != null && C_BPartner_ID != 0) fl.setC_BPartner_ID(C_BPartner_ID);
      }

      //
      // Interest DR CR (Interest)
      {
        final FactLine fl;
        if (line.getInterestAmt().signum() < 0) {
          fl =
              fact.createLine(
                  line,
                  getAccount(Doc.ACCTTYPE_InterestExp, as),
                  getAccount(Doc.ACCTTYPE_InterestExp, as),
                  line.getC_Currency_ID(),
                  line.getInterestAmt().negate());
        } else {
          fl =
              fact.createLine(
                  line,
                  getAccount(Doc.ACCTTYPE_InterestRev, as),
                  getAccount(Doc.ACCTTYPE_InterestRev, as),
                  line.getC_Currency_ID(),
                  line.getInterestAmt().negate());
        }
        if (fl != null && C_BPartner_ID != 0) fl.setC_BPartner_ID(C_BPartner_ID);
      }

      //
      // fact.createTaxCorrection();
    }
    //
    final ArrayList<Fact> facts = new ArrayList<Fact>();
    facts.add(fact);
    return facts;
  } // createFact