completed initial charge logic
This commit is contained in:
@@ -0,0 +1,20 @@
|
||||
package zw.qantra.tm.domain.services;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Service;
|
||||
import zw.qantra.tm.domain.models.ChargeCondition;
|
||||
import zw.qantra.tm.domain.repositories.ChargeConditionRepository;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class ChargeConditionService {
|
||||
private final ChargeConditionRepository chargeConditionRepository;
|
||||
|
||||
public ChargeConditionRepository getChargeConditionRepository() {
|
||||
return chargeConditionRepository;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package zw.qantra.tm.domain.services;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Service;
|
||||
import zw.qantra.tm.domain.models.Charge;
|
||||
import zw.qantra.tm.domain.repositories.ChargeRepository;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class ChargeService {
|
||||
private final ChargeRepository chargeRepository;
|
||||
|
||||
public ChargeRepository getChargeRepository() {
|
||||
return chargeRepository;
|
||||
}
|
||||
}
|
||||
@@ -8,4 +8,8 @@ import zw.qantra.tm.domain.repositories.CurrencyRepository;
|
||||
@RequiredArgsConstructor
|
||||
public class CurrencyService {
|
||||
private final CurrencyRepository currencyRepository;
|
||||
|
||||
public CurrencyRepository getCurrencyRepository() {
|
||||
return currencyRepository;
|
||||
}
|
||||
}
|
||||
@@ -8,4 +8,8 @@ import zw.qantra.tm.domain.repositories.IntegrationProcessorRepository;
|
||||
@RequiredArgsConstructor
|
||||
public class IntegrationProcessorService {
|
||||
private final IntegrationProcessorRepository integrationProcessorRepository;
|
||||
|
||||
public IntegrationProcessorRepository getIntegrationProcessorRepository() {
|
||||
return integrationProcessorRepository;
|
||||
}
|
||||
}
|
||||
@@ -8,4 +8,8 @@ import zw.qantra.tm.domain.repositories.PaymentProcessorRepository;
|
||||
@RequiredArgsConstructor
|
||||
public class PaymentProcessorService {
|
||||
private final PaymentProcessorRepository paymentProcessorRepository;
|
||||
|
||||
public PaymentProcessorRepository getPaymentProcessorRepository() {
|
||||
return paymentProcessorRepository;
|
||||
}
|
||||
}
|
||||
@@ -1,11 +1,87 @@
|
||||
package zw.qantra.tm.domain.services;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
|
||||
import zw.qantra.tm.domain.dtos.SBZProductDto;
|
||||
import zw.qantra.tm.domain.models.Provider;
|
||||
import zw.qantra.tm.domain.repositories.ChargeRepository;
|
||||
import zw.qantra.tm.domain.repositories.ProviderRepository;
|
||||
import zw.qantra.tm.rest.RestService;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class ProviderService {
|
||||
private final ProviderRepository providerRepository;
|
||||
private final RestService restService;
|
||||
|
||||
@Value("${sbz.aggregator.url}")
|
||||
private String aggregatorUrl;
|
||||
|
||||
public ProviderRepository getProviderRepository() {
|
||||
return providerRepository;
|
||||
}
|
||||
|
||||
public List<SBZProductDto> getProviderProducts(UUID providerId) {
|
||||
String token = restService.getMerchantToken();
|
||||
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
headers.setContentType(MediaType.APPLICATION_JSON);
|
||||
headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON));
|
||||
headers.setBearerAuth(token);
|
||||
|
||||
LinkedHashMap response = this.restService.getAs(
|
||||
aggregatorUrl + "/merchant/aggregation/products?size=100&clientUid=" + providerId.toString(),
|
||||
headers,
|
||||
LinkedHashMap.class
|
||||
);
|
||||
|
||||
LinkedHashMap body = (LinkedHashMap) response.get("body");
|
||||
List<LinkedHashMap> content = (List<LinkedHashMap>) body.get("content");
|
||||
|
||||
List<SBZProductDto> products = new ArrayList<>();
|
||||
for (LinkedHashMap product : content) {
|
||||
ObjectMapper mapper = new ObjectMapper();
|
||||
SBZProductDto productDto = mapper.convertValue(product, SBZProductDto.class);
|
||||
products.add(productDto);
|
||||
}
|
||||
|
||||
return products;
|
||||
}
|
||||
|
||||
public List<Provider> getProviders() {
|
||||
return providerRepository.findAll();
|
||||
}
|
||||
|
||||
public Optional<Provider> getProvider(UUID id) {
|
||||
return providerRepository.findById(id);
|
||||
}
|
||||
|
||||
public Provider createProvider(Provider provider) {
|
||||
return providerRepository.save(provider);
|
||||
}
|
||||
|
||||
public Provider updateProvider(UUID id, Provider provider) {
|
||||
if (providerRepository.existsById(id)) {
|
||||
provider.setId(id);
|
||||
return providerRepository.save(provider);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public boolean deleteProvider(UUID id) {
|
||||
if (providerRepository.existsById(id)) {
|
||||
providerRepository.deleteById(id);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -8,4 +8,8 @@ import zw.qantra.tm.domain.repositories.SettingRepository;
|
||||
@RequiredArgsConstructor
|
||||
public class SettingService {
|
||||
private final SettingRepository settingRepository;
|
||||
|
||||
public SettingRepository getSettingRepository() {
|
||||
return settingRepository;
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,6 @@ package zw.qantra.tm.domain.services;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Service;
|
||||
import zw.qantra.tm.domain.enums.Status;
|
||||
import zw.qantra.tm.domain.models.PaymentProcessor;
|
||||
import zw.qantra.tm.domain.models.Transaction;
|
||||
import zw.qantra.tm.domain.repositories.TransactionRepository;
|
||||
import zw.qantra.tm.domain.services.factories.PaymentProcessorFactory;
|
||||
@@ -17,11 +16,18 @@ import zw.qantra.tm.domain.services.processors.handlers.ValidationHandler;
|
||||
public class TransactionService {
|
||||
private final TransactionRepository transactionRepository;
|
||||
private final PaymentProcessorFactory paymentProcessorFactory;
|
||||
private final CalculateChargesHandler calculateChargesHandler;
|
||||
|
||||
public TransactionRepository getTransactionRepository() {
|
||||
return transactionRepository;
|
||||
}
|
||||
|
||||
public Transaction execute(Transaction transaction) {
|
||||
|
||||
LogicPipeline<Transaction, Transaction> transactionLogic =
|
||||
new LogicPipeline<>(new CalculateChargesHandler())
|
||||
new LogicPipeline<>(calculateChargesHandler)
|
||||
.addHandler(new ValidationHandler());
|
||||
|
||||
transaction = transactionLogic.execute(transaction);
|
||||
|
||||
String label = transaction.getType() + "_" + transaction.getIntegrationProcessorLabel();
|
||||
|
||||
@@ -18,8 +18,10 @@ public class ZesaConfirmationProcessor implements TransactionProcessorInterface
|
||||
@Override
|
||||
public Object process(Transaction transaction) throws Exception {
|
||||
System.out.println("processing transaction");
|
||||
throw new Exception("Challenge encountered, please contact support.");
|
||||
// return transaction;
|
||||
|
||||
|
||||
|
||||
return transaction;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,11 +1,135 @@
|
||||
package zw.qantra.tm.domain.services.processors.handlers;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import org.springframework.stereotype.Service;
|
||||
import zw.qantra.tm.domain.models.Charge;
|
||||
import zw.qantra.tm.domain.models.ChargeCondition;
|
||||
import zw.qantra.tm.domain.models.Transaction;
|
||||
import zw.qantra.tm.domain.services.ChargeConditionService;
|
||||
import zw.qantra.tm.domain.services.ChargeService;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.math.RoundingMode;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
|
||||
@AllArgsConstructor
|
||||
@Service
|
||||
public class CalculateChargesHandler implements LogicHandler<Transaction, Transaction> {
|
||||
private ChargeConditionService chargeConditionService;
|
||||
private ChargeService chargeService;
|
||||
|
||||
@Override
|
||||
public Transaction process(Transaction transaction) {
|
||||
System.out.println("processing charges");
|
||||
transaction.setCharge(BigDecimal.ZERO);
|
||||
transaction.setTax(BigDecimal.ZERO);
|
||||
transaction.setGatewayCharge(BigDecimal.ZERO);
|
||||
|
||||
BigDecimal amountToCharge = transaction.getAmount();
|
||||
BigDecimal chargeAmount = BigDecimal.ZERO;
|
||||
|
||||
List<Charge> chargeList = chargeService.getChargeRepository().findAllByCurrency(transaction.getDebitCurrency());
|
||||
|
||||
List<Charge> appropriateCharges = new ArrayList<>();
|
||||
for (Charge charge : chargeList) {
|
||||
boolean isPresent = false;
|
||||
for (ChargeCondition chargeCondition: charge.getIncludes()){
|
||||
List<String> conditionTypes = Arrays.asList(chargeCondition.getCodes().split(","));
|
||||
switch (chargeCondition.getType()){
|
||||
case GATEWAY:
|
||||
isPresent = conditionTypes.contains(transaction.getPaymentProcessorLabel());
|
||||
break;
|
||||
case PROVIDER:
|
||||
isPresent = conditionTypes.contains(transaction.getIntegrationProcessorLabel());
|
||||
break;
|
||||
}
|
||||
if(isPresent) break; // we've found a matching condition, no need to check rest of conditions
|
||||
}
|
||||
if(!isPresent) continue; // if we did not find a match, means this charge does not apply to this transaction
|
||||
|
||||
boolean isExempt = false;
|
||||
for (ChargeCondition chargeCondition: charge.getExcludes()){
|
||||
List<String> conditionTypes = Arrays.asList(chargeCondition.getCodes().split(","));
|
||||
switch (chargeCondition.getType()){
|
||||
case GATEWAY:
|
||||
isExempt = conditionTypes.contains(transaction.getPaymentProcessorLabel());
|
||||
break;
|
||||
case PROVIDER:
|
||||
isExempt = conditionTypes.contains(transaction.getIntegrationProcessorLabel());
|
||||
break;
|
||||
}
|
||||
if(isExempt) break; // we've found a matching condition, no need to check rest of conditions
|
||||
}
|
||||
if(isExempt) continue; // if we found a match, means this transaction is exempt from this charge
|
||||
|
||||
appropriateCharges.add(charge);
|
||||
}
|
||||
|
||||
for (Charge charge : appropriateCharges) {
|
||||
// if minimum amount chargeable is lower than the amount to charge, apply the min charge
|
||||
if(charge.getMinimumAmount() != null) {
|
||||
if(charge.getMinimumAmount().compareTo(amountToCharge) > 0) {
|
||||
applyCharge(transaction, charge, charge.getMin());
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// if maximum amount chargeable is higher than the amount to charge, apply the max charge
|
||||
if(charge.getMaximumAmount() != null) {
|
||||
if(charge.getMaximumAmount().compareTo(amountToCharge) < 0) {
|
||||
applyCharge(transaction, charge, charge.getMax());
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// calculate unrestricted charge amount
|
||||
// if percentage rate is not present then it's a flat charge, else it's a percentage
|
||||
if(charge.getPercentageRate() == null) {
|
||||
if(charge.getFlat() == null)
|
||||
continue;
|
||||
|
||||
chargeAmount = charge.getFlat();
|
||||
}else {
|
||||
BigDecimal fraction = charge.getPercentageRate().divide(
|
||||
new BigDecimal(100), 4, RoundingMode.CEILING);
|
||||
chargeAmount = amountToCharge.multiply(fraction)
|
||||
.setScale(2, RoundingMode.CEILING);
|
||||
|
||||
// if it's a composite charge then add the flat component as well
|
||||
if(charge.isComposite()) {
|
||||
chargeAmount = chargeAmount.add(charge.getFlat())
|
||||
.setScale(2, RoundingMode.CEILING);
|
||||
}
|
||||
}
|
||||
|
||||
// if minimum charge is set, check if the charge amount is less than the minimum
|
||||
if(charge.getMin() != null) {
|
||||
if(charge.getMin().compareTo(chargeAmount) > 0){
|
||||
chargeAmount = charge.getMin();
|
||||
}
|
||||
}
|
||||
|
||||
// if maximum charge is set, check if the charge amount is more than the maximum
|
||||
if(charge.getMax() != null) {
|
||||
if(charge.getMax().compareTo(chargeAmount) < 0) {
|
||||
chargeAmount = charge.getMax();
|
||||
}
|
||||
}
|
||||
|
||||
applyCharge(transaction, charge, chargeAmount);
|
||||
}
|
||||
|
||||
return transaction;
|
||||
}
|
||||
|
||||
void applyCharge(Transaction transaction, Charge charge, BigDecimal chargeAmount) {
|
||||
switch (charge.getChargeLabel()) {
|
||||
case FEE -> transaction.setCharge(chargeAmount);
|
||||
case TAX -> transaction.setTax(chargeAmount);
|
||||
case GATEWAY_FEE -> transaction.setGatewayCharge(chargeAmount);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user