syntax = "proto3"; package ledger.v1; option go_package = "github.com/tech/sendico/pkg/proto/ledger/v1;ledgerv1"; import "google/protobuf/timestamp.proto"; import "google/protobuf/wrappers.proto"; import "api/proto/common/describable/v1/describable.proto"; import "api/proto/common/money/v1/money.proto"; // ===== Enums ===== // EntryType classifies the kind of journal entry. enum EntryType { // ENTRY_TYPE_UNSPECIFIED is the default zero value. ENTRY_TYPE_UNSPECIFIED = 0; // ENTRY_CREDIT records an inbound credit. ENTRY_CREDIT = 1; // ENTRY_DEBIT records an outbound debit. ENTRY_DEBIT = 2; // ENTRY_TRANSFER records a transfer between accounts. ENTRY_TRANSFER = 3; // ENTRY_FX records a foreign-exchange conversion. ENTRY_FX = 4; // ENTRY_FEE records a fee charge. ENTRY_FEE = 5; // ENTRY_ADJUST records a manual adjustment. ENTRY_ADJUST = 6; // ENTRY_REVERSE records a reversal of a prior entry. ENTRY_REVERSE = 7; } // LineType classifies the purpose of a posting line within an entry. enum LineType { // LINE_TYPE_UNSPECIFIED is the default zero value. LINE_TYPE_UNSPECIFIED = 0; // LINE_MAIN is the primary posting line. LINE_MAIN = 1; // LINE_FEE is a fee posting line. LINE_FEE = 2; // LINE_SPREAD is an FX spread posting line. LINE_SPREAD = 3; // LINE_REVERSAL is a reversal posting line. LINE_REVERSAL = 4; } // AccountType classifies the fundamental accounting type of an account. enum AccountType { // ACCOUNT_TYPE_UNSPECIFIED is the default zero value. ACCOUNT_TYPE_UNSPECIFIED = 0; // ACCOUNT_TYPE_ASSET represents an asset account. ACCOUNT_TYPE_ASSET = 1; // ACCOUNT_TYPE_LIABILITY represents a liability account. ACCOUNT_TYPE_LIABILITY = 2; // ACCOUNT_TYPE_REVENUE represents a revenue account. ACCOUNT_TYPE_REVENUE = 3; // ACCOUNT_TYPE_EXPENSE represents an expense account. ACCOUNT_TYPE_EXPENSE = 4; } // AccountStatus indicates whether an account is active or frozen. enum AccountStatus { // ACCOUNT_STATUS_UNSPECIFIED is the default zero value. ACCOUNT_STATUS_UNSPECIFIED = 0; // ACCOUNT_STATUS_ACTIVE means the account accepts postings. ACCOUNT_STATUS_ACTIVE = 1; // ACCOUNT_STATUS_FROZEN means the account is blocked from new postings. ACCOUNT_STATUS_FROZEN = 2; } // AccountRole defines the functional role of an account within an organization. enum AccountRole { // ACCOUNT_ROLE_UNSPECIFIED is the default zero value. ACCOUNT_ROLE_UNSPECIFIED = 0; // ACCOUNT_ROLE_OPERATING is the main operating account. ACCOUNT_ROLE_OPERATING = 1; // ACCOUNT_ROLE_HOLD is a temporary hold account. ACCOUNT_ROLE_HOLD = 2; // ACCOUNT_ROLE_TRANSIT is an in-transit account. ACCOUNT_ROLE_TRANSIT = 3; // ACCOUNT_ROLE_SETTLEMENT is a settlement account. ACCOUNT_ROLE_SETTLEMENT = 4; // ACCOUNT_ROLE_CLEARING is a clearing account. ACCOUNT_ROLE_CLEARING = 5; // ACCOUNT_ROLE_PENDING is a pending-settlement account. ACCOUNT_ROLE_PENDING = 6; // ACCOUNT_ROLE_RESERVE is a reserve account. ACCOUNT_ROLE_RESERVE = 7; // ACCOUNT_ROLE_LIQUIDITY is a liquidity pool account. ACCOUNT_ROLE_LIQUIDITY = 8; // ACCOUNT_ROLE_FEE is a fee collection account. ACCOUNT_ROLE_FEE = 9; // ACCOUNT_ROLE_CHARGEBACK is a chargeback account. ACCOUNT_ROLE_CHARGEBACK = 10; // ACCOUNT_ROLE_ADJUSTMENT is an adjustment account. ACCOUNT_ROLE_ADJUSTMENT = 11; } // LedgerAccount captures the canonical representation of an account resource. message LedgerAccount { string ledger_account_ref = 1; string organization_ref = 2; string account_code = 3; AccountType account_type = 4; string currency = 5; AccountStatus status = 6; bool allow_negative = 7; reserved 8; reserved "is_settlement"; map metadata = 9; google.protobuf.Timestamp created_at = 10; google.protobuf.Timestamp updated_at = 11; common.describable.v1.Describable describable = 12; string owner_ref = 13; AccountRole role = 14; } // A single posting line (mirrors your PostingLine model) message PostingLine { string ledger_account_ref = 1; common.money.v1.Money money = 2; LineType line_type = 3; // MAIN, FEE, SPREAD, ... } // ===== Requests/Responses ===== // CreateAccountRequest is the request to create a new ledger account. message CreateAccountRequest { string organization_ref = 1; string owner_ref = 2; reserved 3; reserved "account_code"; AccountType account_type = 4; string currency = 5; AccountStatus status = 6; bool allow_negative = 7; reserved 8; reserved "is_settlement"; map metadata = 9; common.describable.v1.Describable describable = 10; AccountRole role = 11; } // CreateAccountResponse is the response for CreateAccount. message CreateAccountResponse { LedgerAccount account = 1; } // Common: optional event_time lets caller set business time; server may default to now. message PostCreditRequest { string idempotency_key = 1; string organization_ref = 2; // aligns with PermissionBound string ledger_account_ref = 3; common.money.v1.Money money = 4; string description = 5; repeated PostingLine charges = 6; // FEE/SPREAD lines (no MAIN here) map metadata = 7; google.protobuf.Timestamp event_time = 8; string contra_ledger_account_ref = 9; // optional override for settlement/contra account AccountRole role = 10; // optional: assert target account has this role } // PostDebitRequest is the request to post a debit entry. message PostDebitRequest { string idempotency_key = 1; string organization_ref = 2; string ledger_account_ref = 3; common.money.v1.Money money = 4; string description = 5; repeated PostingLine charges = 6; // FEE/SPREAD map metadata = 7; google.protobuf.Timestamp event_time = 8; string contra_ledger_account_ref = 9; // optional override for settlement/contra account AccountRole role = 10; // optional: assert target account has this role } // TransferRequest is the request to transfer funds between two ledger accounts. message TransferRequest { string idempotency_key = 1; string organization_ref = 2; string from_ledger_account_ref = 3; string to_ledger_account_ref = 4; common.money.v1.Money money = 5; // transfer amount/currency string description = 6; repeated PostingLine charges = 7; // optional FEE/SPREAD lines map metadata = 8; google.protobuf.Timestamp event_time = 9; AccountRole from_role = 10; AccountRole to_role = 11; } // FXRequest is the request to post a foreign-exchange conversion entry. message FXRequest { string idempotency_key = 1; string organization_ref = 2; string from_ledger_account_ref = 3; string to_ledger_account_ref = 4; common.money.v1.Money from_money = 5; // debited common.money.v1.Money to_money = 6; // credited string rate = 7; // quoted rate as string (snapshot for audit) string description = 8; repeated PostingLine charges = 9; // FEE/SPREAD lines map metadata = 10; google.protobuf.Timestamp event_time = 11; } // PostResponse is the common response returned after any posting operation. message PostResponse { string journal_entry_ref = 1; int64 version = 2; // ledger's entry version (monotonic per scope) EntryType entry_type = 3; } // ---- Balances & Entries ---- // GetBalanceRequest is the request to retrieve an account balance. message GetBalanceRequest { string ledger_account_ref = 1; } // BalanceResponse holds the current balance of a ledger account. message BalanceResponse { string ledger_account_ref = 1; common.money.v1.Money balance = 2; int64 version = 3; google.protobuf.Timestamp last_updated = 4; } // GetEntryRequest is the request to retrieve a journal entry by reference. message GetEntryRequest { string entry_ref = 1; } // JournalEntryResponse represents a complete journal entry with all posting lines. message JournalEntryResponse { string entry_ref = 1; string idempotency_key = 2; EntryType entry_type = 3; string description = 4; google.protobuf.Timestamp event_time = 5; int64 version = 6; repeated PostingLine lines = 7; map metadata = 8; repeated string ledger_account_refs = 9; // denormalized set for client-side filtering } // GetStatementRequest is the request to retrieve paginated journal entries for an account. message GetStatementRequest { string ledger_account_ref = 1; string cursor = 2; // opaque int32 limit = 3; // page size } // StatementResponse is a paginated list of journal entries. message StatementResponse { repeated JournalEntryResponse entries = 1; string next_cursor = 2; } // ListAccountsRequest is the request to list ledger accounts with optional filters. message ListAccountsRequest { string organization_ref = 1; // Optional owner filter with 3-state semantics: // - not set: return all accounts within organization // - set to empty string: return accounts where owner_ref is null/empty // - set to a value: return accounts where owner_ref matches google.protobuf.StringValue owner_ref_filter = 2; } // ListAccountsResponse is the response for ListAccounts. message ListAccountsResponse { repeated LedgerAccount accounts = 1; } // ---- Account status mutations ---- // BlockAccountRequest is the request to freeze (block) a ledger account. message BlockAccountRequest { string ledger_account_ref = 1; string organization_ref = 2; AccountRole role = 3; // optional: assert account has this role before blocking } // BlockAccountResponse is the response for BlockAccount. message BlockAccountResponse { LedgerAccount account = 1; } // UnblockAccountRequest is the request to unfreeze (unblock) a ledger account. message UnblockAccountRequest { string ledger_account_ref = 1; string organization_ref = 2; AccountRole role = 3; // optional: assert account has this role before unblocking } // UnblockAccountResponse is the response for UnblockAccount. message UnblockAccountResponse { LedgerAccount account = 1; }