Sapient Fee Calculator: Coding problem in Java

Upasana | May 21, 2019 | 3 min read | 5,267 views | sapient interviews


Problem statement

Sapient has won the contract to implement processing fee calculator for a major investment bank (henceforth referred as client). Client receives transactions from various external sources. These transactions are received in a pre-configured format, for example, csv, excel, xml or a simple pipe delimited format text file placed at a file location. The client needs to calculate the processing fee for each transaction based on some criteria. Design a program for this scenario.

Github Source code

You can clone github repository for the accompanied source code:

Caveats with the current solution

Many important things are missing in the current solution:

  1. Testcase are very important, they are not included yet. You need to invest sometime writing the testcases.

  2. Implementation is only provided for CSV reader, not for xml/xls reader, which can be added later on.

Solution

There are two critical components in this coding problem:

  1. Designing a generic reader for transactions that can read from CSV/JSON/XLS/XML file format. Strategy design pattern can be used in this case, where depending upon the file format we can choose the reader.

  2. Designing the Fee Calculator. Fee calculator logic involves certain criteria like

    • Is transaction an intra-day transaction

    • Is transaction a Buy or Sell

    • etc.

      current logic is very simple, but there is a scope to implement it using proper design pattern.

Creating a Model

We will create a transaction model that maps all attributes of transaction.

Transaction.java
public class Transaction {

    private String externalTransactionID;
    private String clientId;
    private String securityId;
    private Integer transactionType;
    private java.util.Date transactionDate;
    private Double marketValue;
    private Boolean priority;
    private Double transactionFees;

//getter, setter left for brevity
}

Generic Reader for reading transactions

Java 8 provides support for Functional interfaces (Conceptually, a functional interface has exactly one abstract method), we will create a Functional Interface for reading Transactions from a file format. We are providing three implementations for txt, excel and xml file format in form of lamda functions. Also we are providing a static factory method to read a given file and load all transactions into a list.

TransactionReader.java
@FunctionalInterface
public interface TransactionReader {

    List<Transaction> read(String filePath) throws IOException;

    static List<Transaction> readFile(FILE_TYPE fileType, String filePath) throws IOException {
        switch (fileType) {
            case CSV:
                return csvTrxReader().read(filePath);
            case TEXT:
                return textTrxReader().read(filePath);
            case XML:
                return xmlTrxReader().read(filePath);

            default:
                return null;
        }
    }

    static TransactionReader textTrxReader() {
        return transactionFile -> {
            List<Transaction> list = new ArrayList<>();
            String line = "";
            String cvsSplitBy = ",";
            try (BufferedReader br = new BufferedReader(new InputStreamReader(TransactionReader.class.getClassLoader().getResourceAsStream(transactionFile)));) {
                while ((line = br.readLine()) != null) {
                    String[] transactionAttributes = line.split(cvsSplitBy);
                    Transaction transaction = Utils.getTransaction(transactionAttributes);
                    list.add(transaction);
                }
                return list;
            }
        };
    }

    static TransactionReader xmlTrxReader() {
        throw new RuntimeException("not yet implemented");
    }

    static TransactionReader csvTrxReader() {
        throw new RuntimeException("not yet implemented");
    }

}

FeeCalculator logic

Fee calculator logic calculates the applicable fee for each transaction.

FeeCalculator.java
public class FeeCalculator {

    private List<Transaction> transactionList = new ArrayList<>();

    public void addTransaction(Transaction transaction) {
        transactionList.add(calculateFee(transaction));
    }

    public void addTransaction(List<Transaction> transactions) {
        transactions.forEach(this::addTransaction);
    }

    private Transaction calculateFee(Transaction transaction) {
        if (isIntradayTransaction(transaction)) {
            transaction.setTransactionFees(Constant.TRANSACTION_FEE.TEN.getFees());
        } else {
            if (transaction.getPriority()) {
                transaction.setTransactionFees(Constant.TRANSACTION_FEE.FIVE_HUNDRED.getFees());
            } else {
                if (transaction.getTransactionType() == Constant.TRANSACTION_TYPE.SELL.getType() ||
                        transaction.getTransactionType() == Constant.TRANSACTION_TYPE.WITHDRAW.getType()) {
                    transaction.setTransactionFees(Constant.TRANSACTION_FEE.HUNDRED.getFees());
                } else if (transaction.getTransactionType() == Constant.TRANSACTION_TYPE.BUY.getType() ||
                        transaction.getTransactionType() == Constant.TRANSACTION_TYPE.DEPOSIT.getType()) {
                    transaction.setTransactionFees(Constant.TRANSACTION_FEE.FIFTY.getFees());
                }
            }
        }
        return transaction;
    }

    private boolean isIntradayTransaction(Transaction other) {
        boolean isIntraDayTransaction = false;
        if (transactionList.size() > 0) {
            for (Transaction transaction : transactionList) {
                if (transaction.getClientId().equals(other.getClientId()) &&
                        transaction.getSecurityId().equals(other.getSecurityId()) &&
                        transaction.getTransactionDate().equals(other.getTransactionDate())) {
                    if ((transaction.getTransactionType() == Constant.TRANSACTION_TYPE.BUY.getType() &&
                            other.getTransactionType() == Constant.TRANSACTION_TYPE.SELL.getType()) ||
                            (transaction.getTransactionType() == Constant.TRANSACTION_TYPE.SELL.getType() &&
                                    other.getTransactionType() == Constant.TRANSACTION_TYPE.BUY.getType())) {
                        isIntraDayTransaction = true;
                        transaction.setTransactionFees(Constant.TRANSACTION_FEE.TEN.getFees());
                        break;
                    }
                }
            }
        }
        return isIntraDayTransaction;
    }
}

Sorting of transactions

We need to sort the results based on clientId, transactionType, transactionDate and priority. We will use Java 8 feature to do the same.

Trx sorting
public void displayTransactionReport() {
    transactionList.sort(Comparator.comparing(Transaction::getClientId)
            .thenComparing(Transaction::getTransactionType)
            .thenComparing(Transaction::getTransactionDate)
            .thenComparing(Transaction::getPriority));

            ...rest of the logic to display the trxs
}

That’s all for now.


Buy my ebook for complete question bank

Most of these questions has been answered in my eBook "Cracking the Core Java Interview" updated on June 2018, that you can buy from this link:

Buy from Shunya (DRM Free PDF download with updates)

sapient interviews:
  1. Sapient Global Markets important topics in Java
  2. Sapient - Coding Exercise for Designing Smart Card System for Delhi Metro
  3. Sapient Global Market Java Interview Questions and Coding Exercise
See all articles in sapient interviews
Top articles in this category:
  1. Sapient Global Market Java Interview Questions and Coding Exercise
  2. Multi-threading Java Interview Questions for Investment Bank
  3. Goldman Sachs Java Interview Questions
  4. RBS Java Programming Interview Questions
  5. ION Trading Java Interview Questions
  6. Cracking core java interviews - question bank
  7. Sapient Global Markets important topics in Java

Recommended books for interview preparation:

Find more on this topic:
Buy interview books

Java & Microservices interview refresher for experienced developers.