Yimaru-BackEnd/internal/repository/payments.go

216 lines
6.4 KiB
Go

package repository
import (
dbgen "Yimaru-Backend/gen/db"
"Yimaru-Backend/internal/domain"
"context"
"github.com/jackc/pgx/v5/pgtype"
)
func (s *Store) CreatePayment(ctx context.Context, input domain.CreatePaymentInput) (*domain.Payment, error) {
payment, err := s.queries.CreatePayment(ctx, dbgen.CreatePaymentParams{
UserID: input.UserID,
PlanID: int64PtrToPgInt8(input.PlanID),
SubscriptionID: pgtype.Int8{Valid: false},
SessionID: pgtype.Text{Valid: false},
TransactionID: pgtype.Text{Valid: false},
Nonce: input.Nonce,
Amount: toPgNumeric(input.Amount),
Currency: input.Currency,
PaymentMethod: toPgText(input.PaymentMethod),
Column10: string(domain.PaymentStatusPending), // status with COALESCE
PaymentUrl: pgtype.Text{Valid: false},
ExpiresAt: toPgTimestamptzPtr(input.ExpiresAt),
})
if err != nil {
return nil, err
}
return paymentToDomain(payment), nil
}
func (s *Store) GetPaymentByID(ctx context.Context, id int64) (*domain.Payment, error) {
payment, err := s.queries.GetPaymentByID(ctx, id)
if err != nil {
return nil, err
}
return paymentToDomain(payment), nil
}
func (s *Store) GetPaymentBySessionID(ctx context.Context, sessionID string) (*domain.Payment, error) {
payment, err := s.queries.GetPaymentBySessionID(ctx, toPgText(&sessionID))
if err != nil {
return nil, err
}
return paymentToDomain(payment), nil
}
func (s *Store) GetPaymentByNonce(ctx context.Context, nonce string) (*domain.Payment, error) {
payment, err := s.queries.GetPaymentByNonce(ctx, nonce)
if err != nil {
return nil, err
}
return paymentToDomain(payment), nil
}
func (s *Store) GetPaymentByTransactionID(ctx context.Context, transactionID string) (*domain.Payment, error) {
payment, err := s.queries.GetPaymentByTransactionID(ctx, toPgText(&transactionID))
if err != nil {
return nil, err
}
return paymentToDomain(payment), nil
}
func (s *Store) GetPaymentsByUserID(ctx context.Context, userID int64, limit, offset int32) ([]domain.Payment, error) {
payments, err := s.queries.GetPaymentsByUserID(ctx, dbgen.GetPaymentsByUserIDParams{
UserID: userID,
Limit: pgtype.Int4{Int32: limit, Valid: true},
Offset: pgtype.Int4{Int32: offset, Valid: true},
})
if err != nil {
return nil, err
}
result := make([]domain.Payment, len(payments))
for i, p := range payments {
result[i] = domain.Payment{
ID: p.ID,
UserID: p.UserID,
PlanID: int8PtrToInt64Ptr(p.PlanID),
SubscriptionID: int8PtrToInt64Ptr(p.SubscriptionID),
SessionID: fromPgTextPtr(p.SessionID),
TransactionID: fromPgTextPtr(p.TransactionID),
Nonce: p.Nonce,
Amount: fromPgNumeric(p.Amount),
Currency: p.Currency,
PaymentMethod: fromPgTextPtr(p.PaymentMethod),
Status: p.Status,
PaymentURL: fromPgTextPtr(p.PaymentUrl),
PaidAt: timePtr(p.PaidAt),
ExpiresAt: timePtr(p.ExpiresAt),
CreatedAt: p.CreatedAt.Time,
UpdatedAt: timePtr(p.UpdatedAt),
PlanName: fromPgTextPtr(p.PlanName),
}
}
return result, nil
}
func (s *Store) GetPendingPaymentsByUserID(ctx context.Context, userID int64) ([]domain.Payment, error) {
payments, err := s.queries.GetPendingPaymentsByUserID(ctx, userID)
if err != nil {
return nil, err
}
result := make([]domain.Payment, len(payments))
for i, p := range payments {
result[i] = *paymentToDomain(p)
}
return result, nil
}
func (s *Store) UpdatePaymentStatus(ctx context.Context, id int64, status string) error {
return s.queries.UpdatePaymentStatus(ctx, dbgen.UpdatePaymentStatusParams{
Status: status,
ID: id,
})
}
func (s *Store) UpdatePaymentStatusBySessionID(ctx context.Context, sessionID, status, transactionID, paymentMethod string) error {
return s.queries.UpdatePaymentStatusBySessionID(ctx, dbgen.UpdatePaymentStatusBySessionIDParams{
Status: status,
TransactionID: toPgText(&transactionID),
PaymentMethod: toPgText(&paymentMethod),
SessionID: toPgText(&sessionID),
})
}
func (s *Store) UpdatePaymentStatusByNonce(ctx context.Context, nonce, status, transactionID, paymentMethod string) error {
return s.queries.UpdatePaymentStatusByNonce(ctx, dbgen.UpdatePaymentStatusByNonceParams{
Status: status,
TransactionID: toPgText(&transactionID),
PaymentMethod: toPgText(&paymentMethod),
Nonce: nonce,
})
}
func (s *Store) UpdatePaymentSessionID(ctx context.Context, id int64, sessionID, paymentURL string) error {
return s.queries.UpdatePaymentSessionID(ctx, dbgen.UpdatePaymentSessionIDParams{
SessionID: toPgText(&sessionID),
PaymentUrl: toPgText(&paymentURL),
ID: id,
})
}
func (s *Store) LinkPaymentToSubscription(ctx context.Context, paymentID, subscriptionID int64) error {
return s.queries.LinkPaymentToSubscription(ctx, dbgen.LinkPaymentToSubscriptionParams{
SubscriptionID: pgtype.Int8{Int64: subscriptionID, Valid: true},
ID: paymentID,
})
}
func (s *Store) GetExpiredPendingPayments(ctx context.Context) ([]domain.Payment, error) {
payments, err := s.queries.GetExpiredPendingPayments(ctx)
if err != nil {
return nil, err
}
result := make([]domain.Payment, len(payments))
for i, p := range payments {
result[i] = *paymentToDomain(p)
}
return result, nil
}
func (s *Store) ExpirePayment(ctx context.Context, id int64) error {
return s.queries.ExpirePayment(ctx, id)
}
// Helper functions
func paymentToDomain(p dbgen.Payment) *domain.Payment {
return &domain.Payment{
ID: p.ID,
UserID: p.UserID,
PlanID: int8PtrToInt64Ptr(p.PlanID),
SubscriptionID: int8PtrToInt64Ptr(p.SubscriptionID),
SessionID: fromPgTextPtr(p.SessionID),
TransactionID: fromPgTextPtr(p.TransactionID),
Nonce: p.Nonce,
Amount: fromPgNumeric(p.Amount),
Currency: p.Currency,
PaymentMethod: fromPgTextPtr(p.PaymentMethod),
Status: p.Status,
PaymentURL: fromPgTextPtr(p.PaymentUrl),
PaidAt: timePtr(p.PaidAt),
ExpiresAt: timePtr(p.ExpiresAt),
CreatedAt: p.CreatedAt.Time,
UpdatedAt: timePtr(p.UpdatedAt),
}
}
func int64PtrToPgInt8(val *int64) pgtype.Int8 {
if val == nil {
return pgtype.Int8{Valid: false}
}
return pgtype.Int8{Int64: *val, Valid: true}
}
func int8PtrToInt64Ptr(val pgtype.Int8) *int64 {
if !val.Valid {
return nil
}
return &val.Int64
}
func fromPgTextPtr(t pgtype.Text) *string {
if !t.Valid {
return nil
}
return &t.String
}
func strPtr(s string) *string {
return &s
}