syntax = "proto3"; package ledger.v1; option go_package = "github.com/tech/sendico/pkg/proto/ledger/v1;ledgerv1"; import "google/protobuf/timestamp.proto"; import "common/money/v1/money.proto"; // ===== Enums ===== enum EntryType { ENTRY_TYPE_UNSPECIFIED = 0; ENTRY_CREDIT = 1; ENTRY_DEBIT = 2; ENTRY_TRANSFER = 3; ENTRY_FX = 4; ENTRY_FEE = 5; ENTRY_ADJUST = 6; ENTRY_REVERSE = 7; } enum LineType { LINE_TYPE_UNSPECIFIED = 0; LINE_MAIN = 1; LINE_FEE = 2; LINE_SPREAD = 3; LINE_REVERSAL = 4; } enum AccountType { ACCOUNT_TYPE_UNSPECIFIED = 0; ACCOUNT_TYPE_ASSET = 1; ACCOUNT_TYPE_LIABILITY = 2; ACCOUNT_TYPE_REVENUE = 3; ACCOUNT_TYPE_EXPENSE = 4; } enum AccountStatus { ACCOUNT_STATUS_UNSPECIFIED = 0; ACCOUNT_STATUS_ACTIVE = 1; ACCOUNT_STATUS_FROZEN = 2; } // 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; bool is_settlement = 8; map metadata = 9; google.protobuf.Timestamp created_at = 10; google.protobuf.Timestamp updated_at = 11; } // 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 ===== message CreateAccountRequest { string organization_ref = 1; string account_code = 2; AccountType account_type = 3; string currency = 4; AccountStatus status = 5; bool allow_negative = 6; bool is_settlement = 7; map metadata = 8; } 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 } 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 } 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; } 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; } message PostResponse { string journal_entry_ref = 1; int64 version = 2; // ledger's entry version (monotonic per scope) EntryType entry_type = 3; } // ---- Balances & Entries ---- message GetBalanceRequest { string ledger_account_ref = 1; } message BalanceResponse { string ledger_account_ref = 1; common.money.v1.Money balance = 2; int64 version = 3; google.protobuf.Timestamp last_updated = 4; } message GetEntryRequest { string entry_ref = 1; } 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 } message GetStatementRequest { string ledger_account_ref = 1; string cursor = 2; // opaque int32 limit = 3; // page size } message StatementResponse { repeated JournalEntryResponse entries = 1; string next_cursor = 2; } message ListAccountsRequest { string organization_ref = 1; } message ListAccountsResponse { repeated LedgerAccount accounts = 1; }