treasurer/internal/interface/repository/payment.go
2023-06-13 13:22:51 +00:00

159 lines
4.7 KiB
Go

package repository
import (
"context"
"fmt"
"time"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/bson/primitive"
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
"go.uber.org/zap"
"penahub.gitlab.yandexcloud.net/external/treasurer/internal/errors"
"penahub.gitlab.yandexcloud.net/external/treasurer/internal/models"
)
var PaymentFields = struct {
ID string
UserID string
PaymentID string
IdempotencePaymentID string
ClientIP string
Currency string
Amount string
Type string
Status string
Completed string
IsDeleted string
CreatedAt string
UpdatedAt string
DeletedAt string
RawPaymentBody string
CallbackHostGRPC string
}{
ID: "_id",
UserID: "userId",
PaymentID: "paymentId",
IdempotencePaymentID: "idempotencePaymentId",
ClientIP: "clientIp",
Currency: "currency",
Amount: "amount",
Type: "type",
Status: "status",
Completed: "completed",
IsDeleted: "isDeleted",
CreatedAt: "createdAt",
UpdatedAt: "updatedAt",
DeletedAt: "deletedAt",
RawPaymentBody: "rawPaymentBody",
CallbackHostGRPC: "callbackHostGrpc",
}
type PaymentRepositoryDeps struct {
Logger *zap.Logger
Collection *mongo.Collection
}
type PaymentRepository struct {
logger *zap.Logger
collection *mongo.Collection
}
func NewPaymentRepository(deps PaymentRepositoryDeps) (*PaymentRepository, errors.Error) {
if deps.Logger == nil {
return nil, errors.NewWithMessage("Logger in nil on <NewPaymentRepository>", errors.ErrInvalidArgs)
}
if deps.Collection == nil {
return nil, errors.NewWithMessage("Collection in nil on <NewPaymentRepository>", errors.ErrInvalidArgs)
}
return &PaymentRepository{
logger: deps.Logger,
collection: deps.Collection,
}, nil
}
func (receiver *PaymentRepository) SetPaymentComplete(ctx context.Context, paymentID string) (*models.Payment, errors.Error) {
payment := models.Payment{}
options := options.FindOneAndUpdate().SetReturnDocument(options.After)
filter := bson.M{PaymentFields.PaymentID: paymentID}
update := bson.M{"$set": bson.M{
PaymentFields.Completed: true,
PaymentFields.UpdatedAt: time.Now(),
}}
if err := receiver.collection.FindOneAndUpdate(ctx, filter, update, options).Decode(&payment); err != nil {
receiver.logger.Error("failed to set payment complete on <SetPaymentComplete> of <PaymentRepository>",
zap.Error(err),
zap.String("paymentID", paymentID),
)
removeErr := errors.NewWithError(
fmt.Errorf("failed to set payment complete with <%s> on <SetPaymentComplete> of <PaymentRepository>: %w", paymentID, err),
errors.ErrInternalError,
)
if err == mongo.ErrNoDocuments {
return nil, removeErr.SetType(errors.ErrNotFound)
}
return nil, removeErr
}
return &payment, nil
}
func (receiver *PaymentRepository) Insert(ctx context.Context, payment *models.Payment) (*models.Payment, errors.Error) {
sanitizedPayment := payment.Sanitize()
result, err := receiver.collection.InsertOne(ctx, sanitizedPayment)
if err != nil {
receiver.logger.Error("failed to insert payment on <Insert> of <PaymentRepository>",
zap.Any("payment", sanitizedPayment),
zap.Error(err),
)
return nil, errors.NewWithError(
fmt.Errorf("failed to insert payment on <Insert> of <AccountRepository>: %w", err),
errors.ErrInternalError,
)
}
insertedID := result.InsertedID.(primitive.ObjectID).Hex()
sanitizedPayment.ID = insertedID
return sanitizedPayment, nil
}
func (receiver *PaymentRepository) SetPaymentStatus(ctx context.Context, paymentID string, status models.PaymentStatus) (*models.Payment, errors.Error) {
payment := models.Payment{}
options := options.FindOneAndUpdate().SetReturnDocument(options.After)
filter := bson.M{PaymentFields.PaymentID: paymentID}
update := bson.M{"$set": bson.M{
PaymentFields.Status: status,
PaymentFields.UpdatedAt: time.Now(),
}}
if err := receiver.collection.FindOneAndUpdate(ctx, filter, update, options).Decode(&payment); err != nil {
receiver.logger.Error("failed to set payment status on <SetPaymentStatus> of <PaymentRepository>",
zap.Error(err),
zap.String("paymentID", paymentID),
)
removeErr := errors.NewWithError(
fmt.Errorf("failed to set payment status with <%s> on <SetPaymentStatus> of <PaymentRepository>: %w", paymentID, err),
errors.ErrInternalError,
)
if err == mongo.ErrNoDocuments {
return nil, removeErr.SetType(errors.ErrNotFound)
}
return nil, removeErr
}
return &payment, nil
}