PortfolioTransactionService.java

package com.tdmconsult.ete.transactions;

import com.tdmconsult.ete.api.PortfolioTransactionController;
import com.tdmconsult.ete.documents.FinancialDocument;
import com.tdmconsult.ete.documents.FinancialDocumentRepository;
import com.tdmconsult.ete.masterdata.SecurityRepository;
import com.tdmconsult.ete.utils.EurCentUtils;
import java.math.BigDecimal;
import java.util.Objects;
import java.util.UUID;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
@Transactional
@RequiredArgsConstructor
public class PortfolioTransactionService {

    public static final BigDecimal ONE_HUNDRET = BigDecimal.valueOf(100);

    private final TradeTransactionRepository tradeTransactionRepository;
    private final SecurityRepository securityRepository;
    private final PaymentTransactionRepository paymentTransactionRepository;
    private final FinancialDocumentRepository financialDocumentRepository;

    public String buy(final PortfolioTransactionController.BuyRequestDto buyRequest) {

        final var security = securityRepository.findByPublicIdOrThrow(buyRequest.assetPublicId());

        final var data = new TradeTransaction();
        data.setType(TradeTransaction.TransactionType.BUY);
        data.setPublicId(UUID.randomUUID().toString());
        data.setTradingDate(buyRequest.tradingDate());
        data.setSecurity(security);
        data.setQuantity(buyRequest.quantity());
        data.setPrincipleAmount(EurCentUtils.toBigDecimal(buyRequest.principleAmountCents()));
        data.setTotalCost(Objects.requireNonNull(EurCentUtils.toBigDecimal(buyRequest.totalCostCents())));

        final var newTradeTransaction = tradeTransactionRepository.save(data);

        if (buyRequest.documentPublicId() != null) {
            financialDocumentRepository
                    .findByPublicIdOrThrow(buyRequest.documentPublicId())
                    .linkTo(newTradeTransaction)
                    .setState(FinancialDocument.State.PROCESSED);
        }

        return data.getPublicId();
    }

    public String sell(final PortfolioTransactionController.SellRequestDto sellRequest) {

        final var security = securityRepository.findByIsinOrThrow(sellRequest.assetIsin());

        final var data = new TradeTransaction();
        data.setType(TradeTransaction.TransactionType.SELL);
        data.setPublicId(UUID.randomUUID().toString());
        data.setTradingDate(sellRequest.tradingDate());
        data.setSecurity(security);
        data.setQuantity(sellRequest.quantity());
        data.setPrincipleAmount(EurCentUtils.toBigDecimal(sellRequest.principleAmountCents()));
        data.setTotalCost(Objects.requireNonNull(EurCentUtils.toBigDecimal(sellRequest.totalCostCents())));

        tradeTransactionRepository.save(data);
        return data.getPublicId();
    }

    public String payment(final PortfolioTransactionController.PaymentCaptureRequestDto request) {

        final var security = securityRepository.findByIsinOrThrow(request.assetIsin());

        final var data = PaymentTransaction.of(security);
        data.setType(PaymentTransaction.PaymentType.valueOf(request.typeOfPayment()));
        data.setTradingDate(request.tradingDate());
        data.setQuantity(request.quantity());
        data.setGrossAmount(request.grossAmount());
        data.setNetAmount(request.netAmount());

        data.setDividendPerShare(request.dividendPerShare());
        data.setExchangeRate(request.exchangeRate());
        data.setDomesticWithholdingTax(request.domesticCapitalGainTax());
        data.setDomesticWithholdingSoli(request.domesticCapitalGainAddOn());
        data.setForeignWithholdingTax(request.foreignWithholdingTax());

        paymentTransactionRepository.save(data);
        return data.getPublicId();
    }
}