624 lines
18 KiB
Go
624 lines
18 KiB
Go
package order
|
|
|
|
import (
|
|
"database/sql"
|
|
errors2 "enaklo-pos-be/internal/common/errors"
|
|
"enaklo-pos-be/internal/common/logger"
|
|
"enaklo-pos-be/internal/common/mycontext"
|
|
order2 "enaklo-pos-be/internal/constants/order"
|
|
"enaklo-pos-be/internal/entity"
|
|
"enaklo-pos-be/internal/repository"
|
|
"enaklo-pos-be/internal/utils/generator"
|
|
"encoding/json"
|
|
"errors"
|
|
"fmt"
|
|
"go.uber.org/zap"
|
|
"golang.org/x/net/context"
|
|
"gorm.io/gorm"
|
|
"strconv"
|
|
"time"
|
|
)
|
|
|
|
type Config interface {
|
|
GetOrderFee(source string) float64
|
|
}
|
|
|
|
type OrderService struct {
|
|
repo repository.Order
|
|
crypt repository.Crypto
|
|
product repository.Product
|
|
pg repository.PaymentGateway
|
|
payment repository.Payment
|
|
transaction repository.TransactionRepository
|
|
txmanager repository.TransactionManager
|
|
wallet repository.WalletRepository
|
|
linkquRepo repository.LinkQu
|
|
cfg Config
|
|
}
|
|
|
|
func NewOrderService(
|
|
repo repository.Order,
|
|
product repository.Product, crypt repository.Crypto,
|
|
pg repository.PaymentGateway, payment repository.Payment,
|
|
txmanager repository.TransactionManager,
|
|
wallet repository.WalletRepository, cfg Config,
|
|
transaction repository.TransactionRepository,
|
|
linkquRepo repository.LinkQu,
|
|
) *OrderService {
|
|
return &OrderService{
|
|
repo: repo,
|
|
product: product,
|
|
crypt: crypt,
|
|
pg: pg,
|
|
payment: payment,
|
|
txmanager: txmanager,
|
|
wallet: wallet,
|
|
cfg: cfg,
|
|
transaction: transaction,
|
|
linkquRepo: linkquRepo,
|
|
}
|
|
}
|
|
|
|
func (s *OrderService) CreateOrder(ctx mycontext.Context, req *entity.OrderRequest) (*entity.OrderResponse, error) {
|
|
productIDs, filteredItems := s.filterOrderItems(req.OrderItems)
|
|
if len(productIDs) == 0 {
|
|
return nil, errors2.ErrorBadRequest
|
|
}
|
|
req.OrderItems = filteredItems
|
|
|
|
if len(productIDs) < 1 {
|
|
return nil, errors2.ErrorBadRequest
|
|
}
|
|
|
|
products, err := s.product.GetProductsByIDs(ctx, productIDs, req.PartnerID)
|
|
if err != nil {
|
|
logger.ContextLogger(ctx).Error("error when getting products by IDs", zap.Error(err))
|
|
return nil, err
|
|
}
|
|
|
|
productMap := make(map[int64]*entity.ProductDB)
|
|
for _, product := range products {
|
|
productMap[product.ID] = product
|
|
}
|
|
|
|
totalAmount := 0.0
|
|
for _, item := range req.OrderItems {
|
|
product, ok := productMap[item.ProductID]
|
|
if !ok {
|
|
logger.ContextLogger(ctx).Error("product not found", zap.Int64("productID", item.ProductID))
|
|
return nil, errors.New("product not found")
|
|
}
|
|
totalAmount += product.Price * float64(item.Quantity)
|
|
}
|
|
|
|
order := &entity.Order{
|
|
PartnerID: req.PartnerID,
|
|
Status: order2.New.String(),
|
|
Amount: totalAmount,
|
|
Total: totalAmount + s.cfg.GetOrderFee(req.Source),
|
|
Fee: s.cfg.GetOrderFee(req.Source),
|
|
PaymentType: req.PaymentMethod,
|
|
CreatedBy: req.CreatedBy,
|
|
OrderItems: []entity.OrderItem{},
|
|
Source: req.Source,
|
|
}
|
|
|
|
for _, item := range req.OrderItems {
|
|
order.OrderItems = append(order.OrderItems, entity.OrderItem{
|
|
ItemID: item.ProductID,
|
|
ItemType: productMap[item.ProductID].Type,
|
|
Price: productMap[item.ProductID].Price,
|
|
Quantity: int(item.Quantity),
|
|
CreatedBy: req.CreatedBy,
|
|
Product: productMap[item.ProductID].ToProduct(),
|
|
})
|
|
}
|
|
|
|
order, err = s.repo.Create(ctx, order)
|
|
if err != nil {
|
|
logger.ContextLogger(ctx).Error("error when creating order", zap.Error(err))
|
|
return nil, err
|
|
}
|
|
|
|
order, err = s.repo.FindByID(ctx, order.ID)
|
|
if err != nil {
|
|
logger.ContextLogger(ctx).Error("error when creating order", zap.Error(err))
|
|
return nil, err
|
|
}
|
|
|
|
return &entity.OrderResponse{
|
|
Order: order,
|
|
}, nil
|
|
}
|
|
|
|
func (s *OrderService) filterOrderItems(items []entity.OrderItemRequest) ([]int64, []entity.OrderItemRequest) {
|
|
var productIDs []int64
|
|
var filteredItems []entity.OrderItemRequest
|
|
for _, item := range items {
|
|
if item.Quantity != 0 {
|
|
productIDs = append(productIDs, item.ProductID)
|
|
filteredItems = append(filteredItems, item)
|
|
}
|
|
}
|
|
return productIDs, filteredItems
|
|
}
|
|
|
|
func (s *OrderService) CheckInInquiry(ctx mycontext.Context, qrCode string, partnerID *int64) (*entity.CheckinResponse, error) {
|
|
order, err := s.repo.FindByQRCode(ctx, qrCode)
|
|
if err != nil {
|
|
if errors.Is(err, gorm.ErrRecordNotFound) {
|
|
return nil, errors2.NewErrorMessage(errors2.ErrorInvalidRequest, "Not Valid QR Code")
|
|
}
|
|
|
|
logger.ContextLogger(ctx).Error("error when getting order by QR code", zap.Error(err))
|
|
return nil, err
|
|
}
|
|
|
|
if order.PartnerID != *partnerID {
|
|
return nil, errors2.ErrorBadRequest
|
|
}
|
|
|
|
if order.Status != "PAID" {
|
|
return nil, errors2.ErrorInvalidRequest
|
|
}
|
|
|
|
token, err := s.crypt.GenerateJWTOrder(order)
|
|
if err != nil {
|
|
logger.ContextLogger(ctx).Error("error when generate checkin token", zap.Error(err))
|
|
return nil, err
|
|
}
|
|
|
|
orderResponse := &entity.CheckinResponse{
|
|
Token: token,
|
|
}
|
|
|
|
return orderResponse, nil
|
|
}
|
|
|
|
func (s *OrderService) CheckInExecute(ctx mycontext.Context,
|
|
token string, partnerID *int64) (*entity.CheckinExecute, error) {
|
|
pID, orderID, err := s.crypt.ValidateJWTOrder(token)
|
|
if err != nil {
|
|
logger.ContextLogger(ctx).Error("error when validating JWT order", zap.Error(err))
|
|
return nil, err
|
|
}
|
|
|
|
if pID != *partnerID {
|
|
return nil, errors2.ErrorBadRequest
|
|
}
|
|
|
|
order, err := s.repo.FindByID(ctx, orderID)
|
|
if err != nil {
|
|
logger.ContextLogger(ctx).Error("error when getting order by ID", zap.Error(err))
|
|
return nil, err
|
|
}
|
|
|
|
resp := &entity.CheckinExecute{
|
|
Order: order,
|
|
}
|
|
|
|
return resp, nil
|
|
}
|
|
|
|
func (s *OrderService) Execute(ctx mycontext.Context, req *entity.OrderExecuteRequest) (*entity.ExecuteOrderResponse, error) {
|
|
partnerID, orderID, err := s.crypt.ValidateJWTOrder(req.Token)
|
|
if err != nil {
|
|
logger.ContextLogger(ctx).Error("error when validating JWT order", zap.Error(err))
|
|
return nil, err
|
|
}
|
|
|
|
order, err := s.repo.FindByID(ctx, orderID)
|
|
if err != nil {
|
|
if errors.Is(err, gorm.ErrRecordNotFound) {
|
|
logger.ContextLogger(ctx).Error("order not found", zap.Int64("orderID", orderID))
|
|
return nil, errors.New("order not found")
|
|
}
|
|
logger.ContextLogger(ctx).Error("error when finding order by ID", zap.Error(err))
|
|
return nil, err
|
|
}
|
|
|
|
payment, err := s.payment.FindByOrderAndPartnerID(ctx, orderID, partnerID)
|
|
if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
|
|
logger.ContextLogger(ctx).Error("error getting payment data from db", zap.Error(err))
|
|
return nil, err
|
|
}
|
|
|
|
if payment != nil {
|
|
return s.createExecuteOrderResponse(order, payment), nil
|
|
}
|
|
|
|
if order.PartnerID != partnerID {
|
|
logger.ContextLogger(ctx).Error("partner ID mismatch", zap.Int64("orderID", orderID), zap.Int64("tokenPartnerID", partnerID), zap.Int64("orderPartnerID", order.PartnerID))
|
|
return nil, errors.New("partner ID mismatch")
|
|
}
|
|
|
|
if order.Status != "NEW" {
|
|
return nil, errors.New("invalid state")
|
|
}
|
|
|
|
resp := &entity.ExecuteOrderResponse{
|
|
Order: order,
|
|
}
|
|
|
|
order.SetExecutePaymentStatus()
|
|
order, err = s.repo.Update(ctx, order)
|
|
if err != nil {
|
|
logger.ContextLogger(ctx).Error("error when updating order status", zap.Error(err))
|
|
return nil, err
|
|
}
|
|
|
|
return resp, nil
|
|
}
|
|
|
|
func (s *OrderService) createExecuteOrderResponse(order *entity.Order, payment *entity.Payment) *entity.ExecuteOrderResponse {
|
|
var metadata map[string]string
|
|
if err := json.Unmarshal(payment.RequestMetadata, &metadata); err != nil {
|
|
logger.ContextLogger(context.Background()).Error("error unmarshaling request metadata", zap.Error(err))
|
|
return &entity.ExecuteOrderResponse{
|
|
Order: order,
|
|
}
|
|
}
|
|
return &entity.ExecuteOrderResponse{
|
|
Order: order,
|
|
PaymentToken: metadata["payment_token"],
|
|
RedirectURL: metadata["payment_redirect_url"],
|
|
}
|
|
}
|
|
|
|
func (s *OrderService) processNonCashPayment(ctx context.Context, order *entity.Order, partnerID, createdBy int64) (*entity.MidtransResponse, error) {
|
|
paymentRequest := entity.PaymentRequest{
|
|
PaymentReferenceID: generator.GenerateUUIDV4(),
|
|
TotalAmount: int64(order.Total),
|
|
//OrderItems: order.OrderItems,
|
|
Provider: order.PaymentType,
|
|
}
|
|
|
|
paymentResponse, err := s.pg.CreatePayment(paymentRequest)
|
|
if err != nil {
|
|
logger.ContextLogger(ctx).Error("error when creating payment", zap.Error(err))
|
|
return nil, err
|
|
}
|
|
|
|
requestMetadata, err := json.Marshal(map[string]string{
|
|
"partner_id": strconv.FormatInt(partnerID, 10),
|
|
"created_by": strconv.FormatInt(createdBy, 10),
|
|
"payment_token": paymentResponse.Token,
|
|
"payment_redirect_url": paymentResponse.RedirectURL,
|
|
})
|
|
if err != nil {
|
|
logger.ContextLogger(ctx).Error("error when marshaling request metadata", zap.Error(err))
|
|
return nil, err
|
|
}
|
|
|
|
payment := &entity.Payment{
|
|
PartnerID: partnerID,
|
|
OrderID: order.ID,
|
|
ReferenceID: paymentRequest.PaymentReferenceID,
|
|
Channel: "MIDTRANS",
|
|
PaymentType: order.PaymentType,
|
|
Amount: order.Amount,
|
|
State: "PENDING",
|
|
CreatedAt: time.Now(),
|
|
UpdatedAt: time.Now(),
|
|
RequestMetadata: requestMetadata,
|
|
}
|
|
|
|
_, err = s.payment.Create(ctx, payment)
|
|
if err != nil {
|
|
logger.ContextLogger(ctx).Error("error when creating payment record", zap.Error(err))
|
|
return nil, err
|
|
}
|
|
|
|
return &entity.MidtransResponse{
|
|
Token: paymentResponse.Token,
|
|
RedirectURL: paymentResponse.RedirectURL,
|
|
}, nil
|
|
}
|
|
|
|
func (s *OrderService) processQRPayment(ctx mycontext.Context, order *entity.Order, partnerID, createdBy int64) (*entity.PaymentResponse, error) {
|
|
paymentRequest := entity.PaymentRequest{
|
|
PaymentReferenceID: generator.GenerateUUIDV4(),
|
|
TotalAmount: int64(order.Total),
|
|
Provider: "LINKQU",
|
|
CustomerID: fmt.Sprintf("POS-%d", ctx.RequestedBy()),
|
|
CustomerName: fmt.Sprintf("POS-%s", ctx.GetName()),
|
|
}
|
|
|
|
paymentResponse, err := s.pg.CreateQRISPayment(paymentRequest)
|
|
if err != nil {
|
|
logger.ContextLogger(ctx).Error("error when creating payment", zap.Error(err))
|
|
return nil, err
|
|
}
|
|
|
|
requestMetadata, err := json.Marshal(map[string]string{
|
|
"partner_id": strconv.FormatInt(partnerID, 10),
|
|
"created_by": strconv.FormatInt(createdBy, 10),
|
|
"qr_code": paymentResponse.QRCodeURL,
|
|
})
|
|
|
|
if err != nil {
|
|
logger.ContextLogger(ctx).Error("error when marshaling request metadata", zap.Error(err))
|
|
return nil, err
|
|
}
|
|
|
|
payment := &entity.Payment{
|
|
PartnerID: partnerID,
|
|
OrderID: order.ID,
|
|
ReferenceID: paymentRequest.PaymentReferenceID,
|
|
Channel: "LINKQU",
|
|
PaymentType: order.PaymentType,
|
|
Amount: order.Amount,
|
|
State: "PENDING",
|
|
CreatedAt: time.Now(),
|
|
UpdatedAt: time.Now(),
|
|
RequestMetadata: requestMetadata,
|
|
}
|
|
|
|
_, err = s.payment.Create(ctx, payment)
|
|
if err != nil {
|
|
logger.ContextLogger(ctx).Error("error when creating payment record", zap.Error(err))
|
|
return nil, err
|
|
}
|
|
|
|
return paymentResponse, nil
|
|
}
|
|
|
|
func (s *OrderService) processVAPayment(ctx mycontext.Context, order *entity.Order, partnerID, createdBy int64) (*entity.PaymentResponse, error) {
|
|
paymentRequest := entity.PaymentRequest{
|
|
PaymentReferenceID: generator.GenerateUUIDV4(),
|
|
TotalAmount: int64(order.Total),
|
|
Provider: "LINKQU",
|
|
CustomerID: strconv.FormatInt(order.User.ID, 10),
|
|
CustomerName: order.User.Name,
|
|
CustomerEmail: order.User.Email,
|
|
}
|
|
|
|
paymentResponse, err := s.pg.CreatePaymentVA(paymentRequest)
|
|
if err != nil {
|
|
logger.ContextLogger(ctx).Error("error when creating payment", zap.Error(err))
|
|
return nil, err
|
|
}
|
|
|
|
requestMetadata, err := json.Marshal(map[string]string{
|
|
"virtual_account": paymentResponse.VirtualAccountNumber,
|
|
"bank_name": paymentResponse.BankName,
|
|
"bank_code": paymentResponse.BankCode,
|
|
})
|
|
|
|
if err != nil {
|
|
logger.ContextLogger(ctx).Error("error when marshaling request metadata", zap.Error(err))
|
|
return nil, err
|
|
}
|
|
|
|
payment := &entity.Payment{
|
|
PartnerID: partnerID,
|
|
OrderID: order.ID,
|
|
ReferenceID: paymentRequest.PaymentReferenceID,
|
|
Channel: "LINKQU",
|
|
PaymentType: order.PaymentType,
|
|
Amount: order.Amount,
|
|
State: "PENDING",
|
|
CreatedAt: time.Now(),
|
|
UpdatedAt: time.Now(),
|
|
RequestMetadata: requestMetadata,
|
|
}
|
|
|
|
_, err = s.payment.Create(ctx, payment)
|
|
if err != nil {
|
|
logger.ContextLogger(ctx).Error("error when creating payment record", zap.Error(err))
|
|
return nil, err
|
|
}
|
|
|
|
return paymentResponse, nil
|
|
}
|
|
|
|
func (s *OrderService) ProcessCallback(ctx context.Context, req *entity.CallbackRequest) error {
|
|
tx, err := s.txmanager.Begin(ctx, &sql.TxOptions{Isolation: sql.LevelSerializable})
|
|
if err != nil {
|
|
return fmt.Errorf("failed to begin transaction: %w", err)
|
|
}
|
|
defer tx.Rollback()
|
|
|
|
err = s.processPayment(ctx, tx, req)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to process payment: %w", err)
|
|
}
|
|
|
|
return tx.Commit().Error
|
|
}
|
|
|
|
func (s *OrderService) processPayment(ctx context.Context, tx *gorm.DB, req *entity.CallbackRequest) error {
|
|
existingPayment, err := s.payment.FindByReferenceID(ctx, tx, req.TransactionID)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to retrieve payment: %w", err)
|
|
}
|
|
|
|
existingPayment.State = updatePaymentState(req.TransactionStatus)
|
|
_, err = s.payment.UpdateWithTx(ctx, tx, existingPayment)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to update payment: %w", err)
|
|
}
|
|
|
|
order, err := s.repo.FindByID(ctx, existingPayment.OrderID)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to get order: %w", err)
|
|
}
|
|
|
|
if err := s.updateOrderStatus(ctx, tx, existingPayment.State, existingPayment.OrderID); err != nil {
|
|
return fmt.Errorf("failed to update order status: %w", err)
|
|
}
|
|
|
|
if existingPayment.State == "PAID" {
|
|
if err := s.updateWalletBalance(ctx, tx, existingPayment.PartnerID, existingPayment.Amount); err != nil {
|
|
return fmt.Errorf("failed to update wallet balance: %w", err)
|
|
}
|
|
|
|
transaction := &entity.Transaction{
|
|
PartnerID: existingPayment.PartnerID,
|
|
TransactionType: "PAYMENT_RECEIVED",
|
|
Status: "SUCCESS",
|
|
CreatedBy: 0,
|
|
Amount: existingPayment.Amount,
|
|
Fee: order.Fee,
|
|
Total: order.Total,
|
|
}
|
|
if _, err = s.transaction.Create(ctx, tx, transaction); err != nil {
|
|
return fmt.Errorf("failed to update transaction: %w", err)
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func updatePaymentState(status string) string {
|
|
switch status {
|
|
case "settlement", "capture", "paid", "settle":
|
|
return "PAID"
|
|
case "expire", "deny", "cancel", "failure", "EXPIRED":
|
|
return "EXPIRED"
|
|
default:
|
|
return status
|
|
}
|
|
}
|
|
|
|
func (s *OrderService) updateOrderStatus(ctx context.Context, tx *gorm.DB, status string, orderID int64) error {
|
|
if status != "PENDING" {
|
|
return s.repo.SetOrderStatus(ctx, tx, orderID, status)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (s *OrderService) updateWalletBalance(ctx context.Context, tx *gorm.DB, partnerID int64, amount float64) error {
|
|
wallet, err := s.wallet.GetByPartnerID(ctx, tx, partnerID)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to get wallet: %w", err)
|
|
}
|
|
wallet.Balance += amount
|
|
_, err = s.wallet.Update(ctx, tx, wallet)
|
|
return err
|
|
}
|
|
|
|
func (s *OrderService) GetAllHistoryOrders(ctx mycontext.Context, req entity.OrderSearch) ([]*entity.HistoryOrder, int, error) {
|
|
historyOrders, total, err := s.repo.GetAllHystoryOrders(ctx, req)
|
|
if err != nil {
|
|
logger.ContextLogger(ctx).Error("error when get all history orders", zap.Error(err))
|
|
return nil, 0, err
|
|
}
|
|
|
|
data := historyOrders.ToHistoryOrderList()
|
|
|
|
return data, total, nil
|
|
}
|
|
|
|
func (s *OrderService) CountSoldOfTicket(ctx mycontext.Context, req entity.OrderSearch) (*entity.TicketSold, error) {
|
|
ticket, err := s.repo.CountSoldOfTicket(ctx, req)
|
|
|
|
if err != nil {
|
|
logger.ContextLogger(ctx).Error("error when get all history orders", zap.Error(err))
|
|
return nil, err
|
|
}
|
|
|
|
data := ticket.ToTicketSold()
|
|
|
|
return data, nil
|
|
}
|
|
|
|
func (s *OrderService) GetDailySales(ctx mycontext.Context, req entity.OrderSearch) ([]entity.ProductDailySales, error) {
|
|
dailySales, err := s.repo.GetDailySalesMetrics(ctx, req)
|
|
|
|
if err != nil {
|
|
logger.ContextLogger(ctx).Error("error when get all history orders", zap.Error(err))
|
|
return nil, err
|
|
}
|
|
|
|
return dailySales, nil
|
|
}
|
|
|
|
func (s *OrderService) GetPaymentDistribution(ctx mycontext.Context, req entity.OrderSearch) ([]entity.PaymentTypeDistribution, error) {
|
|
paymentDistribution, err := s.repo.GetPaymentTypeDistribution(ctx, req)
|
|
|
|
if err != nil {
|
|
logger.ContextLogger(ctx).Error("error when get all history orders", zap.Error(err))
|
|
return nil, err
|
|
}
|
|
|
|
return paymentDistribution, nil
|
|
}
|
|
|
|
func (s *OrderService) SumAmount(ctx mycontext.Context, req entity.OrderSearch) (*entity.Order, error) {
|
|
amount, err := s.repo.SumAmount(ctx, req)
|
|
|
|
if err != nil {
|
|
logger.ContextLogger(ctx).Error("error when get amount cash orders", zap.Error(err))
|
|
return nil, err
|
|
}
|
|
|
|
data := amount.ToSumAmount()
|
|
|
|
return data, nil
|
|
}
|
|
|
|
func (s *OrderService) GetByID(ctx mycontext.Context, id int64, referenceID string) (*entity.Order, error) {
|
|
if referenceID != "" {
|
|
payment, err := s.payment.FindByReferenceID(ctx, nil, referenceID)
|
|
if err != nil {
|
|
logger.ContextLogger(ctx).Error("error when getting payment by IDs", zap.Error(err))
|
|
return nil, err
|
|
}
|
|
id = payment.OrderID
|
|
}
|
|
|
|
order, err := s.repo.FindByID(ctx, id)
|
|
if err != nil {
|
|
logger.ContextLogger(ctx).Error("error when getting products by IDs", zap.Error(err))
|
|
return nil, err
|
|
}
|
|
|
|
if ctx.IsCasheer() {
|
|
return order, nil
|
|
}
|
|
|
|
//if order.CreatedBy != ctx.RequestedBy() {
|
|
// return nil, errors2.NewError(errors2.ErrorBadRequest.ErrorType(), "order not found")
|
|
//}
|
|
|
|
return order, nil
|
|
}
|
|
|
|
func (s *OrderService) GetPrintDetail(ctx mycontext.Context, id int64) (*entity.OrderPrintDetail, error) {
|
|
order, err := s.repo.FindPrintDetailByID(ctx, id)
|
|
if err != nil {
|
|
logger.ContextLogger(ctx).Error("error when getting products by IDs", zap.Error(err))
|
|
return nil, err
|
|
}
|
|
|
|
return order, nil
|
|
}
|
|
|
|
func (s *OrderService) ProcessLinkQuCallback(ctx context.Context, req *entity.LinkQuCallback) error {
|
|
tx, err := s.txmanager.Begin(ctx, &sql.TxOptions{Isolation: sql.LevelSerializable})
|
|
if err != nil {
|
|
return fmt.Errorf("failed to begin transaction: %w", err)
|
|
}
|
|
defer tx.Rollback()
|
|
|
|
pay, err := s.linkquRepo.CheckPaymentStatus(req.PaymentReff)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to begin transaction: %w", err)
|
|
}
|
|
|
|
if pay.ResponseCode != "00" {
|
|
return nil
|
|
}
|
|
|
|
err = s.processPayment(ctx, tx, &entity.CallbackRequest{
|
|
TransactionID: req.PartnerReff,
|
|
TransactionStatus: pay.Data.StatusPaid,
|
|
})
|
|
|
|
if err != nil {
|
|
return fmt.Errorf("failed to process payment: %w", err)
|
|
}
|
|
|
|
return tx.Commit().Error
|
|
}
|