repository

package
v1.1.3 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 2, 2026 License: AGPL-3.0 Imports: 8 Imported by: 0

Documentation

Overview

Package repository is the data-access layer. It holds the GORM-backed repositories for the core models — users, accounts, and transactions — behind interfaces that expose persistence operations and nothing else. Business rules live in the service packages above; this layer only reads and writes rows.

Repositories bundles the three repositories, and NewRepositories wires them from a single *gorm.DB. Each constructor (and NewRepositories itself) rejects a nil database with errors.ErrNilDB. Every repository owns its own sentinel errors — ErrUserNotFound, ErrAccountNotFound, ErrTransactionNotFound, and the matching ErrFailedTo* values — and translates raw GORM errors into them, so callers match on package errors and never import GORM's.

Reads that return lists take limit and offset for pagination; the service layer is responsible for turning page numbers into those.

Soft deletes

Deletion is reversible and implemented by hand through a deleted_at column, not GORM's automatic soft delete. Delete stamps deleted_at with the current time, Restore clears it (an Unscoped update, since the row is otherwise hidden), and every read filters on deleted_at IS NULL. A deleted row therefore stays in the table but disappears from normal queries until it is restored.

Transactions

Write methods come in a plain form and a WithTx form. The WithTx variant accepts a *gorm.DB supplied by the caller, so a write can join a larger unit of work — for example creating a user and their first account atomically. The account index handed to a new account is derived as one past the highest existing index across all accounts, with index 0 reserved for the admin.

Index

Constants

This section is empty.

Variables

View Source
var (
	ErrAccountNotFound           = errors.New("account not found")
	ErrFailedToCreateAccount     = errors.New("failed to create account")
	ErrFailedToGetAccount        = errors.New("failed to get account")
	ErrFailedToGetAccountsByUser = errors.New("failed to get accounts by user")
	ErrFailedToGetNextIndex      = errors.New("failed to get next account index")
	ErrFailedToUpdateAccount     = errors.New("failed to update account")
	ErrFailedToDeleteAccount     = errors.New("failed to delete account")
	ErrFailedToRestoreAccount    = errors.New("failed to restore account")
)

Common errors for AccountRepository

View Source
var (
	ErrTransactionNotFound             = errors.New("transaction not found")
	ErrFailedToCreateTransaction       = errors.New("failed to create transaction")
	ErrFailedToCreateBatchTransactions = errors.New("failed to create batch transactions")
	ErrFailedToGetTransaction          = errors.New("failed to get transaction")
	ErrFailedToGetTransactionByHash    = errors.New("failed to get transaction by stellar hash")
	ErrFailedToGetTransactionsByLoanID = errors.New("failed to get transactions by loan ID")
	ErrFailedToGetTransactionsByUserID = errors.New("failed to get transactions by user ID")
	ErrFailedToGetTransactionsByStatus = errors.New("failed to get transactions by status")
	ErrFailedToUpdateTransaction       = errors.New("failed to update transaction")
	ErrFailedToListTransactions        = errors.New("failed to list transactions")
	ErrFailedToCountTransactions       = errors.New("failed to count transactions")
)

Common errors for TransactionRepository

View Source
var (
	ErrUserNotFound           = errors.New("user not found")
	ErrFailedToCreateUser     = errors.New("failed to create user")
	ErrFailedToGetUser        = errors.New("failed to get user")
	ErrFailedToGetUsers       = errors.New("failed to get users")
	ErrFailedToGetUsersByKYC  = errors.New("failed to get users by KYC status")
	ErrFailedToGetUsersByRole = errors.New("failed to get users by role")
	ErrFailedToCountUsers     = errors.New("failed to count users")
	ErrFailedToCountAdmins    = errors.New("failed to count admins")
	ErrFailedToUpdateUser     = errors.New("failed to update user")
	ErrFailedToDeleteUser     = errors.New("failed to delete user")
	ErrFailedToRestoreUser    = errors.New("failed to restore user")
)

Common errors for UserRepository

Functions

func IsTransactionUpdatableColumn added in v1.0.0

func IsTransactionUpdatableColumn(col string) bool

IsTransactionUpdatableColumn reports whether col may be written via UpdateFields. Exposed for test-guarding the service-layer partial-update mapping against drift.

Types

type AccountRepository

type AccountRepository interface {
	// Create operations
	Create(ctx context.Context, account *models.Account) error
	CreateWithTx(ctx context.Context, tx *gorm.DB, account *models.Account) error

	// Read operations
	GetByID(ctx context.Context, id string) (*models.Account, error)
	GetByUserID(ctx context.Context, userID string) (*models.Account, error)
	GetByPublicKey(ctx context.Context, publicKey string) (*models.Account, error)
	GetNextAccountIndex(ctx context.Context, userID string) (int, error)
	GetNextAccountIndexWithTx(ctx context.Context, tx *gorm.DB) (int, error)
	// EnsureAccountIndexFloor advances account_index_seq so the next handed-out
	// index is >= floor. No-op when the sequence is already at or past floor.
	EnsureAccountIndexFloor(ctx context.Context, floor int64) error

	// Update operations
	Update(ctx context.Context, account *models.Account) error
	UpdateChainStatus(ctx context.Context, id string, chainStatus string) error
	Restore(ctx context.Context, id string) error

	// Delete operations
	Delete(ctx context.Context, id string) error
}

AccountRepository defines the interface for account data access

func NewAccountRepository

func NewAccountRepository(db *gorm.DB) (AccountRepository, error)

NewAccountRepository creates a new AccountRepository

type Repositories

type Repositories struct {
	// Core repositories
	User        UserRepository
	Account     AccountRepository
	Transaction TransactionRepository
}

func NewRepositories

func NewRepositories(db *gorm.DB) (*Repositories, error)

type TransactionRepository

type TransactionRepository interface {
	// Create operations
	Create(ctx context.Context, tx *models.Transaction) error
	BatchCreate(ctx context.Context, txs []*models.Transaction) error

	// Read operations
	GetByID(ctx context.Context, id string) (*models.Transaction, error)
	GetByStellarHash(ctx context.Context, txHash string) (*models.Transaction, error)
	ListByExternalID(ctx context.Context, externalID string) ([]*models.Transaction, error)
	GetByLoanIDAndType(ctx context.Context, loanID, txType string) (*models.Transaction, error)
	GetByLoanID(ctx context.Context, loanID string, limit, offset int) ([]*models.Transaction, error)
	GetByUserID(ctx context.Context, userID string, limit, offset int) ([]*models.Transaction, error)
	GetByStatus(ctx context.Context, status string, limit, offset int) ([]*models.Transaction, error)

	// List returns transactions newest first, filtered by status and/or type
	// when either is given. Empty filters return everything.
	List(ctx context.Context, status, txType string, limit, offset int) ([]*models.Transaction, error)

	// Count returns the number of transactions matching the same filters List applies.
	Count(ctx context.Context, status, txType string) (int64, error)

	// Update operations
	Update(ctx context.Context, tx *models.Transaction) error

	// UpdateFields writes only the supplied columns, validated against the same
	// allow-list Update uses. Preferred for partial changes to avoid rewriting
	// the text/jsonb columns and all indexes on every touch.
	UpdateFields(ctx context.Context, id string, fields map[string]any) error
}

TransactionRepository defines the interface for transaction data access

func NewTransactionRepository

func NewTransactionRepository(db *gorm.DB) (TransactionRepository, error)

NewTransactionRepository creates a new instance of TransactionRepository

type UserRepository

type UserRepository interface {
	// Create operations
	Create(ctx context.Context, user *models.User) error
	CreateWithTx(ctx context.Context, tx *gorm.DB, user *models.User) error

	// Read operations
	GetByID(ctx context.Context, id string) (*models.User, error)
	GetByMobileNumber(ctx context.Context, mobileNumber string) (*models.User, error)
	GetByNationalID(ctx context.Context, nationalID string) (*models.User, error)
	GetByKYCStatus(ctx context.Context, kycStatus string, limit, offset int) ([]*models.User, error)
	GetByRole(ctx context.Context, role string, limit, offset int) ([]*models.User, error)
	List(ctx context.Context, limit, offset int) ([]*models.User, error)

	// ListFiltered returns users newest first, filtered by status and/or KYC
	// status when either is given. Empty filters return every non-deleted user.
	ListFiltered(ctx context.Context, status, kycStatus string, limit, offset int) ([]*models.User, error)

	// Count operations
	Count(ctx context.Context) (int64, error)

	// CountFiltered returns the number of users matching ListFiltered's filters.
	CountFiltered(ctx context.Context, status, kycStatus string) (int64, error)
	CountByKYCStatus(ctx context.Context, kycStatus string) (int64, error)
	CountByRole(ctx context.Context, role string) (int64, error)
	CountAdmins(ctx context.Context) (int, error)

	// Update operations
	Update(ctx context.Context, user *models.User) error

	// UpdateMobileNumber rebinds a user to a new MSISDN. Deliberately separate
	// from Update (which does not touch mobile_number) because this changes the
	// account's identity anchor — it is only used by new-SIM account recovery,
	// after the caller has verified ownership. The unique index on
	// mobile_number is the final guard against binding a number twice.
	UpdateMobileNumber(ctx context.Context, userID, mobileNumber string) error

	Restore(ctx context.Context, id string) error

	// Delete operations
	Delete(ctx context.Context, id string) error
}

UserRepository defines the interface for user data access

func NewUserRepository

func NewUserRepository(db *gorm.DB) (UserRepository, error)

NewUserRepository creates a new instance of UserRepository

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL