minor adjustments
This commit is contained in:
@@ -14,22 +14,9 @@ import org.springframework.data.jpa.domain.Specification;
|
|||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
import zw.qantra.tm.domain.enums.RequestType;
|
import zw.qantra.tm.domain.enums.RequestType;
|
||||||
import zw.qantra.tm.domain.enums.Status;
|
|
||||||
import zw.qantra.tm.domain.models.AdditionalData;
|
import zw.qantra.tm.domain.models.AdditionalData;
|
||||||
import zw.qantra.tm.domain.models.Provider;
|
|
||||||
import zw.qantra.tm.domain.models.Transaction;
|
import zw.qantra.tm.domain.models.Transaction;
|
||||||
import zw.qantra.tm.domain.repositories.TransactionRepository;
|
import zw.qantra.tm.domain.repositories.TransactionRepository;
|
||||||
import zw.qantra.tm.domain.services.factories.PaymentProcessorFactory;
|
|
||||||
import zw.qantra.tm.domain.services.processors.TransactionProcessorInterface;
|
|
||||||
import zw.qantra.tm.domain.services.processors.handlers.CalculateChargesHandler;
|
|
||||||
import zw.qantra.tm.domain.services.processors.handlers.ConfirmationLabelHandler;
|
|
||||||
import zw.qantra.tm.domain.services.processors.handlers.ConfirmationLogicHandler;
|
|
||||||
import zw.qantra.tm.domain.services.processors.handlers.FormattingHandler;
|
|
||||||
import zw.qantra.tm.domain.services.processors.handlers.LogicPipeline;
|
|
||||||
import zw.qantra.tm.domain.services.processors.handlers.RecipientsUpdateHandler;
|
|
||||||
import zw.qantra.tm.domain.services.processors.handlers.ValidationHandler;
|
|
||||||
import zw.qantra.tm.domain.services.processors.handlers.erp.*;
|
|
||||||
import zw.qantra.tm.domain.models.TransactionEvent;
|
|
||||||
import zw.qantra.tm.exceptions.ApiException;
|
import zw.qantra.tm.exceptions.ApiException;
|
||||||
import zw.qantra.tm.utils.Utils;
|
import zw.qantra.tm.utils.Utils;
|
||||||
|
|
||||||
|
|||||||
@@ -1,171 +0,0 @@
|
|||||||
package zw.qantra.tm.domain.services.processors.handlers.erp;
|
|
||||||
|
|
||||||
import lombok.RequiredArgsConstructor;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
|
||||||
import org.springframework.http.HttpHeaders;
|
|
||||||
import org.springframework.http.ResponseEntity;
|
|
||||||
import org.springframework.stereotype.Service;
|
|
||||||
import zw.qantra.tm.domain.dtos.erp.PaymentEntryDto;
|
|
||||||
import zw.qantra.tm.domain.dtos.erp.PaymentReferenceDto;
|
|
||||||
import zw.qantra.tm.domain.enums.RequestType;
|
|
||||||
import zw.qantra.tm.domain.enums.Status;
|
|
||||||
import zw.qantra.tm.domain.models.Provider;
|
|
||||||
import zw.qantra.tm.domain.models.Transaction;
|
|
||||||
import zw.qantra.tm.domain.models.TransactionEvent;
|
|
||||||
import zw.qantra.tm.domain.models.User;
|
|
||||||
import zw.qantra.tm.domain.repositories.TransactionRepository;
|
|
||||||
import zw.qantra.tm.domain.services.ProviderService;
|
|
||||||
import zw.qantra.tm.domain.services.TransactionEventService;
|
|
||||||
import zw.qantra.tm.domain.services.TransactionService;
|
|
||||||
import zw.qantra.tm.domain.services.UserService;
|
|
||||||
import zw.qantra.tm.domain.services.processors.handlers.LogicHandler;
|
|
||||||
import zw.qantra.tm.exceptions.ApiException;
|
|
||||||
import zw.qantra.tm.rest.RestService;
|
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
|
||||||
import java.math.RoundingMode;
|
|
||||||
import java.nio.charset.StandardCharsets;
|
|
||||||
import java.util.*;
|
|
||||||
|
|
||||||
@Service
|
|
||||||
@RequiredArgsConstructor
|
|
||||||
public class PurchasePaymentEntryHandler implements LogicHandler<Transaction, Transaction>{
|
|
||||||
Logger logger = LoggerFactory.getLogger(PurchasePaymentEntryHandler.class);
|
|
||||||
|
|
||||||
private final RestService restService;
|
|
||||||
private final UserService userService;
|
|
||||||
private final TransactionEventService transactionEventService;
|
|
||||||
private final TransactionRepository transactionRepository;
|
|
||||||
private final ProviderService providerService;
|
|
||||||
|
|
||||||
@Value("${erpnext.url}")
|
|
||||||
private String erpnextUrl;
|
|
||||||
@Value("${erpnext.api.key}")
|
|
||||||
private String erpnextApiKey;
|
|
||||||
@Value("${erpnext.api.secret}")
|
|
||||||
private String erpnextApiSecret;
|
|
||||||
@Value("${erpnext.username}")
|
|
||||||
private String erpnextUsername;
|
|
||||||
@Value("${erpnext.password}")
|
|
||||||
private String erpnextPassword;
|
|
||||||
@Value("${erpnext.company}")
|
|
||||||
private String erpnextCompany;
|
|
||||||
@Value("${erpnext.accounts.accountsreceivable}")
|
|
||||||
private String accountsReceivableAccount;
|
|
||||||
@Value("${erpnext.accounts.cash}")
|
|
||||||
private String cashAccount;
|
|
||||||
@Value("${erpnext.accounts.payable}")
|
|
||||||
private String payableAccount;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Transaction process(Transaction transaction) {
|
|
||||||
logger.info("Processing purchase payment entry for transaction: {}", transaction.getReference());
|
|
||||||
TransactionEvent transactionEvent = TransactionEvent.builder()
|
|
||||||
.transactionId(transaction.getId().toString())
|
|
||||||
.event(RequestType.PURCHASE_PAYMENT.name())
|
|
||||||
.status(Status.PROCESSING)
|
|
||||||
.build();
|
|
||||||
transactionEventService.save(transactionEvent);
|
|
||||||
|
|
||||||
if(transaction.getStatus() == Status.SUCCESS){
|
|
||||||
try {
|
|
||||||
logger.info("Creating purchase payment entry in ERPNext for successful transaction");
|
|
||||||
|
|
||||||
// login to erp
|
|
||||||
HttpHeaders headers = new HttpHeaders();
|
|
||||||
headers.add("Content-Type", "application/json");
|
|
||||||
headers.add("Accept", "application/json");
|
|
||||||
|
|
||||||
Map<String, String> loginRequest = Map.of(
|
|
||||||
"usr", erpnextUsername,
|
|
||||||
"pwd", erpnextPassword);
|
|
||||||
|
|
||||||
String sid = "";
|
|
||||||
|
|
||||||
try {
|
|
||||||
ResponseEntity response = restService.postAsEntity(
|
|
||||||
erpnextUrl + "/method/login", loginRequest, headers, LinkedHashMap.class);
|
|
||||||
|
|
||||||
sid = response.getHeaders().getFirst("Set-Cookie");
|
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
throw new ApiException("Failed to login to ERPNext");
|
|
||||||
}
|
|
||||||
|
|
||||||
// create customer in erp
|
|
||||||
String basicAuth = "Basic " + Base64.getEncoder().encodeToString(
|
|
||||||
(erpnextApiKey + ":" + erpnextApiSecret).getBytes(StandardCharsets.UTF_8));
|
|
||||||
headers.add("Authorization", basicAuth);
|
|
||||||
headers.add("Cookie", sid);
|
|
||||||
|
|
||||||
User user = userService.getUserRepository().findById(UUID.fromString(transaction.getUserId())).orElse(null);
|
|
||||||
if(user == null)
|
|
||||||
throw new ApiException("Could not find user");
|
|
||||||
|
|
||||||
Provider provider = providerService.getProviderRepository()
|
|
||||||
.findByClientId(transaction.getBillClientId());
|
|
||||||
BigDecimal commissionPercentage = BigDecimal.valueOf(provider.getPercentageCommission())
|
|
||||||
.divide(BigDecimal.valueOf(100), 2, RoundingMode.CEILING);
|
|
||||||
BigDecimal commission = transaction.getAmount().multiply(commissionPercentage)
|
|
||||||
.setScale(2, RoundingMode.CEILING);
|
|
||||||
BigDecimal amount = transaction.getAmount().subtract(commission);
|
|
||||||
|
|
||||||
PaymentReferenceDto paymentReferenceDto = PaymentReferenceDto.builder()
|
|
||||||
.referenceDoctype("Purchase Invoice")
|
|
||||||
.referenceName(transaction.getErpPurchaseRef())
|
|
||||||
.allocatedAmount(amount)
|
|
||||||
.build();
|
|
||||||
|
|
||||||
String refNo = transaction.getCreditRef().isBlank() ? transaction.getId().toString() : transaction.getCreditRef();
|
|
||||||
|
|
||||||
PaymentEntryDto paymentEntryDto = PaymentEntryDto.builder()
|
|
||||||
.doctype("Payment Entry")
|
|
||||||
.company(erpnextCompany)
|
|
||||||
.docstatus(1)
|
|
||||||
.paymentType("Pay")
|
|
||||||
.party("Steward Bank")
|
|
||||||
.partyType("Supplier")
|
|
||||||
.paidFrom(cashAccount)
|
|
||||||
.paidTo(payableAccount)
|
|
||||||
.paidAmount(amount)
|
|
||||||
.receivedAmount(amount)
|
|
||||||
.referenceNo(refNo)
|
|
||||||
.referenceDate(transaction.getCreatedAt().toLocalDate().toString())
|
|
||||||
.postingDate(transaction.getCreatedAt().toLocalDate().toString())
|
|
||||||
.references(Arrays.asList(paymentReferenceDto))
|
|
||||||
.build();
|
|
||||||
|
|
||||||
try {
|
|
||||||
LinkedHashMap response = restService.postAs(
|
|
||||||
erpnextUrl + "/v2/document/Payment Entry", paymentEntryDto, headers, LinkedHashMap.class);
|
|
||||||
|
|
||||||
LinkedHashMap data = (LinkedHashMap) response.get("data");
|
|
||||||
String transactionId = (String) data.get("name");
|
|
||||||
|
|
||||||
transaction.setErpPurchasePaymentRef(transactionId);
|
|
||||||
transactionEvent.setStatus(Status.SUCCESS);
|
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
throw new ApiException("Failed to create purchase payment entry in ERPNext");
|
|
||||||
}
|
|
||||||
|
|
||||||
logger.info("purchase payment entry created successfully in ERPNext");
|
|
||||||
} catch (Exception e) {
|
|
||||||
logger.error("Failed to create purchase payment entry in ERPNext: {}", e.getMessage(), e);
|
|
||||||
// Don't fail the transaction, just log the error
|
|
||||||
// The ERP invoice creation is a side effect, not critical to the payment flow
|
|
||||||
transactionEvent.setStatus(Status.FAILED);
|
|
||||||
transactionEvent.setMessage(e.getMessage());
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
logger.info("Transaction status is not SUCCESS ({}), skipping purchase payment entry creation", transaction.getStatus());
|
|
||||||
}
|
|
||||||
|
|
||||||
transactionEventService.save(transactionEvent);
|
|
||||||
|
|
||||||
return transactionRepository.save(transaction);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -11,7 +11,6 @@ import zw.qantra.tm.domain.models.TransactionEvent;
|
|||||||
import zw.qantra.tm.domain.services.*;
|
import zw.qantra.tm.domain.services.*;
|
||||||
import zw.qantra.tm.domain.services.factories.PaymentProcessorFactory;
|
import zw.qantra.tm.domain.services.factories.PaymentProcessorFactory;
|
||||||
import zw.qantra.tm.domain.services.processors.TransactionProcessorInterface;
|
import zw.qantra.tm.domain.services.processors.TransactionProcessorInterface;
|
||||||
import zw.qantra.tm.domain.services.processors.handlers.erp.*;
|
|
||||||
import zw.qantra.tm.exceptions.ApiException;
|
import zw.qantra.tm.exceptions.ApiException;
|
||||||
|
|
||||||
@Service("pollStatus")
|
@Service("pollStatus")
|
||||||
|
|||||||
Reference in New Issue
Block a user