114 lines
3.3 KiB
Go
114 lines
3.3 KiB
Go
package store
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
|
|
"github.com/tech/sendico/fx/storage"
|
|
"github.com/tech/sendico/fx/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/mongo"
|
|
"go.uber.org/zap"
|
|
)
|
|
|
|
type currencyStore struct {
|
|
logger mlogger.Logger
|
|
repo repository.Repository
|
|
}
|
|
|
|
func NewCurrency(logger mlogger.Logger, db *mongo.Database) (storage.CurrencyStore, error) {
|
|
repo := repository.CreateMongoRepository(db, model.CurrenciesCollection)
|
|
|
|
index := &ri.Definition{
|
|
Keys: []ri.Key{
|
|
{Field: "code", Sort: ri.Asc},
|
|
},
|
|
Unique: true,
|
|
}
|
|
if err := repo.CreateIndex(index); err != nil {
|
|
logger.Error("Failed to ensure currencies index", zap.Error(err))
|
|
return nil, err
|
|
}
|
|
childLogger := logger.Named(model.CurrenciesCollection)
|
|
childLogger.Debug("Currency store initialised", zap.String("collection", model.CurrenciesCollection))
|
|
|
|
return ¤cyStore{
|
|
logger: childLogger,
|
|
repo: repo,
|
|
}, nil
|
|
}
|
|
|
|
func (c *currencyStore) Get(ctx context.Context, code string) (*model.Currency, error) {
|
|
if code == "" {
|
|
c.logger.Warn("Attempt to fetch currency with empty code")
|
|
return nil, merrors.InvalidArgument("currencyStore: empty code")
|
|
}
|
|
result := &model.Currency{}
|
|
if err := c.repo.FindOneByFilter(ctx, repository.Filter("code", code), result); err != nil {
|
|
if errors.Is(err, merrors.ErrNoData) {
|
|
c.logger.Debug("Currency not found", zap.String("code", code))
|
|
}
|
|
return nil, err
|
|
}
|
|
c.logger.Debug("Currency loaded", zap.String("code", code))
|
|
return result, nil
|
|
}
|
|
|
|
func (c *currencyStore) List(ctx context.Context, codes ...string) ([]*model.Currency, error) {
|
|
query := repository.Query()
|
|
if len(codes) > 0 {
|
|
values := make([]any, len(codes))
|
|
for i, code := range codes {
|
|
values[i] = code
|
|
}
|
|
query = query.In(repository.Field("code"), values...)
|
|
}
|
|
|
|
currencies := make([]*model.Currency, 0)
|
|
err := c.repo.FindManyByFilter(ctx, query, func(cur *mongo.Cursor) error {
|
|
doc := &model.Currency{}
|
|
if err := cur.Decode(doc); err != nil {
|
|
return err
|
|
}
|
|
currencies = append(currencies, doc)
|
|
return nil
|
|
})
|
|
if err != nil {
|
|
c.logger.Warn("Failed to list currencies", zap.Error(err))
|
|
return nil, err
|
|
}
|
|
c.logger.Debug("Listed currencies", zap.Int("count", len(currencies)))
|
|
return currencies, nil
|
|
}
|
|
|
|
func (c *currencyStore) Upsert(ctx context.Context, currency *model.Currency) error {
|
|
if currency == nil {
|
|
c.logger.Warn("Attempt to upsert nil currency")
|
|
return merrors.InvalidArgument("currencyStore: nil currency")
|
|
}
|
|
if currency.Code == "" {
|
|
c.logger.Warn("Attempt to upsert currency with empty code")
|
|
return merrors.InvalidArgument("currencyStore: empty code")
|
|
}
|
|
|
|
existing := &model.Currency{}
|
|
filter := repository.Filter("code", currency.Code)
|
|
if err := c.repo.FindOneByFilter(ctx, filter, existing); err != nil {
|
|
if errors.Is(err, merrors.ErrNoData) {
|
|
c.logger.Debug("Inserting new currency", zap.String("code", currency.Code))
|
|
return c.repo.Insert(ctx, currency, filter)
|
|
}
|
|
c.logger.Warn("Failed to fetch currency", zap.Error(err), zap.String("code", currency.Code))
|
|
return err
|
|
}
|
|
|
|
if existing.GetID() != nil {
|
|
currency.SetID(*existing.GetID())
|
|
}
|
|
c.logger.Debug("Updating currency", zap.String("code", currency.Code))
|
|
return c.repo.Update(ctx, currency)
|
|
}
|