public void debit(String walletPublicKey, BalanceType balanceType, BigDecimal debitAmount)
      throws CantRegisterDebitException, CashMoneyWalletInsufficientFundsException {
    DatabaseTable table;
    DatabaseTableRecord record;
    try {
      table = this.database.getTable(CashMoneyWalletDatabaseConstants.WALLETS_TABLE_NAME);
      record = this.getWalletRecordByPublicKey(walletPublicKey);
      if (balanceType == BalanceType.AVAILABLE) {
        BigDecimal available =
            new BigDecimal(
                record.getStringValue(
                    CashMoneyWalletDatabaseConstants.WALLETS_AVAILABLE_BALANCE_COLUMN_NAME));
        available = available.subtract(debitAmount);

        if (available.compareTo(new BigDecimal(0)) < 0)
          throw new CashMoneyWalletInsufficientFundsException(
              CashMoneyWalletInsufficientFundsException.DEFAULT_MESSAGE,
              null,
              "Debit in Cash wallet",
              "Cant debit available balance by this amount, insufficient funds.");

        record.setStringValue(
            CashMoneyWalletDatabaseConstants.WALLETS_AVAILABLE_BALANCE_COLUMN_NAME,
            available.toPlainString());

      } else if (balanceType == BalanceType.BOOK) {
        BigDecimal book =
            new BigDecimal(
                record.getStringValue(
                    CashMoneyWalletDatabaseConstants.WALLETS_BOOK_BALANCE_COLUMN_NAME));
        book = book.subtract(debitAmount);

        if (book.compareTo(new BigDecimal(0)) < 0)
          throw new CashMoneyWalletInsufficientFundsException(
              CantRegisterDebitException.DEFAULT_MESSAGE,
              null,
              "Debit in Cash wallet",
              "Cant debit book balance by this amount, insufficient funds.");

        record.setStringValue(
            CashMoneyWalletDatabaseConstants.WALLETS_BOOK_BALANCE_COLUMN_NAME,
            book.toPlainString());

      } else if (balanceType == BalanceType.ALL) {
        BigDecimal available =
            new BigDecimal(
                record.getStringValue(
                    CashMoneyWalletDatabaseConstants.WALLETS_AVAILABLE_BALANCE_COLUMN_NAME));
        BigDecimal book =
            new BigDecimal(
                record.getStringValue(
                    CashMoneyWalletDatabaseConstants.WALLETS_BOOK_BALANCE_COLUMN_NAME));

        available = available.subtract(debitAmount);
        book = book.subtract(debitAmount);

        if (available.compareTo(new BigDecimal(0)) < 0)
          throw new CashMoneyWalletInsufficientFundsException(
              CantRegisterDebitException.DEFAULT_MESSAGE,
              null,
              "Debit in Cash wallet",
              "Cant debit available balance by this amount, insufficient funds.");

        if (book.compareTo(new BigDecimal(0)) < 0)
          throw new CashMoneyWalletInsufficientFundsException(
              CantRegisterDebitException.DEFAULT_MESSAGE,
              null,
              "Debit in Cash wallet",
              "Cant debit book balance by this amount, insufficient funds.");

        record.setStringValue(
            CashMoneyWalletDatabaseConstants.WALLETS_AVAILABLE_BALANCE_COLUMN_NAME,
            available.toPlainString());
        record.setStringValue(
            CashMoneyWalletDatabaseConstants.WALLETS_BOOK_BALANCE_COLUMN_NAME,
            book.toPlainString());
      }

      table.updateRecord(record);

    } catch (CashMoneyWalletInconsistentTableStateException e) {
      throw new CantRegisterDebitException(
          e.getMessage(),
          e,
          "Debit in Cash wallet",
          "Cant debit balance. Inconsistent Table State");
    } catch (CantUpdateRecordException e) {
      throw new CantRegisterDebitException(
          e.getMessage(), e, "Debit in Cash wallet", "Cant debit balance. Cant update record");
    } catch (CantLoadTableToMemoryException e) {
      throw new CantRegisterDebitException(
          e.getMessage(),
          e,
          "Debit in Cash wallet",
          "Cant debit balance. Cant load table to memory");
    } catch (CashMoneyWalletDoesNotExistException e) {
      throw new CantRegisterDebitException(
          e.getMessage(), e, "Debit in Cash wallet", "Cant debit balance. Wallet does not exist");
    }
  }
  public void credit(String walletPublicKey, BalanceType balanceType, BigDecimal creditAmount)
      throws CantRegisterCreditException {
    DatabaseTable table;
    DatabaseTableRecord record;
    try {
      table = this.database.getTable(CashMoneyWalletDatabaseConstants.WALLETS_TABLE_NAME);
      record = this.getWalletRecordByPublicKey(walletPublicKey);
      if (balanceType == BalanceType.AVAILABLE) {
        BigDecimal available =
            new BigDecimal(
                record.getStringValue(
                    CashMoneyWalletDatabaseConstants.WALLETS_AVAILABLE_BALANCE_COLUMN_NAME));
        available = available.add(creditAmount);

        record.setStringValue(
            CashMoneyWalletDatabaseConstants.WALLETS_AVAILABLE_BALANCE_COLUMN_NAME,
            available.toPlainString());
      } else if (balanceType == BalanceType.BOOK) {
        BigDecimal book =
            new BigDecimal(
                record.getStringValue(
                    CashMoneyWalletDatabaseConstants.WALLETS_BOOK_BALANCE_COLUMN_NAME));
        book = book.add(creditAmount);

        record.setStringValue(
            CashMoneyWalletDatabaseConstants.WALLETS_BOOK_BALANCE_COLUMN_NAME,
            book.toPlainString());
      } else if (balanceType == BalanceType.ALL) {
        BigDecimal available =
            new BigDecimal(
                record.getStringValue(
                    CashMoneyWalletDatabaseConstants.WALLETS_AVAILABLE_BALANCE_COLUMN_NAME));
        BigDecimal book =
            new BigDecimal(
                record.getStringValue(
                    CashMoneyWalletDatabaseConstants.WALLETS_BOOK_BALANCE_COLUMN_NAME));

        available = available.add(creditAmount);
        book = book.add(creditAmount);

        record.setStringValue(
            CashMoneyWalletDatabaseConstants.WALLETS_AVAILABLE_BALANCE_COLUMN_NAME,
            available.toPlainString());
        record.setStringValue(
            CashMoneyWalletDatabaseConstants.WALLETS_BOOK_BALANCE_COLUMN_NAME,
            book.toPlainString());
      }

      table.updateRecord(record);

    } catch (CashMoneyWalletInconsistentTableStateException e) {
      throw new CantRegisterCreditException(
          e.getMessage(),
          e,
          "Credit in Cash wallet",
          "Cant credit balance. Inconsistent Table State");
    } catch (CantUpdateRecordException e) {
      throw new CantRegisterCreditException(
          e.getMessage(), e, "Credit in Cash wallet", "Cant credit balance. Cant update record");
    } catch (CantLoadTableToMemoryException e) {
      throw new CantRegisterCreditException(
          e.getMessage(),
          e,
          "Credit in Cash wallet",
          "Cant credit balance. Cant load table to memory");
    } catch (CashMoneyWalletDoesNotExistException e) {
      throw new CantRegisterCreditException(
          e.getMessage(), e, "Credit in Cash wallet", "Cant credit balance. Wallet does not exist");
    }
  }