fixed doc env vars + mongo v2 migration

This commit is contained in:
Stephan D
2026-01-31 00:26:42 +01:00
parent cbb7bd8ba6
commit 1aa7e287fb
356 changed files with 1705 additions and 1729 deletions

View File

@@ -7,7 +7,7 @@ import (
"time"
"github.com/tech/sendico/pkg/model"
"go.mongodb.org/mongo-driver/bson/primitive"
"go.mongodb.org/mongo-driver/v2/bson"
)
// AccountType controls normal balance side.
@@ -35,7 +35,7 @@ type Account struct {
Currency string `bson:"currency,omitempty" json:"currency,omitempty"`
// Managing entity in your platform (not legal owner).
OrganizationRef *primitive.ObjectID `bson:"organizationRef,omitempty" json:"organizationRef,omitempty"`
OrganizationRef *bson.ObjectID `bson:"organizationRef,omitempty" json:"organizationRef,omitempty"`
// Posting policy & lifecycle
AllowNegative bool `bson:"allowNegative" json:"allowNegative"`
@@ -131,7 +131,7 @@ func (a *Account) BalanceSide() int {
}
// CloseOwnershipPeriod sets the To date for the first matching active ownership.
func (a *Account) CloseOwnershipPeriod(partyID primitive.ObjectID, role OwnershipRole, to time.Time) bool {
func (a *Account) CloseOwnershipPeriod(partyID bson.ObjectID, role OwnershipRole, to time.Time) bool {
for i := range a.Ownerships {
o := &a.Ownerships[i]
if o.OwnerPartyRef == partyID && o.Role == role && o.ActiveAt(to) {

View File

@@ -1,17 +1,17 @@
package ledger
import (
"github.com/shopspring/decimal"
"github.com/tech/sendico/pkg/model"
"github.com/tech/sendico/pkg/mservice"
"github.com/shopspring/decimal"
"go.mongodb.org/mongo-driver/bson/primitive"
"go.mongodb.org/mongo-driver/v2/bson"
)
type AccountBalance struct {
model.PermissionBound `bson:",inline" json:",inline"`
LedgerAccountRef primitive.ObjectID `bson:"ledgerAccountRef" json:"ledgerAccountRef"` // unique
Balance decimal.Decimal `bson:"balance" json:"balance"`
Version int64 `bson:"version" json:"version"` // for optimistic locking
LedgerAccountRef bson.ObjectID `bson:"ledgerAccountRef" json:"ledgerAccountRef"` // unique
Balance decimal.Decimal `bson:"balance" json:"balance"`
Version int64 `bson:"version" json:"version"` // for optimistic locking
}
func (a *AccountBalance) Collection() string {

View File

@@ -6,7 +6,7 @@ import (
"github.com/tech/sendico/pkg/model"
"github.com/tech/sendico/pkg/mservice"
"go.mongodb.org/mongo-driver/bson/primitive"
"go.mongodb.org/mongo-driver/v2/bson"
)
// EntryType is a closed set of journal entry kinds.
@@ -35,10 +35,10 @@ type JournalEntry struct {
Version int64 `bson:"version" json:"version"`
// Denormalized set of all affected ledger accounts (for entry-level access control & queries)
LedgerAccountRefs []primitive.ObjectID `bson:"ledgerAccountRefs,omitempty" json:"ledgerAccountRefs,omitempty"`
LedgerAccountRefs []bson.ObjectID `bson:"ledgerAccountRefs,omitempty" json:"ledgerAccountRefs,omitempty"`
// Optional backlink for reversals
ReversalOf *primitive.ObjectID `bson:"reversalOf,omitempty" json:"reversalOf,omitempty"`
ReversalOf *bson.ObjectID `bson:"reversalOf,omitempty" json:"reversalOf,omitempty"`
}
func (j *JournalEntry) Collection() string {

View File

@@ -3,7 +3,7 @@ package ledger
import (
"time"
"go.mongodb.org/mongo-driver/bson/primitive"
"go.mongodb.org/mongo-driver/v2/bson"
)
// OwnershipRole captures legal roles (not permissions).
@@ -17,11 +17,11 @@ const (
)
type Ownership struct {
OwnerPartyRef primitive.ObjectID `bson:"ownerPartyRef" json:"ownerPartyRef"`
Role OwnershipRole `bson:"role" json:"role"`
SharePct *float64 `bson:"sharePct,omitempty" json:"sharePct,omitempty"` // 0..100; nil = unspecified
From time.Time `bson:"effectiveFrom" json:"effectiveFrom"`
To *time.Time `bson:"effectiveTo,omitempty" json:"effectiveTo,omitempty"` // active if t < To; nil = open
OwnerPartyRef bson.ObjectID `bson:"ownerPartyRef" json:"ownerPartyRef"`
Role OwnershipRole `bson:"role" json:"role"`
SharePct *float64 `bson:"sharePct,omitempty" json:"sharePct,omitempty"` // 0..100; nil = unspecified
From time.Time `bson:"effectiveFrom" json:"effectiveFrom"`
To *time.Time `bson:"effectiveTo,omitempty" json:"effectiveTo,omitempty"` // active if t < To; nil = open
}
func (o *Ownership) Validate() error {

View File

@@ -6,7 +6,7 @@ import (
"github.com/tech/sendico/pkg/model"
"github.com/tech/sendico/pkg/mservice"
"go.mongodb.org/mongo-driver/bson/primitive"
"go.mongodb.org/mongo-driver/v2/bson"
)
// PartyKind (string-backed enum) — readable in BSON/JSON, safe in Go.
@@ -39,10 +39,10 @@ func (k *PartyKind) UnmarshalJSON(b []byte) error {
type Party struct {
model.PermissionBound `bson:",inline" json:",inline"`
Kind PartyKind `bson:"kind" json:"kind"`
Name string `bson:"name" json:"name"`
UserRef *primitive.ObjectID `bson:"userRef,omitempty" json:"userRef,omitempty"` // internal user, if applicable
OrganizationRef *primitive.ObjectID `bson:"organizationRef,omitempty" json:"organizationRef,omitempty"` // internal org, if applicable
Kind PartyKind `bson:"kind" json:"kind"`
Name string `bson:"name" json:"name"`
UserRef *bson.ObjectID `bson:"userRef,omitempty" json:"userRef,omitempty"` // internal user, if applicable
OrganizationRef *bson.ObjectID `bson:"organizationRef,omitempty" json:"organizationRef,omitempty"` // internal org, if applicable
// add your own fields here if needed (KYC flags, etc.)
}

View File

@@ -2,11 +2,11 @@
package ledger
import (
"github.com/shopspring/decimal"
"github.com/tech/sendico/pkg/db/storable"
"github.com/tech/sendico/pkg/model"
"github.com/tech/sendico/pkg/mservice"
"github.com/shopspring/decimal"
"go.mongodb.org/mongo-driver/bson/primitive"
"go.mongodb.org/mongo-driver/v2/bson"
)
// LineType is a closed set of posting line roles within an entry.
@@ -22,8 +22,8 @@ const (
type PostingLine struct {
storable.Base `bson:",inline" json:",inline"`
JournalEntryRef primitive.ObjectID `bson:"journalEntryRef" json:"journalEntryRef"`
LedgerAccountRef primitive.ObjectID `bson:"ledgerAccountRef" json:"ledgerAccountRef"`
JournalEntryRef bson.ObjectID `bson:"journalEntryRef" json:"journalEntryRef"`
LedgerAccountRef bson.ObjectID `bson:"ledgerAccountRef" json:"ledgerAccountRef"`
// Amount sign convention: positive = credit, negative = debit
Amount decimal.Decimal `bson:"amount" json:"amount"`

View File

@@ -14,14 +14,14 @@ import (
"github.com/tech/sendico/pkg/mutil/mzap"
describablev1 "github.com/tech/sendico/pkg/proto/common/describable/v1"
ledgerv1 "github.com/tech/sendico/pkg/proto/ledger/v1"
"go.mongodb.org/mongo-driver/bson/primitive"
"go.mongodb.org/mongo-driver/v2/bson"
"go.uber.org/zap"
"google.golang.org/protobuf/types/known/timestamppb"
)
// createAccountParams holds validated and normalized fields from a CreateAccountRequest.
type createAccountParams struct {
orgRef primitive.ObjectID
orgRef bson.ObjectID
currency string
modelType pmodel.LedgerAccountType
modelStatus pmodel.LedgerAccountStatus
@@ -104,7 +104,7 @@ func (s *Service) createAccountResponder(_ context.Context, req *ledgerv1.Create
}
// resolveTopologyAccount ensures ledger topology is initialized and returns the system account for the given role.
func (s *Service) resolveTopologyAccount(ctx context.Context, orgRef primitive.ObjectID, currency string, role pmodel.AccountRole) (*ledgerv1.CreateAccountResponse, error) {
func (s *Service) resolveTopologyAccount(ctx context.Context, orgRef bson.ObjectID, currency string, role pmodel.AccountRole) (*ledgerv1.CreateAccountResponse, error) {
if err := s.ensureLedgerTopology(ctx, orgRef, currency); err != nil {
recordAccountOperation("create", "error")
return nil, err
@@ -142,7 +142,7 @@ func (s *Service) persistNewAccount(ctx context.Context, p createAccountParams,
const maxCreateAttempts = 3
for attempt := 0; attempt < maxCreateAttempts; attempt++ {
accountID := primitive.NewObjectID()
accountID := bson.NewObjectID()
account := buildNewAccount(p, metadata, describable, ownerRef, req.GetAllowNegative(), accountID)
err := s.storage.Accounts().Create(ctx, account)
@@ -180,7 +180,7 @@ func (s *Service) persistNewAccount(ctx context.Context, p createAccountParams,
}
// parseOwnerRef parses an optional owner reference string into an ObjectID pointer.
func parseOwnerRef(ownerRefStr string) (*primitive.ObjectID, error) {
func parseOwnerRef(ownerRefStr string) (*bson.ObjectID, error) {
if ownerRefStr == "" {
return nil, nil
}
@@ -192,7 +192,7 @@ func parseOwnerRef(ownerRefStr string) (*primitive.ObjectID, error) {
}
// buildNewAccount constructs a LedgerAccount model from validated parameters.
func buildNewAccount(p createAccountParams, metadata map[string]string, describable *pmodel.Describable, ownerRef *primitive.ObjectID, allowNegative bool, accountRef primitive.ObjectID) *pmodel.LedgerAccount {
func buildNewAccount(p createAccountParams, metadata map[string]string, describable *pmodel.Describable, ownerRef *bson.ObjectID, allowNegative bool, accountRef bson.ObjectID) *pmodel.LedgerAccount {
account := &pmodel.LedgerAccount{
AccountCode: generateAccountCode(p.modelType, p.currency, accountRef),
Currency: p.currency,
@@ -353,14 +353,14 @@ func toProtoAccount(account *pmodel.LedgerAccount) *ledgerv1.LedgerAccount {
}
}
func objectIDHex(id primitive.ObjectID) string {
func objectIDHex(id bson.ObjectID) string {
if id.IsZero() {
return ""
}
return id.Hex()
}
func objectIDPtrHex(id *primitive.ObjectID) string {
func objectIDPtrHex(id *bson.ObjectID) string {
if id == nil || id.IsZero() {
return ""
}
@@ -413,11 +413,11 @@ func describableToProto(desc pmodel.Describable) *describablev1.Describable {
}
}
func (s *Service) ensureSettlementAccount(ctx context.Context, orgRef primitive.ObjectID, currency string) (*pmodel.LedgerAccount, error) {
func (s *Service) ensureSettlementAccount(ctx context.Context, orgRef bson.ObjectID, currency string) (*pmodel.LedgerAccount, error) {
return s.ensureRoleAccount(ctx, orgRef, currency, pmodel.AccountRoleSettlement)
}
func generateAccountCode(accountType pmodel.LedgerAccountType, currency string, id primitive.ObjectID) string {
func generateAccountCode(accountType pmodel.LedgerAccountType, currency string, id bson.ObjectID) string {
typePart := strings.ToLower(strings.TrimSpace(string(accountType)))
if typePart == "" {
typePart = "account"

View File

@@ -6,7 +6,7 @@ import (
"testing"
"github.com/stretchr/testify/require"
"go.mongodb.org/mongo-driver/bson/primitive"
"go.mongodb.org/mongo-driver/v2/bson"
"go.uber.org/zap"
"github.com/tech/sendico/ledger/storage"
@@ -45,7 +45,7 @@ func (s *accountStoreStub) Create(_ context.Context, account *pmodel.LedgerAccou
}
if account.GetID() == nil || account.GetID().IsZero() {
account.SetID(primitive.NewObjectID())
account.SetID(bson.NewObjectID())
}
account.CreatedAt = account.CreatedAt.UTC()
@@ -55,18 +55,18 @@ func (s *accountStoreStub) Create(_ context.Context, account *pmodel.LedgerAccou
return nil
}
func (s *accountStoreStub) GetByAccountCode(_ context.Context, _ primitive.ObjectID, _ string, _ string) (*pmodel.LedgerAccount, error) {
func (s *accountStoreStub) GetByAccountCode(_ context.Context, _ bson.ObjectID, _ string, _ string) (*pmodel.LedgerAccount, error) {
if s.existingErr != nil {
return nil, s.existingErr
}
return s.existing, nil
}
func (s *accountStoreStub) Get(context.Context, primitive.ObjectID) (*pmodel.LedgerAccount, error) {
func (s *accountStoreStub) Get(context.Context, bson.ObjectID) (*pmodel.LedgerAccount, error) {
return nil, storage.ErrAccountNotFound
}
func (s *accountStoreStub) GetByRole(_ context.Context, orgRef primitive.ObjectID, currency string, role pmodel.AccountRole) (*pmodel.LedgerAccount, error) {
func (s *accountStoreStub) GetByRole(_ context.Context, orgRef bson.ObjectID, currency string, role pmodel.AccountRole) (*pmodel.LedgerAccount, error) {
if s.existingByRole != nil {
if acc, ok := s.existingByRole[role]; ok {
return acc, nil
@@ -84,7 +84,7 @@ func (s *accountStoreStub) GetSystemAccount(context.Context, pmodel.SystemAccoun
return nil, storage.ErrAccountNotFound
}
func (s *accountStoreStub) GetDefaultSettlement(context.Context, primitive.ObjectID, string) (*pmodel.LedgerAccount, error) {
func (s *accountStoreStub) GetDefaultSettlement(context.Context, bson.ObjectID, string) (*pmodel.LedgerAccount, error) {
if s.defaultErr != nil {
return nil, s.defaultErr
}
@@ -94,11 +94,11 @@ func (s *accountStoreStub) GetDefaultSettlement(context.Context, primitive.Objec
return nil, storage.ErrAccountNotFound
}
func (s *accountStoreStub) ListByOrganization(context.Context, primitive.ObjectID, *storage.AccountsFilter, int, int) ([]*pmodel.LedgerAccount, error) {
func (s *accountStoreStub) ListByOrganization(context.Context, bson.ObjectID, *storage.AccountsFilter, int, int) ([]*pmodel.LedgerAccount, error) {
return nil, nil
}
func (s *accountStoreStub) UpdateStatus(context.Context, primitive.ObjectID, pmodel.LedgerAccountStatus) error {
func (s *accountStoreStub) UpdateStatus(context.Context, bson.ObjectID, pmodel.LedgerAccountStatus) error {
return nil
}
@@ -116,7 +116,7 @@ func (r *repositoryStub) Outbox() storage.OutboxStore { return n
func TestCreateAccountResponder_Success(t *testing.T) {
t.Parallel()
orgRef := primitive.NewObjectID()
orgRef := bson.NewObjectID()
accountStore := &accountStoreStub{}
svc := &Service{
@@ -161,7 +161,7 @@ func TestCreateAccountResponder_Success(t *testing.T) {
func TestCreateAccountResponder_AutoCreatesSettlementAccount(t *testing.T) {
t.Parallel()
orgRef := primitive.NewObjectID()
orgRef := bson.NewObjectID()
accountStore := &accountStoreStub{}
svc := &Service{
@@ -237,7 +237,7 @@ func TestCreateAccountResponder_AutoCreatesSettlementAccount(t *testing.T) {
func TestCreateAccountResponder_RetriesOnConflict(t *testing.T) {
t.Parallel()
orgRef := primitive.NewObjectID()
orgRef := bson.NewObjectID()
accountStore := &accountStoreStub{
// first create attempt returns conflict, second succeeds
createErrs: []error{merrors.DataConflict("duplicate")},
@@ -292,7 +292,7 @@ func TestCreateAccountResponder_InvalidAccountType(t *testing.T) {
// AccountType missing => must fail
req := &ledgerv1.CreateAccountRequest{
OrganizationRef: primitive.NewObjectID().Hex(),
OrganizationRef: bson.NewObjectID().Hex(),
Currency: "USD",
}

View File

@@ -18,7 +18,7 @@ import (
pmodel "github.com/tech/sendico/pkg/model"
moneyv1 "github.com/tech/sendico/pkg/proto/common/money/v1"
ledgerv1 "github.com/tech/sendico/pkg/proto/ledger/v1"
"go.mongodb.org/mongo-driver/bson/primitive"
"go.mongodb.org/mongo-driver/v2/bson"
"go.uber.org/zap"
)
@@ -50,16 +50,16 @@ func (r *memoryRepository) Outbox() storage.OutboxStore { return
func (r *memoryRepository) TransactionFactory() transaction.Factory { return r.txFactory }
type memoryAccountsStore struct {
records map[primitive.ObjectID]*pmodel.LedgerAccount
records map[bson.ObjectID]*pmodel.LedgerAccount
systemByPurposeKey map[string]*pmodel.LedgerAccount
}
func (s *memoryAccountsStore) Create(_ context.Context, account *pmodel.LedgerAccount) error {
if account.GetID() == nil || account.GetID().IsZero() {
account.SetID(primitive.NewObjectID())
account.SetID(bson.NewObjectID())
}
if s.records == nil {
s.records = make(map[primitive.ObjectID]*pmodel.LedgerAccount)
s.records = make(map[bson.ObjectID]*pmodel.LedgerAccount)
}
s.records[*account.GetID()] = account
if account.SystemPurpose != nil {
@@ -72,7 +72,7 @@ func (s *memoryAccountsStore) Create(_ context.Context, account *pmodel.LedgerAc
return nil
}
func (s *memoryAccountsStore) Get(_ context.Context, accountRef primitive.ObjectID) (*pmodel.LedgerAccount, error) {
func (s *memoryAccountsStore) Get(_ context.Context, accountRef bson.ObjectID) (*pmodel.LedgerAccount, error) {
if s.records == nil {
return nil, storage.ErrAccountNotFound
}
@@ -82,11 +82,11 @@ func (s *memoryAccountsStore) Get(_ context.Context, accountRef primitive.Object
return nil, storage.ErrAccountNotFound
}
func (s *memoryAccountsStore) GetByAccountCode(context.Context, primitive.ObjectID, string, string) (*pmodel.LedgerAccount, error) {
func (s *memoryAccountsStore) GetByAccountCode(context.Context, bson.ObjectID, string, string) (*pmodel.LedgerAccount, error) {
return nil, merrors.NotImplemented("get by code")
}
func (s *memoryAccountsStore) GetByRole(context.Context, primitive.ObjectID, string, pmodel.AccountRole) (*pmodel.LedgerAccount, error) {
func (s *memoryAccountsStore) GetByRole(context.Context, bson.ObjectID, string, pmodel.AccountRole) (*pmodel.LedgerAccount, error) {
return nil, merrors.NotImplemented("get by role")
}
@@ -101,15 +101,15 @@ func (s *memoryAccountsStore) GetSystemAccount(_ context.Context, purpose pmodel
return nil, storage.ErrAccountNotFound
}
func (s *memoryAccountsStore) GetDefaultSettlement(context.Context, primitive.ObjectID, string) (*pmodel.LedgerAccount, error) {
func (s *memoryAccountsStore) GetDefaultSettlement(context.Context, bson.ObjectID, string) (*pmodel.LedgerAccount, error) {
return nil, merrors.NotImplemented("get default settlement")
}
func (s *memoryAccountsStore) ListByOrganization(context.Context, primitive.ObjectID, *storage.AccountsFilter, int, int) ([]*pmodel.LedgerAccount, error) {
func (s *memoryAccountsStore) ListByOrganization(context.Context, bson.ObjectID, *storage.AccountsFilter, int, int) ([]*pmodel.LedgerAccount, error) {
return nil, merrors.NotImplemented("list by organization")
}
func (s *memoryAccountsStore) UpdateStatus(context.Context, primitive.ObjectID, pmodel.LedgerAccountStatus) error {
func (s *memoryAccountsStore) UpdateStatus(context.Context, bson.ObjectID, pmodel.LedgerAccountStatus) error {
return merrors.NotImplemented("update status")
}
@@ -136,7 +136,7 @@ type memoryJournalEntriesStore struct {
func (s *memoryJournalEntriesStore) Create(_ context.Context, entry *model.JournalEntry) error {
if entry.GetID() == nil || entry.GetID().IsZero() {
entry.SetID(primitive.NewObjectID())
entry.SetID(bson.NewObjectID())
}
if s.byKey == nil {
s.byKey = make(map[string]*model.JournalEntry)
@@ -146,11 +146,11 @@ func (s *memoryJournalEntriesStore) Create(_ context.Context, entry *model.Journ
return nil
}
func (s *memoryJournalEntriesStore) Get(context.Context, primitive.ObjectID) (*model.JournalEntry, error) {
func (s *memoryJournalEntriesStore) Get(context.Context, bson.ObjectID) (*model.JournalEntry, error) {
return nil, merrors.NotImplemented("get entry")
}
func (s *memoryJournalEntriesStore) GetByIdempotencyKey(_ context.Context, orgRef primitive.ObjectID, key string) (*model.JournalEntry, error) {
func (s *memoryJournalEntriesStore) GetByIdempotencyKey(_ context.Context, orgRef bson.ObjectID, key string) (*model.JournalEntry, error) {
if s.byKey == nil {
return nil, storage.ErrJournalEntryNotFound
}
@@ -161,7 +161,7 @@ func (s *memoryJournalEntriesStore) GetByIdempotencyKey(_ context.Context, orgRe
return entry, nil
}
func (s *memoryJournalEntriesStore) ListByOrganization(context.Context, primitive.ObjectID, int, int) ([]*model.JournalEntry, error) {
func (s *memoryJournalEntriesStore) ListByOrganization(context.Context, bson.ObjectID, int, int) ([]*model.JournalEntry, error) {
return nil, merrors.NotImplemented("list entries")
}
@@ -174,19 +174,19 @@ func (s *memoryPostingLinesStore) CreateMany(_ context.Context, lines []*model.P
return nil
}
func (s *memoryPostingLinesStore) ListByJournalEntry(context.Context, primitive.ObjectID) ([]*model.PostingLine, error) {
func (s *memoryPostingLinesStore) ListByJournalEntry(context.Context, bson.ObjectID) ([]*model.PostingLine, error) {
return nil, merrors.NotImplemented("list lines by entry")
}
func (s *memoryPostingLinesStore) ListByAccount(context.Context, primitive.ObjectID, int, int) ([]*model.PostingLine, error) {
func (s *memoryPostingLinesStore) ListByAccount(context.Context, bson.ObjectID, int, int) ([]*model.PostingLine, error) {
return nil, merrors.NotImplemented("list lines by account")
}
type memoryBalancesStore struct {
records map[primitive.ObjectID]*model.AccountBalance
records map[bson.ObjectID]*model.AccountBalance
}
func (s *memoryBalancesStore) Get(_ context.Context, accountRef primitive.ObjectID) (*model.AccountBalance, error) {
func (s *memoryBalancesStore) Get(_ context.Context, accountRef bson.ObjectID) (*model.AccountBalance, error) {
if s.records == nil {
return nil, storage.ErrBalanceNotFound
}
@@ -199,14 +199,14 @@ func (s *memoryBalancesStore) Get(_ context.Context, accountRef primitive.Object
func (s *memoryBalancesStore) Upsert(_ context.Context, balance *model.AccountBalance) error {
if s.records == nil {
s.records = make(map[primitive.ObjectID]*model.AccountBalance)
s.records = make(map[bson.ObjectID]*model.AccountBalance)
}
copied := *balance
s.records[balance.AccountRef] = &copied
return nil
}
func (s *memoryBalancesStore) IncrementBalance(context.Context, primitive.ObjectID, string) error {
func (s *memoryBalancesStore) IncrementBalance(context.Context, bson.ObjectID, string) error {
return merrors.NotImplemented("increment balance")
}
@@ -216,13 +216,13 @@ func (memoryOutboxStore) Create(context.Context, *model.OutboxEvent) error { ret
func (memoryOutboxStore) ListPending(context.Context, int) ([]*model.OutboxEvent, error) {
return nil, merrors.NotImplemented("list outbox")
}
func (memoryOutboxStore) MarkSent(context.Context, primitive.ObjectID, time.Time) error {
func (memoryOutboxStore) MarkSent(context.Context, bson.ObjectID, time.Time) error {
return merrors.NotImplemented("mark sent")
}
func (memoryOutboxStore) MarkFailed(context.Context, primitive.ObjectID) error {
func (memoryOutboxStore) MarkFailed(context.Context, bson.ObjectID) error {
return merrors.NotImplemented("mark failed")
}
func (memoryOutboxStore) IncrementAttempts(context.Context, primitive.ObjectID) error {
func (memoryOutboxStore) IncrementAttempts(context.Context, bson.ObjectID) error {
return merrors.NotImplemented("increment attempts")
}
@@ -242,9 +242,9 @@ func newTestService() (*Service, *memoryRepository) {
return svc, repo
}
func newOrgAccount(orgRef primitive.ObjectID, currency string, role pmodel.AccountRole) *pmodel.LedgerAccount {
func newOrgAccount(orgRef bson.ObjectID, currency string, role pmodel.AccountRole) *pmodel.LedgerAccount {
account := &pmodel.LedgerAccount{
AccountCode: "test:" + strings.ToLower(currency) + ":" + primitive.NewObjectID().Hex(),
AccountCode: "test:" + strings.ToLower(currency) + ":" + bson.NewObjectID().Hex(),
Currency: currency,
AccountType: pmodel.LedgerAccountTypeAsset,
Status: pmodel.LedgerAccountStatusActive,
@@ -256,7 +256,7 @@ func newOrgAccount(orgRef primitive.ObjectID, currency string, role pmodel.Accou
return account
}
func balanceString(t *testing.T, balances *memoryBalancesStore, accountID primitive.ObjectID) string {
func balanceString(t *testing.T, balances *memoryBalancesStore, accountID bson.ObjectID) string {
t.Helper()
bal, err := balances.Get(context.Background(), accountID)
if errors.Is(err, storage.ErrBalanceNotFound) {
@@ -266,7 +266,7 @@ func balanceString(t *testing.T, balances *memoryBalancesStore, accountID primit
return bal.Balance
}
func balanceDecimal(t *testing.T, balances *memoryBalancesStore, accountID primitive.ObjectID) decimal.Decimal {
func balanceDecimal(t *testing.T, balances *memoryBalancesStore, accountID bson.ObjectID) decimal.Decimal {
t.Helper()
bal, err := balances.Get(context.Background(), accountID)
if errors.Is(err, storage.ErrBalanceNotFound) {
@@ -289,7 +289,7 @@ func TestExternalCreditAndDebit(t *testing.T) {
svc, repo := newTestService()
require.NoError(t, svc.ensureSystemAccounts(ctx))
orgRef := primitive.NewObjectID()
orgRef := bson.NewObjectID()
pending := newOrgAccount(orgRef, "USD", pmodel.AccountRolePending)
require.NoError(t, repo.accounts.Create(ctx, pending))
@@ -333,7 +333,7 @@ func TestExternalCreditCurrencyMismatch(t *testing.T) {
svc, repo := newTestService()
require.NoError(t, svc.ensureSystemAccounts(ctx))
orgRef := primitive.NewObjectID()
orgRef := bson.NewObjectID()
pending := newOrgAccount(orgRef, "USD", pmodel.AccountRolePending)
require.NoError(t, repo.accounts.Create(ctx, pending))
@@ -361,7 +361,7 @@ func TestExternalOperationsRejectSystemScopeTargets(t *testing.T) {
svc, repo := newTestService()
require.NoError(t, svc.ensureSystemAccounts(ctx))
orgRef := primitive.NewObjectID()
orgRef := bson.NewObjectID()
source, err := repo.accounts.GetSystemAccount(ctx, pmodel.SystemAccountPurposeExternalSource, "USD")
require.NoError(t, err)
sink, err := repo.accounts.GetSystemAccount(ctx, pmodel.SystemAccountPurposeExternalSink, "USD")
@@ -395,7 +395,7 @@ func TestExternalFlowInvariant(t *testing.T) {
svc, repo := newTestService()
require.NoError(t, svc.ensureSystemAccounts(ctx))
orgRef := primitive.NewObjectID()
orgRef := bson.NewObjectID()
pending := newOrgAccount(orgRef, "USD", pmodel.AccountRolePending)
transit := newOrgAccount(orgRef, "USD", pmodel.AccountRoleTransit)
require.NoError(t, repo.accounts.Create(ctx, pending))
@@ -441,7 +441,7 @@ func TestExternalInvariantRandomSequence(t *testing.T) {
svc, repo := newTestService()
require.NoError(t, svc.ensureSystemAccounts(ctx))
orgRef := primitive.NewObjectID()
orgRef := bson.NewObjectID()
pending := newOrgAccount(orgRef, "USD", pmodel.AccountRolePending)
transit := newOrgAccount(orgRef, "USD", pmodel.AccountRoleTransit)
require.NoError(t, repo.accounts.Create(ctx, pending))

View File

@@ -9,18 +9,18 @@ import (
"github.com/tech/sendico/pkg/merrors"
moneyv1 "github.com/tech/sendico/pkg/proto/common/money/v1"
ledgerv1 "github.com/tech/sendico/pkg/proto/ledger/v1"
"go.mongodb.org/mongo-driver/bson/primitive"
"go.mongodb.org/mongo-driver/v2/bson"
"google.golang.org/protobuf/types/known/timestamppb"
)
// parseObjectID converts a hex string to ObjectID
func parseObjectID(hexID string) (primitive.ObjectID, error) {
func parseObjectID(hexID string) (bson.ObjectID, error) {
if hexID == "" {
return primitive.NilObjectID, merrors.InvalidArgument("empty object ID")
return bson.NilObjectID, merrors.InvalidArgument("empty object ID")
}
oid, err := primitive.ObjectIDFromHex(hexID)
oid, err := bson.ObjectIDFromHex(hexID)
if err != nil {
return primitive.NilObjectID, merrors.InvalidArgument(fmt.Sprintf("invalid object ID: %v", err))
return bson.NilObjectID, merrors.InvalidArgument(fmt.Sprintf("invalid object ID: %v", err))
}
return oid, nil
}

View File

@@ -10,13 +10,13 @@ import (
"github.com/tech/sendico/ledger/storage/model"
moneyv1 "github.com/tech/sendico/pkg/proto/common/money/v1"
ledgerv1 "github.com/tech/sendico/pkg/proto/ledger/v1"
"go.mongodb.org/mongo-driver/bson/primitive"
"go.mongodb.org/mongo-driver/v2/bson"
"google.golang.org/protobuf/types/known/timestamppb"
)
func TestParseObjectID(t *testing.T) {
t.Run("ValidObjectID", func(t *testing.T) {
validID := primitive.NewObjectID()
validID := bson.NewObjectID()
result, err := parseObjectID(validID.Hex())
require.NoError(t, err)
@@ -27,7 +27,7 @@ func TestParseObjectID(t *testing.T) {
result, err := parseObjectID("")
require.Error(t, err)
assert.Equal(t, primitive.NilObjectID, result)
assert.Equal(t, bson.NilObjectID, result)
assert.Contains(t, err.Error(), "empty object ID")
})
@@ -35,7 +35,7 @@ func TestParseObjectID(t *testing.T) {
result, err := parseObjectID("invalid-hex-string")
require.Error(t, err)
assert.Equal(t, primitive.NilObjectID, result)
assert.Equal(t, bson.NilObjectID, result)
assert.Contains(t, err.Error(), "invalid object ID")
})
@@ -43,7 +43,7 @@ func TestParseObjectID(t *testing.T) {
result, err := parseObjectID("abc123")
require.Error(t, err)
assert.Equal(t, primitive.NilObjectID, result)
assert.Equal(t, bson.NilObjectID, result)
})
}
@@ -145,7 +145,7 @@ func TestValidatePostingLines(t *testing.T) {
t.Run("ValidPostingLines", func(t *testing.T) {
lines := []*ledgerv1.PostingLine{
{
LedgerAccountRef: primitive.NewObjectID().Hex(),
LedgerAccountRef: bson.NewObjectID().Hex(),
Money: &moneyv1.Money{
Amount: "10.00",
Currency: "USD",
@@ -192,7 +192,7 @@ func TestValidatePostingLines(t *testing.T) {
t.Run("NilMoney", func(t *testing.T) {
lines := []*ledgerv1.PostingLine{
{
LedgerAccountRef: primitive.NewObjectID().Hex(),
LedgerAccountRef: bson.NewObjectID().Hex(),
Money: nil,
},
}
@@ -206,7 +206,7 @@ func TestValidatePostingLines(t *testing.T) {
t.Run("MainLineType", func(t *testing.T) {
lines := []*ledgerv1.PostingLine{
{
LedgerAccountRef: primitive.NewObjectID().Hex(),
LedgerAccountRef: bson.NewObjectID().Hex(),
Money: &moneyv1.Money{
Amount: "10.00",
Currency: "USD",

View File

@@ -12,7 +12,7 @@ import (
"github.com/tech/sendico/pkg/merrors"
pmodel "github.com/tech/sendico/pkg/model"
"github.com/tech/sendico/pkg/mservice"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/v2/bson"
)
// CheckExternalInvariant validates the external_source/external_sink invariant for a currency.

View File

@@ -9,7 +9,7 @@ import (
"github.com/tech/sendico/pkg/merrors"
"github.com/tech/sendico/pkg/mutil/mzap"
ledgerv1 "github.com/tech/sendico/pkg/proto/ledger/v1"
"go.mongodb.org/mongo-driver/bson/primitive"
"go.mongodb.org/mongo-driver/v2/bson"
"go.uber.org/zap"
)
@@ -35,7 +35,7 @@ func (s *Service) listAccountsResponder(_ context.Context, req *ledgerv1.ListAcc
var filter *storage.AccountsFilter
if req.GetOwnerRefFilter() != nil {
ownerRefStr := strings.TrimSpace(req.GetOwnerRefFilter().GetValue())
var ownerRef primitive.ObjectID
var ownerRef bson.ObjectID
if ownerRefStr != "" {
ownerRef, err = parseObjectID(ownerRefStr)
if err != nil {

View File

@@ -12,7 +12,7 @@ import (
"github.com/stretchr/testify/require"
"github.com/tech/sendico/ledger/storage/model"
me "github.com/tech/sendico/pkg/messaging/envelope"
"go.mongodb.org/mongo-driver/bson/primitive"
"go.mongodb.org/mongo-driver/v2/bson"
"go.uber.org/zap"
)
@@ -24,8 +24,8 @@ func TestOutboxPublisherDispatchSuccess(t *testing.T) {
Payload: []byte(`{"journalEntryRef":"abc123"}`),
Attempts: 0,
}
event.SetID(primitive.NewObjectID())
event.OrganizationRef = primitive.NewObjectID()
event.SetID(bson.NewObjectID())
event.OrganizationRef = bson.NewObjectID()
store := &recordingOutboxStore{
pending: []*model.OutboxEvent{event},
@@ -62,8 +62,8 @@ func TestOutboxPublisherDispatchFailureMarksAttempts(t *testing.T) {
Payload: []byte(`{"journalEntryRef":"xyz789"}`),
Attempts: maxOutboxDeliveryAttempts - 1,
}
event.SetID(primitive.NewObjectID())
event.OrganizationRef = primitive.NewObjectID()
event.SetID(bson.NewObjectID())
event.OrganizationRef = bson.NewObjectID()
store := &recordingOutboxStore{
pending: []*model.OutboxEvent{event},
@@ -89,9 +89,9 @@ type recordingOutboxStore struct {
pending []*model.OutboxEvent
markedSent []primitive.ObjectID
markedFailed []primitive.ObjectID
incremented []primitive.ObjectID
markedSent []bson.ObjectID
markedFailed []bson.ObjectID
incremented []bson.ObjectID
}
func (s *recordingOutboxStore) Create(context.Context, *model.OutboxEvent) error {
@@ -106,7 +106,7 @@ func (s *recordingOutboxStore) ListPending(context.Context, int) ([]*model.Outbo
return events, nil
}
func (s *recordingOutboxStore) MarkSent(_ context.Context, eventRef primitive.ObjectID, sentAt time.Time) error {
func (s *recordingOutboxStore) MarkSent(_ context.Context, eventRef bson.ObjectID, sentAt time.Time) error {
_ = sentAt
s.mu.Lock()
defer s.mu.Unlock()
@@ -114,14 +114,14 @@ func (s *recordingOutboxStore) MarkSent(_ context.Context, eventRef primitive.Ob
return nil
}
func (s *recordingOutboxStore) MarkFailed(_ context.Context, eventRef primitive.ObjectID) error {
func (s *recordingOutboxStore) MarkFailed(_ context.Context, eventRef bson.ObjectID) error {
s.mu.Lock()
defer s.mu.Unlock()
s.markedFailed = append(s.markedFailed, eventRef)
return nil
}
func (s *recordingOutboxStore) IncrementAttempts(_ context.Context, eventRef primitive.ObjectID) error {
func (s *recordingOutboxStore) IncrementAttempts(_ context.Context, eventRef bson.ObjectID) error {
s.mu.Lock()
defer s.mu.Unlock()
s.incremented = append(s.incremented, eventRef)

View File

@@ -13,7 +13,7 @@ import (
pmodel "github.com/tech/sendico/pkg/model"
"github.com/tech/sendico/pkg/mutil/mzap"
ledgerv1 "github.com/tech/sendico/pkg/proto/ledger/v1"
"go.mongodb.org/mongo-driver/bson/primitive"
"go.mongodb.org/mongo-driver/v2/bson"
"go.uber.org/zap"
)
@@ -89,7 +89,7 @@ func (s *Service) postCreditResponder(_ context.Context, req *ledgerv1.PostCredi
return nil, err
}
accountsByRef := map[primitive.ObjectID]*pmodel.LedgerAccount{accountRef: account}
accountsByRef := map[bson.ObjectID]*pmodel.LedgerAccount{accountRef: account}
eventTime := getEventTime(req.EventTime)
creditAmount, _ := parseDecimal(req.Money.Amount)
@@ -109,7 +109,7 @@ func (s *Service) postCreditResponder(_ context.Context, req *ledgerv1.PostCredi
postingLines := make([]*model.PostingLine, 0, 2+len(charges))
mainLine := &model.PostingLine{
JournalEntryRef: primitive.NilObjectID,
JournalEntryRef: bson.NilObjectID,
AccountRef: accountRef,
Amount: creditAmount.String(),
Currency: req.Money.Currency,
@@ -146,7 +146,7 @@ func (s *Service) postCreditResponder(_ context.Context, req *ledgerv1.PostCredi
entryTotal = entryTotal.Add(chargeAmount)
chargeLine := &model.PostingLine{
JournalEntryRef: primitive.NilObjectID,
JournalEntryRef: bson.NilObjectID,
AccountRef: chargeAccountRef,
Amount: chargeAmount.String(),
Currency: charge.Money.Currency,
@@ -170,7 +170,7 @@ func (s *Service) postCreditResponder(_ context.Context, req *ledgerv1.PostCredi
contraAmount := entryTotal.Neg()
if !contraAmount.IsZero() || len(postingLines) == 1 {
contraLine := &model.PostingLine{
JournalEntryRef: primitive.NilObjectID,
JournalEntryRef: bson.NilObjectID,
AccountRef: *contraAccountID,
Amount: contraAmount.String(),
Currency: req.Money.Currency,

View File

@@ -13,7 +13,7 @@ import (
pmodel "github.com/tech/sendico/pkg/model"
"github.com/tech/sendico/pkg/mutil/mzap"
ledgerv1 "github.com/tech/sendico/pkg/proto/ledger/v1"
"go.mongodb.org/mongo-driver/bson/primitive"
"go.mongodb.org/mongo-driver/v2/bson"
"go.uber.org/zap"
)
@@ -86,7 +86,7 @@ func (s *Service) postDebitResponder(_ context.Context, req *ledgerv1.PostDebitR
return nil, err
}
accountsByRef := map[primitive.ObjectID]*pmodel.LedgerAccount{accountRef: account}
accountsByRef := map[bson.ObjectID]*pmodel.LedgerAccount{accountRef: account}
eventTime := getEventTime(req.EventTime)
debitAmount, _ := parseDecimal(req.Money.Amount)
@@ -106,7 +106,7 @@ func (s *Service) postDebitResponder(_ context.Context, req *ledgerv1.PostDebitR
postingLines := make([]*model.PostingLine, 0, 2+len(charges))
mainLine := &model.PostingLine{
JournalEntryRef: primitive.NilObjectID,
JournalEntryRef: bson.NilObjectID,
AccountRef: accountRef,
Amount: debitAmount.Neg().String(),
Currency: req.Money.Currency,
@@ -143,7 +143,7 @@ func (s *Service) postDebitResponder(_ context.Context, req *ledgerv1.PostDebitR
entryTotal = entryTotal.Add(chargeAmount)
chargeLine := &model.PostingLine{
JournalEntryRef: primitive.NilObjectID,
JournalEntryRef: bson.NilObjectID,
AccountRef: chargeAccountRef,
Amount: chargeAmount.String(),
Currency: charge.Money.Currency,
@@ -167,7 +167,7 @@ func (s *Service) postDebitResponder(_ context.Context, req *ledgerv1.PostDebitR
contraAmount := entryTotal.Neg()
if !contraAmount.IsZero() || len(postingLines) == 1 {
contraLine := &model.PostingLine{
JournalEntryRef: primitive.NilObjectID,
JournalEntryRef: bson.NilObjectID,
AccountRef: *contraAccountID,
Amount: contraAmount.String(),
Currency: req.Money.Currency,

View File

@@ -13,7 +13,7 @@ import (
pmodel "github.com/tech/sendico/pkg/model"
"github.com/tech/sendico/pkg/mutil/mzap"
ledgerv1 "github.com/tech/sendico/pkg/proto/ledger/v1"
"go.mongodb.org/mongo-driver/bson/primitive"
"go.mongodb.org/mongo-driver/v2/bson"
"go.uber.org/zap"
)
@@ -100,7 +100,7 @@ func (s *Service) postExternalCreditResponder(_ context.Context, req *ledgerv1.P
return nil, merrors.Internal("system account missing identifier")
}
accountsByRef := map[primitive.ObjectID]*pmodel.LedgerAccount{
accountsByRef := map[bson.ObjectID]*pmodel.LedgerAccount{
accountRef: account,
*systemAccountID: systemAccount,
}
@@ -123,7 +123,7 @@ func (s *Service) postExternalCreditResponder(_ context.Context, req *ledgerv1.P
postingLines := make([]*model.PostingLine, 0, 2+len(charges))
mainLine := &model.PostingLine{
JournalEntryRef: primitive.NilObjectID,
JournalEntryRef: bson.NilObjectID,
AccountRef: accountRef,
Amount: creditAmount.String(),
Currency: req.Money.Currency,
@@ -160,7 +160,7 @@ func (s *Service) postExternalCreditResponder(_ context.Context, req *ledgerv1.P
entryTotal = entryTotal.Add(chargeAmount)
chargeLine := &model.PostingLine{
JournalEntryRef: primitive.NilObjectID,
JournalEntryRef: bson.NilObjectID,
AccountRef: chargeAccountRef,
Amount: chargeAmount.String(),
Currency: charge.Money.Currency,
@@ -173,7 +173,7 @@ func (s *Service) postExternalCreditResponder(_ context.Context, req *ledgerv1.P
contraAmount := entryTotal.Neg()
if !contraAmount.IsZero() || len(postingLines) == 1 {
contraLine := &model.PostingLine{
JournalEntryRef: primitive.NilObjectID,
JournalEntryRef: bson.NilObjectID,
AccountRef: *systemAccountID,
Amount: contraAmount.String(),
Currency: req.Money.Currency,
@@ -333,7 +333,7 @@ func (s *Service) postExternalDebitResponder(_ context.Context, req *ledgerv1.Po
return nil, merrors.Internal("system account missing identifier")
}
accountsByRef := map[primitive.ObjectID]*pmodel.LedgerAccount{
accountsByRef := map[bson.ObjectID]*pmodel.LedgerAccount{
accountRef: account,
*systemAccountID: systemAccount,
}
@@ -356,7 +356,7 @@ func (s *Service) postExternalDebitResponder(_ context.Context, req *ledgerv1.Po
postingLines := make([]*model.PostingLine, 0, 2+len(charges))
mainLine := &model.PostingLine{
JournalEntryRef: primitive.NilObjectID,
JournalEntryRef: bson.NilObjectID,
AccountRef: accountRef,
Amount: debitAmount.Neg().String(),
Currency: req.Money.Currency,
@@ -393,7 +393,7 @@ func (s *Service) postExternalDebitResponder(_ context.Context, req *ledgerv1.Po
entryTotal = entryTotal.Add(chargeAmount)
chargeLine := &model.PostingLine{
JournalEntryRef: primitive.NilObjectID,
JournalEntryRef: bson.NilObjectID,
AccountRef: chargeAccountRef,
Amount: chargeAmount.String(),
Currency: charge.Money.Currency,
@@ -406,7 +406,7 @@ func (s *Service) postExternalDebitResponder(_ context.Context, req *ledgerv1.Po
contraAmount := entryTotal.Neg()
if !contraAmount.IsZero() || len(postingLines) == 1 {
contraLine := &model.PostingLine{
JournalEntryRef: primitive.NilObjectID,
JournalEntryRef: bson.NilObjectID,
AccountRef: *systemAccountID,
Amount: contraAmount.String(),
Currency: req.Money.Currency,

View File

@@ -12,7 +12,7 @@ import (
pmodel "github.com/tech/sendico/pkg/model"
"github.com/tech/sendico/pkg/mutil/mzap"
ledgerv1 "github.com/tech/sendico/pkg/proto/ledger/v1"
"go.mongodb.org/mongo-driver/bson/primitive"
"go.mongodb.org/mongo-driver/v2/bson"
"go.uber.org/zap"
)
@@ -115,7 +115,7 @@ func (s *Service) fxResponder(_ context.Context, req *ledgerv1.FXRequest) gsresp
return nil, merrors.InvalidArgument(fmt.Sprintf("to_account: %s", err.Error()))
}
accountsByRef := map[primitive.ObjectID]*pmodel.LedgerAccount{
accountsByRef := map[bson.ObjectID]*pmodel.LedgerAccount{
fromAccountRef: fromAccount,
toAccountRef: toAccount,
}
@@ -131,7 +131,7 @@ func (s *Service) fxResponder(_ context.Context, req *ledgerv1.FXRequest) gsresp
// Debit from account
fromLine := &model.PostingLine{
JournalEntryRef: primitive.NilObjectID,
JournalEntryRef: bson.NilObjectID,
AccountRef: fromAccountRef,
Amount: fromAmount.Neg().String(), // negative = debit
Currency: req.FromMoney.Currency,
@@ -142,7 +142,7 @@ func (s *Service) fxResponder(_ context.Context, req *ledgerv1.FXRequest) gsresp
// Credit to account
toLine := &model.PostingLine{
JournalEntryRef: primitive.NilObjectID,
JournalEntryRef: bson.NilObjectID,
AccountRef: toAccountRef,
Amount: toAmount.String(), // positive = credit
Currency: req.ToMoney.Currency,
@@ -175,7 +175,7 @@ func (s *Service) fxResponder(_ context.Context, req *ledgerv1.FXRequest) gsresp
}
chargeLine := &model.PostingLine{
JournalEntryRef: primitive.NilObjectID,
JournalEntryRef: bson.NilObjectID,
AccountRef: chargeAccountRef,
Amount: chargeAmount.String(),
Currency: charge.Money.Currency,

View File

@@ -13,7 +13,7 @@ import (
"github.com/tech/sendico/pkg/merrors"
pmodel "github.com/tech/sendico/pkg/model"
"github.com/tech/sendico/pkg/mutil/mzap"
"go.mongodb.org/mongo-driver/bson/primitive"
"go.mongodb.org/mongo-driver/v2/bson"
"go.uber.org/zap"
)
@@ -47,23 +47,23 @@ func validateAccountRole(account *pmodel.LedgerAccount, expected pmodel.AccountR
// If accountRefStr is non-empty, it fetches by ID and optionally asserts the role.
// If accountRefStr is empty and role is set, it resolves via GetByRole(orgRef, currency, role).
// Returns the account and its ObjectID, or an error.
func (s *Service) resolveAccount(ctx context.Context, accountRefStr string, role pmodel.AccountRole, orgRef primitive.ObjectID, currency, label string) (*pmodel.LedgerAccount, primitive.ObjectID, error) {
func (s *Service) resolveAccount(ctx context.Context, accountRefStr string, role pmodel.AccountRole, orgRef bson.ObjectID, currency, label string) (*pmodel.LedgerAccount, bson.ObjectID, error) {
if accountRefStr != "" {
ref, err := parseObjectID(accountRefStr)
if err != nil {
return nil, primitive.NilObjectID, err
return nil, bson.NilObjectID, err
}
account, err := s.storage.Accounts().Get(ctx, ref)
if err != nil {
if errors.Is(err, storage.ErrAccountNotFound) {
return nil, primitive.NilObjectID, merrors.NoData(label + " not found")
return nil, bson.NilObjectID, merrors.NoData(label + " not found")
}
return nil, primitive.NilObjectID, merrors.Internal("failed to get " + label)
return nil, bson.NilObjectID, merrors.Internal("failed to get " + label)
}
// If role is also specified, assert it matches
if role != "" {
if err := validateAccountRole(account, role, label); err != nil {
return nil, primitive.NilObjectID, err
return nil, bson.NilObjectID, err
}
}
return account, ref, nil
@@ -71,25 +71,25 @@ func (s *Service) resolveAccount(ctx context.Context, accountRefStr string, role
// No ref provided — resolve by role
if role == "" {
return nil, primitive.NilObjectID, merrors.InvalidArgument(label + ": ledger_account_ref or role is required")
return nil, bson.NilObjectID, merrors.InvalidArgument(label + ": ledger_account_ref or role is required")
}
if orgRef.IsZero() {
return nil, primitive.NilObjectID, merrors.InvalidArgument(label + ": organization_ref is required for role resolution")
return nil, bson.NilObjectID, merrors.InvalidArgument(label + ": organization_ref is required for role resolution")
}
if currency == "" {
return nil, primitive.NilObjectID, merrors.InvalidArgument(label + ": currency is required for role resolution")
return nil, bson.NilObjectID, merrors.InvalidArgument(label + ": currency is required for role resolution")
}
account, err := s.storage.Accounts().GetByRole(ctx, orgRef, currency, role)
if err != nil {
if errors.Is(err, storage.ErrAccountNotFound) {
return nil, primitive.NilObjectID, merrors.NoData(fmt.Sprintf("%s: no account found with role %s", label, role))
return nil, bson.NilObjectID, merrors.NoData(fmt.Sprintf("%s: no account found with role %s", label, role))
}
return nil, primitive.NilObjectID, merrors.Internal("failed to resolve " + label + " by role")
return nil, bson.NilObjectID, merrors.Internal("failed to resolve " + label + " by role")
}
return account, *account.GetID(), nil
}
func validateAccountForOrg(account *pmodel.LedgerAccount, orgRef primitive.ObjectID, currency string) error {
func validateAccountForOrg(account *pmodel.LedgerAccount, orgRef bson.ObjectID, currency string) error {
if account == nil {
return merrors.InvalidArgument("account is required")
}
@@ -111,7 +111,7 @@ func validateAccountForOrg(account *pmodel.LedgerAccount, orgRef primitive.Objec
return nil
}
func (s *Service) getAccount(ctx context.Context, cache map[primitive.ObjectID]*pmodel.LedgerAccount, accountRef primitive.ObjectID) (*pmodel.LedgerAccount, error) {
func (s *Service) getAccount(ctx context.Context, cache map[bson.ObjectID]*pmodel.LedgerAccount, accountRef bson.ObjectID) (*pmodel.LedgerAccount, error) {
if accountRef.IsZero() {
return nil, merrors.InvalidArgument("account reference is required")
}
@@ -127,7 +127,7 @@ func (s *Service) getAccount(ctx context.Context, cache map[primitive.ObjectID]*
return account, nil
}
func (s *Service) resolveSettlementAccount(ctx context.Context, orgRef primitive.ObjectID, currency, override string, cache map[primitive.ObjectID]*pmodel.LedgerAccount) (*pmodel.LedgerAccount, error) {
func (s *Service) resolveSettlementAccount(ctx context.Context, orgRef bson.ObjectID, currency, override string, cache map[bson.ObjectID]*pmodel.LedgerAccount) (*pmodel.LedgerAccount, error) {
if override != "" {
overrideRef, err := parseObjectID(override)
if err != nil {
@@ -172,12 +172,12 @@ func (s *Service) resolveSettlementAccount(ctx context.Context, orgRef primitive
return account, nil
}
func (s *Service) upsertBalances(ctx context.Context, lines []*model.PostingLine, accounts map[primitive.ObjectID]*pmodel.LedgerAccount) error {
func (s *Service) upsertBalances(ctx context.Context, lines []*model.PostingLine, accounts map[bson.ObjectID]*pmodel.LedgerAccount) error {
if len(lines) == 0 {
return nil
}
balanceDeltas := make(map[primitive.ObjectID]decimal.Decimal, len(lines))
balanceDeltas := make(map[bson.ObjectID]decimal.Decimal, len(lines))
for _, line := range lines {
delta, err := parseDecimal(line.Amount)
if err != nil {
@@ -233,7 +233,7 @@ func (s *Service) upsertBalances(ctx context.Context, lines []*model.PostingLine
if account.OrganizationRef != nil {
newBalance.OrganizationRef = *account.OrganizationRef
} else {
newBalance.OrganizationRef = primitive.NilObjectID
newBalance.OrganizationRef = bson.NilObjectID
}
if err := balancesStore.Upsert(ctx, newBalance); err != nil {

View File

@@ -13,7 +13,7 @@ import (
"github.com/tech/sendico/ledger/storage/model"
"github.com/tech/sendico/pkg/merrors"
pmodel "github.com/tech/sendico/pkg/model"
"go.mongodb.org/mongo-driver/bson/primitive"
"go.mongodb.org/mongo-driver/v2/bson"
"go.uber.org/zap"
)
@@ -31,7 +31,7 @@ func (s *stubRepository) Balances() storage.BalancesStore { return s
func (s *stubRepository) Outbox() storage.OutboxStore { return s.outbox }
type stubAccountsStore struct {
getByID map[primitive.ObjectID]*pmodel.LedgerAccount
getByID map[bson.ObjectID]*pmodel.LedgerAccount
defaultSettlement *pmodel.LedgerAccount
getErr error
defaultErr error
@@ -40,7 +40,7 @@ type stubAccountsStore struct {
func (s *stubAccountsStore) Create(context.Context, *pmodel.LedgerAccount) error {
return merrors.NotImplemented("create")
}
func (s *stubAccountsStore) Get(ctx context.Context, accountRef primitive.ObjectID) (*pmodel.LedgerAccount, error) {
func (s *stubAccountsStore) Get(ctx context.Context, accountRef bson.ObjectID) (*pmodel.LedgerAccount, error) {
if s.getErr != nil {
return nil, s.getErr
}
@@ -49,16 +49,16 @@ func (s *stubAccountsStore) Get(ctx context.Context, accountRef primitive.Object
}
return nil, storage.ErrAccountNotFound
}
func (s *stubAccountsStore) GetByAccountCode(context.Context, primitive.ObjectID, string, string) (*pmodel.LedgerAccount, error) {
func (s *stubAccountsStore) GetByAccountCode(context.Context, bson.ObjectID, string, string) (*pmodel.LedgerAccount, error) {
return nil, merrors.NotImplemented("get by code")
}
func (s *stubAccountsStore) GetByRole(context.Context, primitive.ObjectID, string, pmodel.AccountRole) (*pmodel.LedgerAccount, error) {
func (s *stubAccountsStore) GetByRole(context.Context, bson.ObjectID, string, pmodel.AccountRole) (*pmodel.LedgerAccount, error) {
return nil, merrors.NotImplemented("get by role")
}
func (s *stubAccountsStore) GetSystemAccount(context.Context, pmodel.SystemAccountPurpose, string) (*pmodel.LedgerAccount, error) {
return nil, merrors.NotImplemented("get system account")
}
func (s *stubAccountsStore) GetDefaultSettlement(context.Context, primitive.ObjectID, string) (*pmodel.LedgerAccount, error) {
func (s *stubAccountsStore) GetDefaultSettlement(context.Context, bson.ObjectID, string) (*pmodel.LedgerAccount, error) {
if s.defaultErr != nil {
return nil, s.defaultErr
}
@@ -67,21 +67,21 @@ func (s *stubAccountsStore) GetDefaultSettlement(context.Context, primitive.Obje
}
return s.defaultSettlement, nil
}
func (s *stubAccountsStore) ListByOrganization(context.Context, primitive.ObjectID, *storage.AccountsFilter, int, int) ([]*pmodel.LedgerAccount, error) {
func (s *stubAccountsStore) ListByOrganization(context.Context, bson.ObjectID, *storage.AccountsFilter, int, int) ([]*pmodel.LedgerAccount, error) {
return nil, merrors.NotImplemented("list")
}
func (s *stubAccountsStore) UpdateStatus(context.Context, primitive.ObjectID, pmodel.LedgerAccountStatus) error {
func (s *stubAccountsStore) UpdateStatus(context.Context, bson.ObjectID, pmodel.LedgerAccountStatus) error {
return merrors.NotImplemented("update status")
}
type stubBalancesStore struct {
records map[primitive.ObjectID]*model.AccountBalance
records map[bson.ObjectID]*model.AccountBalance
upserts []*model.AccountBalance
getErr error
upErr error
}
func (s *stubBalancesStore) Get(ctx context.Context, accountRef primitive.ObjectID) (*model.AccountBalance, error) {
func (s *stubBalancesStore) Get(ctx context.Context, accountRef bson.ObjectID) (*model.AccountBalance, error) {
if s.getErr != nil {
return nil, s.getErr
}
@@ -98,13 +98,13 @@ func (s *stubBalancesStore) Upsert(ctx context.Context, balance *model.AccountBa
copied := *balance
s.upserts = append(s.upserts, &copied)
if s.records == nil {
s.records = make(map[primitive.ObjectID]*model.AccountBalance)
s.records = make(map[bson.ObjectID]*model.AccountBalance)
}
s.records[balance.AccountRef] = &copied
return nil
}
func (s *stubBalancesStore) IncrementBalance(context.Context, primitive.ObjectID, string) error {
func (s *stubBalancesStore) IncrementBalance(context.Context, bson.ObjectID, string) error {
return merrors.NotImplemented("increment")
}
@@ -126,22 +126,22 @@ func (s *stubOutboxStore) ListPending(context.Context, int) ([]*model.OutboxEven
return nil, merrors.NotImplemented("list")
}
func (s *stubOutboxStore) MarkSent(context.Context, primitive.ObjectID, time.Time) error {
func (s *stubOutboxStore) MarkSent(context.Context, bson.ObjectID, time.Time) error {
return merrors.NotImplemented("mark sent")
}
func (s *stubOutboxStore) MarkFailed(context.Context, primitive.ObjectID) error {
func (s *stubOutboxStore) MarkFailed(context.Context, bson.ObjectID) error {
return merrors.NotImplemented("mark failed")
}
func (s *stubOutboxStore) IncrementAttempts(context.Context, primitive.ObjectID) error {
func (s *stubOutboxStore) IncrementAttempts(context.Context, bson.ObjectID) error {
return merrors.NotImplemented("increment attempts")
}
func TestResolveSettlementAccount_Default(t *testing.T) {
ctx := context.Background()
orgRef := primitive.NewObjectID()
settlementID := primitive.NewObjectID()
orgRef := bson.NewObjectID()
settlementID := bson.NewObjectID()
settlement := &pmodel.LedgerAccount{}
settlement.SetID(settlementID)
settlement.OrganizationRef = &orgRef
@@ -151,7 +151,7 @@ func TestResolveSettlementAccount_Default(t *testing.T) {
accounts := &stubAccountsStore{defaultSettlement: settlement}
repo := &stubRepository{accounts: accounts}
service := &Service{logger: zap.NewNop(), storage: repo}
cache := make(map[primitive.ObjectID]*pmodel.LedgerAccount)
cache := make(map[bson.ObjectID]*pmodel.LedgerAccount)
result, err := service.resolveSettlementAccount(ctx, orgRef, "USD", "", cache)
@@ -162,18 +162,18 @@ func TestResolveSettlementAccount_Default(t *testing.T) {
func TestResolveSettlementAccount_Override(t *testing.T) {
ctx := context.Background()
orgRef := primitive.NewObjectID()
overrideID := primitive.NewObjectID()
orgRef := bson.NewObjectID()
overrideID := bson.NewObjectID()
override := &pmodel.LedgerAccount{}
override.SetID(overrideID)
override.OrganizationRef = &orgRef
override.Currency = "EUR"
override.Status = pmodel.LedgerAccountStatusActive
accounts := &stubAccountsStore{getByID: map[primitive.ObjectID]*pmodel.LedgerAccount{overrideID: override}}
accounts := &stubAccountsStore{getByID: map[bson.ObjectID]*pmodel.LedgerAccount{overrideID: override}}
repo := &stubRepository{accounts: accounts}
service := &Service{logger: zap.NewNop(), storage: repo}
cache := make(map[primitive.ObjectID]*pmodel.LedgerAccount)
cache := make(map[bson.ObjectID]*pmodel.LedgerAccount)
result, err := service.resolveSettlementAccount(ctx, orgRef, "EUR", overrideID.Hex(), cache)
@@ -184,12 +184,12 @@ func TestResolveSettlementAccount_Override(t *testing.T) {
func TestResolveSettlementAccount_NoDefault(t *testing.T) {
ctx := context.Background()
orgRef := primitive.NewObjectID()
orgRef := bson.NewObjectID()
accounts := &stubAccountsStore{defaultErr: storage.ErrAccountNotFound}
repo := &stubRepository{accounts: accounts}
service := &Service{logger: zap.NewNop(), storage: repo}
_, err := service.resolveSettlementAccount(ctx, orgRef, "USD", "", map[primitive.ObjectID]*pmodel.LedgerAccount{})
_, err := service.resolveSettlementAccount(ctx, orgRef, "USD", "", map[bson.ObjectID]*pmodel.LedgerAccount{})
require.Error(t, err)
assert.True(t, errors.Is(err, merrors.ErrInvalidArg))
@@ -197,8 +197,8 @@ func TestResolveSettlementAccount_NoDefault(t *testing.T) {
func TestUpsertBalances_Succeeds(t *testing.T) {
ctx := context.Background()
orgRef := primitive.NewObjectID()
accountRef := primitive.NewObjectID()
orgRef := bson.NewObjectID()
accountRef := bson.NewObjectID()
account := &pmodel.LedgerAccount{AllowNegative: false, Currency: "USD"}
account.OrganizationRef = &orgRef
@@ -213,7 +213,7 @@ func TestUpsertBalances_Succeeds(t *testing.T) {
balances := &stubBalancesStore{}
repo := &stubRepository{balances: balances}
service := &Service{logger: zap.NewNop(), storage: repo}
accountCache := map[primitive.ObjectID]*pmodel.LedgerAccount{accountRef: account}
accountCache := map[bson.ObjectID]*pmodel.LedgerAccount{accountRef: account}
require.NoError(t, service.upsertBalances(ctx, balanceLines, accountCache))
require.Len(t, balances.upserts, 1)
@@ -224,8 +224,8 @@ func TestUpsertBalances_Succeeds(t *testing.T) {
func TestUpsertBalances_DisallowNegative(t *testing.T) {
ctx := context.Background()
orgRef := primitive.NewObjectID()
accountRef := primitive.NewObjectID()
orgRef := bson.NewObjectID()
accountRef := bson.NewObjectID()
account := &pmodel.LedgerAccount{AllowNegative: false, Currency: "USD"}
account.OrganizationRef = &orgRef
@@ -240,7 +240,7 @@ func TestUpsertBalances_DisallowNegative(t *testing.T) {
balances := &stubBalancesStore{}
repo := &stubRepository{balances: balances}
service := &Service{logger: zap.NewNop(), storage: repo}
accountCache := map[primitive.ObjectID]*pmodel.LedgerAccount{accountRef: account}
accountCache := map[bson.ObjectID]*pmodel.LedgerAccount{accountRef: account}
err := service.upsertBalances(ctx, balanceLines, accountCache)
@@ -250,8 +250,8 @@ func TestUpsertBalances_DisallowNegative(t *testing.T) {
func TestEnqueueOutbox_CreatesEvent(t *testing.T) {
ctx := context.Background()
orgRef := primitive.NewObjectID()
entryID := primitive.NewObjectID()
orgRef := bson.NewObjectID()
entryID := bson.NewObjectID()
entry := &model.JournalEntry{
IdempotencyKey: "idem",
EventTime: time.Now().UTC(),
@@ -263,7 +263,7 @@ func TestEnqueueOutbox_CreatesEvent(t *testing.T) {
lines := []*model.PostingLine{
{
AccountRef: primitive.NewObjectID(),
AccountRef: bson.NewObjectID(),
Amount: "100",
Currency: "USD",
LineType: model.LineTypeMain,

View File

@@ -13,7 +13,7 @@ import (
pmodel "github.com/tech/sendico/pkg/model"
"github.com/tech/sendico/pkg/mutil/mzap"
ledgerv1 "github.com/tech/sendico/pkg/proto/ledger/v1"
"go.mongodb.org/mongo-driver/bson/primitive"
"go.mongodb.org/mongo-driver/v2/bson"
"go.uber.org/zap"
)
@@ -121,7 +121,7 @@ func (s *Service) transferResponder(_ context.Context, req *ledgerv1.TransferReq
return nil, merrors.InvalidArgument("cannot transfer to same account")
}
accountsByRef := map[primitive.ObjectID]*pmodel.LedgerAccount{
accountsByRef := map[bson.ObjectID]*pmodel.LedgerAccount{
fromAccountRef: fromAccount,
toAccountRef: toAccount,
}
@@ -136,7 +136,7 @@ func (s *Service) transferResponder(_ context.Context, req *ledgerv1.TransferReq
// Debit from account
fromLine := &model.PostingLine{
JournalEntryRef: primitive.NilObjectID,
JournalEntryRef: bson.NilObjectID,
AccountRef: fromAccountRef,
Amount: transferAmount.Neg().String(), // negative = debit
Currency: req.Money.Currency,
@@ -147,7 +147,7 @@ func (s *Service) transferResponder(_ context.Context, req *ledgerv1.TransferReq
// Credit to account
toLine := &model.PostingLine{
JournalEntryRef: primitive.NilObjectID,
JournalEntryRef: bson.NilObjectID,
AccountRef: toAccountRef,
Amount: transferAmount.String(), // positive = credit
Currency: req.Money.Currency,
@@ -184,7 +184,7 @@ func (s *Service) transferResponder(_ context.Context, req *ledgerv1.TransferReq
}
chargeLine := &model.PostingLine{
JournalEntryRef: primitive.NilObjectID,
JournalEntryRef: bson.NilObjectID,
AccountRef: chargeAccountRef,
Amount: chargeAmount.String(),
Currency: charge.Money.Currency,

View File

@@ -8,7 +8,7 @@ import (
"github.com/tech/sendico/ledger/storage"
"github.com/tech/sendico/pkg/merrors"
pmodel "github.com/tech/sendico/pkg/model"
"go.mongodb.org/mongo-driver/bson/primitive"
"go.mongodb.org/mongo-driver/v2/bson"
)
// EnsureSystemAccounts initializes required system accounts once at startup.
@@ -128,7 +128,7 @@ func (s *Service) cacheSystemAccount(purpose pmodel.SystemAccountPurpose, curren
}
func newExternalSystemAccount(purpose pmodel.SystemAccountPurpose, currency string) *pmodel.LedgerAccount {
ref := primitive.NewObjectID()
ref := bson.NewObjectID()
purposeCopy := purpose
account := &pmodel.LedgerAccount{
AccountCode: generateAccountCode(pmodel.LedgerAccountTypeAsset, currency, ref),

View File

@@ -8,7 +8,7 @@ import (
"github.com/tech/sendico/ledger/storage"
"github.com/tech/sendico/pkg/merrors"
pmodel "github.com/tech/sendico/pkg/model"
"go.mongodb.org/mongo-driver/bson/primitive"
"go.mongodb.org/mongo-driver/v2/bson"
"go.uber.org/zap"
)
@@ -19,7 +19,7 @@ type systemAccountsStoreStub struct {
func (s *systemAccountsStoreStub) Create(_ context.Context, account *pmodel.LedgerAccount) error {
if account.GetID() == nil || account.GetID().IsZero() {
account.SetID(primitive.NewObjectID())
account.SetID(bson.NewObjectID())
}
s.created = append(s.created, account)
if s.existing == nil {
@@ -32,15 +32,15 @@ func (s *systemAccountsStoreStub) Create(_ context.Context, account *pmodel.Ledg
return nil
}
func (s *systemAccountsStoreStub) Get(context.Context, primitive.ObjectID) (*pmodel.LedgerAccount, error) {
func (s *systemAccountsStoreStub) Get(context.Context, bson.ObjectID) (*pmodel.LedgerAccount, error) {
return nil, storage.ErrAccountNotFound
}
func (s *systemAccountsStoreStub) GetByAccountCode(context.Context, primitive.ObjectID, string, string) (*pmodel.LedgerAccount, error) {
func (s *systemAccountsStoreStub) GetByAccountCode(context.Context, bson.ObjectID, string, string) (*pmodel.LedgerAccount, error) {
return nil, merrors.NotImplemented("get by code")
}
func (s *systemAccountsStoreStub) GetByRole(context.Context, primitive.ObjectID, string, pmodel.AccountRole) (*pmodel.LedgerAccount, error) {
func (s *systemAccountsStoreStub) GetByRole(context.Context, bson.ObjectID, string, pmodel.AccountRole) (*pmodel.LedgerAccount, error) {
return nil, merrors.NotImplemented("get by role")
}
@@ -55,15 +55,15 @@ func (s *systemAccountsStoreStub) GetSystemAccount(_ context.Context, purpose pm
return nil, storage.ErrAccountNotFound
}
func (s *systemAccountsStoreStub) GetDefaultSettlement(context.Context, primitive.ObjectID, string) (*pmodel.LedgerAccount, error) {
func (s *systemAccountsStoreStub) GetDefaultSettlement(context.Context, bson.ObjectID, string) (*pmodel.LedgerAccount, error) {
return nil, merrors.NotImplemented("get default settlement")
}
func (s *systemAccountsStoreStub) ListByOrganization(context.Context, primitive.ObjectID, *storage.AccountsFilter, int, int) ([]*pmodel.LedgerAccount, error) {
func (s *systemAccountsStoreStub) ListByOrganization(context.Context, bson.ObjectID, *storage.AccountsFilter, int, int) ([]*pmodel.LedgerAccount, error) {
return nil, merrors.NotImplemented("list")
}
func (s *systemAccountsStoreStub) UpdateStatus(context.Context, primitive.ObjectID, pmodel.LedgerAccountStatus) error {
func (s *systemAccountsStoreStub) UpdateStatus(context.Context, bson.ObjectID, pmodel.LedgerAccountStatus) error {
return merrors.NotImplemented("update status")
}

View File

@@ -9,7 +9,7 @@ import (
"github.com/tech/sendico/pkg/merrors"
pmodel "github.com/tech/sendico/pkg/model"
"github.com/tech/sendico/pkg/mutil/mzap"
"go.mongodb.org/mongo-driver/bson/primitive"
"go.mongodb.org/mongo-driver/v2/bson"
"go.uber.org/zap"
)
@@ -32,7 +32,7 @@ func isRequiredTopologyRole(role pmodel.AccountRole) bool {
return false
}
func (s *Service) ensureLedgerTopology(ctx context.Context, orgRef primitive.ObjectID, currency string) error {
func (s *Service) ensureLedgerTopology(ctx context.Context, orgRef bson.ObjectID, currency string) error {
if s.storage == nil || s.storage.Accounts() == nil {
return errStorageNotInitialized
}
@@ -52,7 +52,7 @@ func (s *Service) ensureLedgerTopology(ctx context.Context, orgRef primitive.Obj
return nil
}
func (s *Service) ensureRoleAccount(ctx context.Context, orgRef primitive.ObjectID, currency string, role pmodel.AccountRole) (*pmodel.LedgerAccount, error) {
func (s *Service) ensureRoleAccount(ctx context.Context, orgRef bson.ObjectID, currency string, role pmodel.AccountRole) (*pmodel.LedgerAccount, error) {
if s.storage == nil || s.storage.Accounts() == nil {
return nil, errStorageNotInitialized
}
@@ -104,8 +104,8 @@ func (s *Service) ensureRoleAccount(ctx context.Context, orgRef primitive.Object
return account, nil
}
func newSystemAccount(orgRef primitive.ObjectID, currency string, role pmodel.AccountRole) *pmodel.LedgerAccount {
ref := primitive.NewObjectID()
func newSystemAccount(orgRef bson.ObjectID, currency string, role pmodel.AccountRole) *pmodel.LedgerAccount {
ref := bson.NewObjectID()
account := &pmodel.LedgerAccount{
AccountCode: generateAccountCode(pmodel.LedgerAccountTypeAsset, currency, ref),
AccountType: pmodel.LedgerAccountTypeAsset,