package store import ( "context" "strings" storage "github.com/tech/sendico/gateway/mntx/storage" "github.com/tech/sendico/gateway/mntx/storage/model" "github.com/tech/sendico/pkg/db/repository" ri "github.com/tech/sendico/pkg/db/repository/index" "github.com/tech/sendico/pkg/merrors" "github.com/tech/sendico/pkg/mlogger" "go.mongodb.org/mongo-driver/v2/bson" "go.mongodb.org/mongo-driver/v2/mongo" "go.uber.org/zap" ) const ( payoutsCollection = "card_payouts" payoutIdemField = "idempotencyKey" payoutIdField = "payoutId" ) type Payouts struct { logger mlogger.Logger repository repository.Repository } func NewPayouts(logger mlogger.Logger, db *mongo.Database) (*Payouts, error) { if db == nil { return nil, merrors.InvalidArgument("mongo database is nil") } if logger == nil { logger = zap.NewNop() } logger = logger.Named("payouts").With(zap.String("collection", payoutsCollection)) repo := repository.CreateMongoRepository(db, payoutsCollection) if err := repo.CreateIndex(&ri.Definition{ Keys: []ri.Key{{Field: payoutIdemField, Sort: ri.Asc}}, Unique: true, }); err != nil { logger.Error("Failed to create payouts idempotency index", zap.Error(err), zap.String("index_field", payoutIdemField)) return nil, err } p := &Payouts{ logger: logger, repository: repo, } p.logger.Debug("Payouts store initialised") return p, nil } func (p *Payouts) findOneByField(ctx context.Context, field, value string) (*model.CardPayout, error) { var res model.CardPayout return &res, p.repository.FindOneByFilter(ctx, repository.Filter(field, value), &res) } func (p *Payouts) FindByIdempotencyKey(ctx context.Context, key string) (*model.CardPayout, error) { return p.findOneByField(ctx, payoutIdemField, key) } func (p *Payouts) FindByPaymentID(ctx context.Context, paymentID string) (*model.CardPayout, error) { return p.findOneByField(ctx, payoutIdField, paymentID) } func (p *Payouts) Upsert(ctx context.Context, record *model.CardPayout) error { if record == nil { p.logger.Warn("Invalid argument provided: nil record") return merrors.InvalidArgument("payout record is nil", "record") } record.OperationRef = strings.TrimSpace(record.OperationRef) record.PayoutID = strings.TrimSpace(record.PayoutID) record.CustomerID = strings.TrimSpace(record.CustomerID) record.ProviderCode = strings.TrimSpace(record.ProviderCode) record.ProviderPaymentID = strings.TrimSpace(record.ProviderPaymentID) if record.OperationRef == "" { p.logger.Warn("Invalid argument provided: operation reference missing") return merrors.InvalidArgument("operation ref is required", "operation_ref") } if record.ID == bson.NilObjectID { return p.repository.Insert(ctx, record, nil) } return p.repository.Update(ctx, record) } var _ storage.PayoutsStore = (*Payouts)(nil)