narasiahli-be/app/module/ebooks/service/ebook_purchases.service.go

186 lines
5.2 KiB
Go

package service
import (
"errors"
"narasi-ahli-be/app/database/entity"
"narasi-ahli-be/app/module/ebooks/mapper"
"narasi-ahli-be/app/module/ebooks/repository"
"narasi-ahli-be/app/module/ebooks/response"
usersRepository "narasi-ahli-be/app/module/users/repository"
"narasi-ahli-be/utils/paginator"
utilSvc "narasi-ahli-be/utils/service"
"time"
"github.com/rs/zerolog"
)
// EbookPurchasesService
type ebookPurchasesService struct {
Repo repository.EbookPurchasesRepository
EbooksRepo repository.EbooksRepository
Log zerolog.Logger
UsersRepo usersRepository.UsersRepository
}
// EbookPurchasesService define interface of IEbookPurchasesService
type EbookPurchasesService interface {
GetByBuyerId(authToken string, pagination *paginator.Pagination) (purchases []*response.EbookPurchaseResponse, paging paginator.Pagination, err error)
PurchaseEbook(authToken string, ebookId uint, paymentMethod string) (purchase *response.EbookPurchaseResponse, err error)
UpdatePaymentStatus(purchaseId uint, paymentStatus string, transactionId string, paymentProof string) (err error)
GetPurchaseById(purchaseId uint) (purchase *response.EbookPurchaseResponse, err error)
ConfirmPayment(purchaseId uint) (err error)
}
// NewEbookPurchasesService init EbookPurchasesService
func NewEbookPurchasesService(
repo repository.EbookPurchasesRepository,
ebooksRepo repository.EbooksRepository,
log zerolog.Logger,
usersRepo usersRepository.UsersRepository) EbookPurchasesService {
return &ebookPurchasesService{
Repo: repo,
EbooksRepo: ebooksRepo,
Log: log,
UsersRepo: usersRepo,
}
}
// GetByBuyerId implement interface of EbookPurchasesService
func (_i *ebookPurchasesService) GetByBuyerId(authToken string, pagination *paginator.Pagination) (purchases []*response.EbookPurchaseResponse, paging paginator.Pagination, err error) {
user := utilSvc.GetUserInfo(_i.Log, _i.UsersRepo, authToken)
if user == nil {
return nil, paginator.Pagination{}, errors.New("user not found")
}
purchasesData, paging, err := _i.Repo.GetByBuyerId(user.ID, pagination)
if err != nil {
return nil, paging, err
}
purchases = mapper.ToEbookPurchaseResponseList(purchasesData)
return purchases, paging, nil
}
// PurchaseEbook implement interface of EbookPurchasesService
func (_i *ebookPurchasesService) PurchaseEbook(authToken string, ebookId uint, paymentMethod string) (purchase *response.EbookPurchaseResponse, err error) {
user := utilSvc.GetUserInfo(_i.Log, _i.UsersRepo, authToken)
if user == nil {
return nil, errors.New("user not found")
}
// Check if ebook exists
ebook, err := _i.EbooksRepo.FindOne(ebookId)
if err != nil {
return nil, errors.New("ebook not found")
}
// Check if already purchased
existingPurchase, err := _i.Repo.FindByBuyerAndEbook(user.ID, ebookId)
if err == nil && existingPurchase != nil {
return nil, errors.New("ebook already purchased")
}
// Create purchase record
purchaseEntity := &entity.EbookPurchases{
BuyerId: user.ID,
EbookId: ebookId,
PurchasePrice: ebook.Price,
PaymentMethod: &paymentMethod,
PaymentStatus: stringPtr("pending"),
StatusId: intPtr(1),
IsActive: boolPtr(true),
}
purchaseData, err := _i.Repo.Create(purchaseEntity)
if err != nil {
return nil, err
}
// Update purchase count
err = _i.EbooksRepo.UpdatePurchaseCount(ebookId)
if err != nil {
_i.Log.Error().Err(err).Msg("Failed to update purchase count")
}
purchase = mapper.ToEbookPurchaseResponse(purchaseData)
return purchase, nil
}
// UpdatePaymentStatus implement interface of EbookPurchasesService
func (_i *ebookPurchasesService) UpdatePaymentStatus(purchaseId uint, paymentStatus string, transactionId string, paymentProof string) (err error) {
_, err = _i.Repo.FindOne(purchaseId)
if err != nil {
return errors.New("purchase not found")
}
updateData := &entity.EbookPurchases{
PaymentStatus: &paymentStatus,
TransactionId: &transactionId,
PaymentProof: &paymentProof,
}
if paymentStatus == "paid" {
now := time.Now()
updateData.PaymentDate = &now
}
err = _i.Repo.Update(purchaseId, updateData)
if err != nil {
return err
}
return nil
}
// GetPurchaseById implement interface of EbookPurchasesService
func (_i *ebookPurchasesService) GetPurchaseById(purchaseId uint) (purchase *response.EbookPurchaseResponse, err error) {
purchaseData, err := _i.Repo.FindOne(purchaseId)
if err != nil {
return nil, err
}
purchase = mapper.ToEbookPurchaseResponse(purchaseData)
return purchase, nil
}
// ConfirmPayment implement interface of EbookPurchasesService
func (_i *ebookPurchasesService) ConfirmPayment(purchaseId uint) (err error) {
purchase, err := _i.Repo.FindOne(purchaseId)
if err != nil {
return errors.New("purchase not found")
}
if purchase.PaymentStatus == nil || *purchase.PaymentStatus != "paid" {
return errors.New("payment not completed")
}
// Update status to confirmed
updateData := &entity.EbookPurchases{
StatusId: intPtr(2), // Assuming 2 is confirmed status
}
err = _i.Repo.Update(purchaseId, updateData)
if err != nil {
return err
}
return nil
}
// Helper functions
func stringPtr(s string) *string {
return &s
}
func intPtr(i int) *int {
return &i
}
func boolPtr(b bool) *bool {
return &b
}