Skip to content
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.hackerrank.corebanking.controller;

import com.hackerrank.corebanking.helper.TransactionLimits;
import com.hackerrank.corebanking.model.Account;
import com.hackerrank.corebanking.model.Transaction;
import com.hackerrank.corebanking.repository.TransactionRepository;
Expand All @@ -10,8 +11,12 @@
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.*;

import java.time.LocalDate;
import java.time.ZoneId;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@RestController
@RequestMapping("/api/core-banking/transaction")
Expand Down Expand Up @@ -51,6 +56,48 @@ public List<Transaction> transactionHistory(@RequestParam(name = "accountId") St
return transactionRepository.findTransactionsByDateCreatedBetweenAndFromAccountIdOrToAccountId(fromDate, toDate, accountId, accountId);
}

@GetMapping("/limits")
@ResponseStatus(HttpStatus.OK)
public Map<String, Double> getTransactionLimits() {
Map<String, Double> limits = new HashMap<>();
limits.put("dailyLimit", TransactionLimits.DAILY_LIMIT);
limits.put("monthlyLimit", TransactionLimits.MONTHLY_LIMIT);
return limits;
}

@GetMapping("/card-usage/{cardNumber}")
@ResponseStatus(HttpStatus.OK)
public Map<String, Double> getCardTransactionUsage(@PathVariable String cardNumber) {
Map<String, Double> usage = new HashMap<>();

// Calculate daily usage
LocalDate today = LocalDate.now();
Date startDate = Date.from(today.atStartOfDay(ZoneId.systemDefault()).toInstant());
Date endDate = Date.from(today.plusDays(1).atStartOfDay(ZoneId.systemDefault()).toInstant());

List<Transaction> dailyTransactions = transactionRepository.findBySourceCardNumberAndTransactionDateBetween(
cardNumber, startDate, endDate);
double dailyUsage = dailyTransactions.stream()
.mapToDouble(Transaction::getTransferAmount)
.sum();

// Calculate monthly usage
LocalDate firstOfMonth = today.withDayOfMonth(1);
Date monthStartDate = Date.from(firstOfMonth.atStartOfDay(ZoneId.systemDefault()).toInstant());
Date monthEndDate = Date.from(today.plusDays(1).atStartOfDay(ZoneId.systemDefault()).toInstant());

List<Transaction> monthlyTransactions = transactionRepository.findBySourceCardNumberAndTransactionDateBetween(
cardNumber, monthStartDate, monthEndDate);
double monthlyUsage = monthlyTransactions.stream()
.mapToDouble(Transaction::getTransferAmount)
.sum();

usage.put("dailyUsage", dailyUsage);
usage.put("monthlyUsage", monthlyUsage);

return usage;
}

public Object getErrorMessage() {
throw new UnsupportedOperationException("Unimplemented method 'getErrorMessage'");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,10 @@ public ResponseEntity<?> handleAccountLockedException(Exception ex, WebRequest r
ErrorDetails errorDetails = new ErrorDetails(new Date(), ex.getMessage(), request.getDescription(false));
return new ResponseEntity<>(errorDetails, HttpStatus.FORBIDDEN);
}

@ExceptionHandler(TransactionLimitOperationException.class)
public ResponseEntity<?> handleTransactionLimitOperationException(Exception ex, WebRequest request) {
ErrorDetails errorDetails = new ErrorDetails(new Date(), ex.getMessage(), request.getDescription(false));
return new ResponseEntity<>(errorDetails, HttpStatus.FORBIDDEN);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package com.hackerrank.corebanking.exception;

public class TransactionLimitOperationException extends RuntimeException {
public TransactionLimitOperationException(String message) {
super(message);
}
}


Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package com.hackerrank.corebanking.helper;

import com.hackerrank.corebanking.model.Transaction;
import com.hackerrank.corebanking.repository.TransactionRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.time.LocalDate;
import java.time.YearMonth;
import java.time.ZoneId;
import java.util.Date;

@Component
public class TransactionLimits {
public static double DAILY_LIMIT = 5000.00;
public static double MONTHLY_LIMIT = 20000.00;

@Autowired
private TransactionRepository transactionRepository;

private TransactionLimits() {}

public double calculateTotalDailyCardTransactions(String cardNumber) {
LocalDate today = LocalDate.now();
Date startDate = Date.from(today.atStartOfDay(ZoneId.systemDefault()).toInstant());
Date endDate = Date.from(today.plusDays(1).atStartOfDay(ZoneId.systemDefault()).toInstant());

return transactionRepository
.findBySourceCardNumberAndDateCreatedBetween(cardNumber, startDate, endDate)
.stream()
.mapToDouble(Transaction::getTransferAmount)
.sum();
}

public double calculateTotalMonthlyCardTransactions(String cardNumber) {
YearMonth currentMonth = YearMonth.now();
Date startDate = Date.from(currentMonth.atDay(1).atStartOfDay(ZoneId.systemDefault()).toInstant());
Date endDate = Date
.from(currentMonth.atEndOfMonth().atTime(23, 59, 59).atZone(ZoneId.systemDefault()).toInstant());

return transactionRepository
.findBySourceCardNumberAndDateCreatedBetween(cardNumber, startDate, endDate)
.stream()
.mapToDouble(Transaction::getTransferAmount)
.sum();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,10 @@
@Entity
public class Transaction implements Serializable {
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@Column(name = "date_created")
Date dateCreated = new Date();
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@Column(name = "last_created")
Date lastCreated = new Date();
@TableGenerator(name = "tr_id_gen", table = "tr_id_gen", pkColumnName = "gen_name", valueColumnName = "gen_val", pkColumnValue = "gen_val", initialValue = 1042, allocationSize = 7)
@Id
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,4 +38,7 @@ List<Transaction> findBySourceCardNumberAndTransactionDateBetween(
@Param("startDate") Date startDate,
@Param("endDate") Date endDate
);

List<Transaction> findBySourceCardNumberAndDateCreatedBetween(
String sourceCardNumber, Date startDate, Date endDate);
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Optional;

@Service
public class CardService {
Expand Down Expand Up @@ -127,4 +128,12 @@ public void processVirtualTransactionLimits(Card card, Double transactionAmount)

throw new IllegalArgumentException("The virtual card transaction cannot be processed due to confusing, redundant checks.");
}

public Optional<Card> getCardByNumber(String cardNumber) {
return cardRepository.findById(cardNumber); // if cardNumber is @Id
}

public Card saveCard(Card card) {
return cardRepository.save(card);
}
}
Loading