package payments import ( "context" db "git.sendico.io/tech/sxchnge/shared/database" deps "git.sendico.io/tech/sxchnge/shared/database/dependencies" "git.sendico.io/tech/sxchnge/shared/database/repository" "git.sendico.io/tech/sxchnge/shared/database/repository/builder" ri "git.sendico.io/tech/sxchnge/shared/database/repository/index" "git.sendico.io/tech/sxchnge/shared/database/source" "go.mongodb.org/mongo-driver/v2/bson" ) type Store interface { Create(context.Context, *Record) error Get(context.Context, bson.ObjectID, bson.ObjectID, string) (*Record, error) ByKey(context.Context, bson.ObjectID, string, string) (*Record, error) List(context.Context, bson.ObjectID, string) ([]Record, error) Authorize(context.Context, *Record, string) error Attach(context.Context, *Record, string) error } type mongoStore struct{ records repository.Repository } func OpenStore(factory db.Factory) (Store, error) { d, err := deps.ResolveDependencies(factory) if err != nil { return nil, err } r := repository.CreateRepository(source.Majority(d.Database), "payment_quotes") err = r.CreateIndex(&ri.Definition{Name: "customer_execution_key", Unique: true, Keys: []ri.Key{{Field: "customer", Sort: ri.Asc}, {Field: "namespace", Sort: ri.Asc}, {Field: "key", Sort: ri.Asc}}, PartialFilter: repository.Query().Comparison(repository.Field("key"), builder.Gt, "")}) if err != nil { return nil, err } if err = r.CreateIndex(&ri.Definition{Name: "provider_quote_unique", Unique: true, Keys: []ri.Key{{Field: "namespace", Sort: ri.Asc}, {Field: "providerQuote", Sort: ri.Asc}}, PartialFilter: repository.Query().Comparison(repository.Field("providerQuote"), builder.Gt, "")}); err != nil { return nil, err } return &mongoStore{r}, nil } func scope(customer bson.ObjectID, namespace string) repository.FilterQuery { return repository.Query().Filter(repository.Field("customer"), customer).Filter(repository.Field("namespace"), namespace) } func (s *mongoStore) Create(ctx context.Context, r *Record) error { return s.records.Insert(ctx, r, nil) } func (s *mongoStore) Get(ctx context.Context, id, customer bson.ObjectID, namespace string) (*Record, error) { r := &Record{} err := s.records.FindOneByFilter(ctx, scope(customer, namespace).Filter(repository.IDField(), id), r) return r, err } func (s *mongoStore) ByKey(ctx context.Context, customer bson.ObjectID, namespace, key string) (*Record, error) { r := &Record{} err := s.records.FindOneByFilter(ctx, scope(customer, namespace).Filter(repository.Field("key"), key), r) return r, err } func (s *mongoStore) List(ctx context.Context, customer bson.ObjectID, namespace string) ([]Record, error) { var rows []Record err := s.records.FindAllByFilter(ctx, scope(customer, namespace).Comparison(repository.Field("key"), builder.Gt, "").Sort(repository.Field("createdAt"), true), &rows) return rows, err } func (s *mongoStore) Authorize(ctx context.Context, r *Record, key string) error { matched, err := s.records.PatchOneByFilter(ctx, scope(r.Customer, r.Namespace).Filter(repository.IDField(), r.ID).Filter(repository.Field("key"), ""), repository.Patch().Set(repository.Field("key"), key), &Record{}) if err != nil { return err } if !matched { return Uncertain } return nil } func (s *mongoStore) Attach(ctx context.Context, r *Record, id string) error { matched, err := s.records.PatchOneByFilter(ctx, scope(r.Customer, r.Namespace).Filter(repository.IDField(), r.ID).Filter(repository.Field("payment"), ""), repository.Patch().Set(repository.Field("payment"), id), &Record{}) if err != nil { return err } if matched { return nil } current, err := s.Get(ctx, r.ID, r.Customer, r.Namespace) if err != nil { return err } if current.Payment != id { return Uncertain } return nil }