fixed ledger account name propagation when creating ledger account
This commit is contained in:
@@ -7,6 +7,7 @@ import (
|
||||
|
||||
"github.com/tech/sendico/ledger/storage"
|
||||
"github.com/tech/sendico/pkg/db/repository"
|
||||
"github.com/tech/sendico/pkg/db/repository/builder"
|
||||
ri "github.com/tech/sendico/pkg/db/repository/index"
|
||||
"github.com/tech/sendico/pkg/merrors"
|
||||
"github.com/tech/sendico/pkg/mlogger"
|
||||
@@ -24,6 +25,11 @@ type accountsStore struct {
|
||||
repo repository.Repository
|
||||
}
|
||||
|
||||
const (
|
||||
orgCurrencyRoleNonOperatingIndex = "org_currency_role_non_operating_unique"
|
||||
orgCurrencyRoleSystemOperatingName = "org_currency_role_system_operating_unique"
|
||||
)
|
||||
|
||||
func NewAccounts(logger mlogger.Logger, db *mongo.Database) (storage.AccountsStore, error) {
|
||||
repo := repository.CreateMongoRepository(db, mservice.LedgerAccounts)
|
||||
|
||||
@@ -41,7 +47,7 @@ func NewAccounts(logger mlogger.Logger, db *mongo.Database) (storage.AccountsSto
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Create compound index on organizationRef + currency + role (unique)
|
||||
// Keep role uniqueness for non-operating organization accounts.
|
||||
roleIndex := &ri.Definition{
|
||||
Keys: []ri.Key{
|
||||
{Field: "organizationRef", Sort: ri.Asc},
|
||||
@@ -49,16 +55,36 @@ func NewAccounts(logger mlogger.Logger, db *mongo.Database) (storage.AccountsSto
|
||||
{Field: "role", Sort: ri.Asc},
|
||||
},
|
||||
Unique: true,
|
||||
PartialFilter: repository.Filter(
|
||||
"scope",
|
||||
pkm.LedgerAccountScopeOrganization,
|
||||
),
|
||||
Name: orgCurrencyRoleNonOperatingIndex,
|
||||
PartialFilter: repository.Query().
|
||||
Filter(repository.Field("scope"), pkm.LedgerAccountScopeOrganization).
|
||||
Comparison(repository.Field("role"), builder.Ne, account_role.AccountRoleOperating),
|
||||
}
|
||||
if err := repo.CreateIndex(roleIndex); err != nil {
|
||||
logger.Error("Failed to ensure accounts role index", zap.Error(err))
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Ensure only one system-tagged operating role per organization/currency.
|
||||
systemOperatingRoleIndex := &ri.Definition{
|
||||
Keys: []ri.Key{
|
||||
{Field: "organizationRef", Sort: ri.Asc},
|
||||
{Field: "currency", Sort: ri.Asc},
|
||||
{Field: "role", Sort: ri.Asc},
|
||||
{Field: "metadata.system", Sort: ri.Asc},
|
||||
},
|
||||
Unique: true,
|
||||
Name: orgCurrencyRoleSystemOperatingName,
|
||||
PartialFilter: repository.Query().
|
||||
Filter(repository.Field("scope"), pkm.LedgerAccountScopeOrganization).
|
||||
Filter(repository.Field("role"), account_role.AccountRoleOperating).
|
||||
Filter(repository.Field("metadata.system"), "true"),
|
||||
}
|
||||
if err := repo.CreateIndex(systemOperatingRoleIndex); err != nil {
|
||||
logger.Error("Failed to ensure system operating role index", zap.Error(err))
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Create compound index on scope + systemPurpose + currency (unique) for system accounts
|
||||
systemIndex := &ri.Definition{
|
||||
Keys: []ri.Key{
|
||||
@@ -182,14 +208,34 @@ func (a *accountsStore) GetByRole(ctx context.Context, orgRef bson.ObjectID, cur
|
||||
return nil, merrors.InvalidArgument("accountsStore: empty role")
|
||||
}
|
||||
|
||||
result := &pkm.LedgerAccount{}
|
||||
limit := int64(1)
|
||||
|
||||
// Prefer topology/system-tagged account when present.
|
||||
systemQuery := repository.Query().
|
||||
Filter(repository.Field("organizationRef"), orgRef).
|
||||
Filter(repository.Field("currency"), currency).
|
||||
Filter(repository.Field("role"), role).
|
||||
Filter(repository.Field("scope"), pkm.LedgerAccountScopeOrganization).
|
||||
Filter(repository.Field("metadata.system"), "true").
|
||||
Limit(&limit)
|
||||
if err := a.repo.FindOneByFilter(ctx, systemQuery, result); err == nil {
|
||||
a.logger.Debug("System account loaded by role", mzap.ObjRef("accountRef", *result.GetID()),
|
||||
zap.String("currency", currency), zap.String("role", string(role)))
|
||||
return result, nil
|
||||
} else if !errors.Is(err, merrors.ErrNoData) {
|
||||
a.logger.Warn("Failed to get account by role", zap.Error(err), mzap.ObjRef("organization_ref", orgRef),
|
||||
zap.String("currency", currency), zap.String("role", string(role)))
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Fallback to any organization account with the role.
|
||||
query := repository.Query().
|
||||
Filter(repository.Field("organizationRef"), orgRef).
|
||||
Filter(repository.Field("currency"), currency).
|
||||
Filter(repository.Field("role"), role).
|
||||
Filter(repository.Field("scope"), pkm.LedgerAccountScopeOrganization).
|
||||
Limit(&limit)
|
||||
|
||||
result := &pkm.LedgerAccount{}
|
||||
if err := a.repo.FindOneByFilter(ctx, query, result); err != nil {
|
||||
if errors.Is(err, merrors.ErrNoData) {
|
||||
a.logger.Debug("Account not found by role", zap.String("currency", currency),
|
||||
|
||||
Reference in New Issue
Block a user