540 lines
18 KiB
Protocol Buffer
540 lines
18 KiB
Protocol Buffer
syntax = "proto3";
|
|
package komp_ac.accounting;
|
|
|
|
import "ecb.proto";
|
|
|
|
// Mutable informational journals. A journal may contain only debits, only
|
|
// credits, or any non-zero balance. Balance is reported but never enforced.
|
|
// Accounting periods close date ranges inside a profile and freeze account sums
|
|
// without replacing the live accounts projection. Closed periods can be reopened;
|
|
// approved periods are final.
|
|
service Accounting {
|
|
// Resolve or atomically create every node in a parsed account path.
|
|
rpc EnsureAccount(EnsureAccountRequest) returns (Account);
|
|
|
|
// Create a journal with its first lines when journal_id is absent, or append
|
|
// all supplied lines atomically when journal_id identifies an existing one.
|
|
rpc PostJournal(PostJournalRequest) returns (Journal);
|
|
|
|
// Close a balanced journal. Closed journals can be reopened while their
|
|
// accounting period is open.
|
|
rpc CloseJournal(CloseJournalRequest) returns (Journal);
|
|
rpc ReopenJournal(ReopenJournalRequest) returns (Journal);
|
|
|
|
// Return journal lines and credits-minus-debits informational balance.
|
|
rpc GetJournal(GetJournalRequest) returns (Journal);
|
|
|
|
// Search profile journals by user-facing name while retaining journal ids
|
|
// as the stable relationship keys.
|
|
rpc SearchJournals(SearchJournalsRequest) returns (SearchJournalsResponse);
|
|
|
|
// Return the profile-wide count of balanced and unbalanced journals.
|
|
rpc GetAccountingStatus(GetAccountingStatusRequest) returns (AccountingStatus);
|
|
|
|
// Return an oldest-first, paginated queue of unbalanced journals.
|
|
rpc ListUnbalancedJournals(ListUnbalancedJournalsRequest)
|
|
returns (ListUnbalancedJournalsResponse);
|
|
|
|
// Soft-delete one line while retaining it for audit display.
|
|
rpc SoftDeleteJournalLine(SoftDeleteJournalLineRequest) returns (Journal);
|
|
|
|
// Atomically supersede active lines and append corrected replacements. The
|
|
// originals and their conversion evidence remain immutable audit history.
|
|
rpc CorrectJournal(CorrectJournalRequest) returns (Journal);
|
|
|
|
// Create an open accounting period for a profile. Periods may be any length
|
|
// (month, half-year, year). Overlapping ranges for the same profile are rejected.
|
|
rpc ConfigureAccountingPeriod(ConfigureAccountingPeriodRequest)
|
|
returns (AccountingPeriod);
|
|
|
|
// Closing snapshots balances and blocks mutations through the period end.
|
|
// A closed period may be reopened until the profile is approved.
|
|
rpc CloseAccountingPeriod(CloseAccountingPeriodRequest) returns (AccountingPeriod);
|
|
rpc ReopenAccountingPeriod(ReopenAccountingPeriodRequest) returns (AccountingPeriod);
|
|
|
|
// Approves the profile's financial statement. One profile is one accounting
|
|
// period, and approval happens once for it, not once per period inside it.
|
|
// Every period must be closed first, and none may be reopened afterwards.
|
|
rpc ApproveProfile(ApproveProfileRequest) returns (ProfileApproval);
|
|
rpc GetProfileApproval(GetProfileApprovalRequest) returns (ProfileApproval);
|
|
|
|
rpc GetAccountingPeriod(GetAccountingPeriodRequest) returns (AccountingPeriod);
|
|
rpc ListAccountingPeriods(ListAccountingPeriodsRequest)
|
|
returns (ListAccountingPeriodsResponse);
|
|
rpc ListPeriodBalances(ListPeriodBalancesRequest) returns (ListPeriodBalancesResponse);
|
|
|
|
// Materialize one row per directly transferable source account in a table
|
|
// containing an ACCOUNTING_TRANSFER definition. Source fields are frozen
|
|
// accounting facts; target fields start as an unchanged same-path copy and
|
|
// may then be changed by the table's Steel logic or by the user.
|
|
rpc GenerateAccountingTransfer(GenerateAccountingTransferRequest)
|
|
returns (GenerateAccountingTransferResponse);
|
|
|
|
// Administratively map one account in a predecessor profile to one account
|
|
// in the current profile. Existing activity on the target account is allowed.
|
|
rpc MapOpeningBalanceAccount(MapOpeningBalanceAccountRequest)
|
|
returns (OpeningBalanceAccountMapping);
|
|
rpc UnmapOpeningBalanceAccount(UnmapOpeningBalanceAccountRequest)
|
|
returns (UnmapOpeningBalanceAccountResponse);
|
|
rpc ListOpeningBalanceAccounts(ListOpeningBalanceAccountsRequest)
|
|
returns (ListOpeningBalanceAccountsResponse);
|
|
}
|
|
|
|
message EnsureAccountRequest {
|
|
string profile_name = 1;
|
|
// Slash-delimited root-to-leaf account path, for example "123/12/1".
|
|
string account = 2;
|
|
// Currency accepted by source postings to the leaf account. Empty uses the
|
|
// profile accounting currency. Missing ancestors are created in the profile
|
|
// accounting currency.
|
|
string denomination_currency = 3;
|
|
}
|
|
|
|
message Account {
|
|
int64 id = 1;
|
|
optional int64 parent_account_id = 2;
|
|
string segment = 3;
|
|
// Slash-delimited root-to-leaf account path.
|
|
string account = 4;
|
|
string denomination_currency = 5;
|
|
}
|
|
|
|
enum JournalSide {
|
|
JOURNAL_SIDE_UNSPECIFIED = 0;
|
|
JOURNAL_SIDE_DEBIT = 1;
|
|
JOURNAL_SIDE_CREDIT = 2;
|
|
}
|
|
|
|
// A period is only ever open or closed. Approval is a fact about the whole
|
|
// profile, because the profile is the accounting period being reported on.
|
|
enum AccountingPeriodStatus {
|
|
ACCOUNTING_PERIOD_STATUS_UNSPECIFIED = 0;
|
|
ACCOUNTING_PERIOD_STATUS_OPEN = 1;
|
|
ACCOUNTING_PERIOD_STATUS_CLOSED = 2;
|
|
}
|
|
|
|
// How long one accounting period lasts. MONTH and YEAR span whole months, so
|
|
// the caller states only the start and the end is derived. PARTIAL is the
|
|
// exception for periods real life cut short.
|
|
enum AccountingPeriodType {
|
|
ACCOUNTING_PERIOD_TYPE_UNSPECIFIED = 0;
|
|
// One calendar month.
|
|
ACCOUNTING_PERIOD_TYPE_MONTH = 1;
|
|
// Twelve consecutive months. Starting in January gives the calendar year;
|
|
// any other start month gives a business year (hospodársky rok).
|
|
ACCOUNTING_PERIOD_TYPE_YEAR = 2;
|
|
// Neither a whole month nor a whole year, because the entity was formed or
|
|
// terminated part-way through one. The only type carrying an explicit end.
|
|
ACCOUNTING_PERIOD_TYPE_PARTIAL = 3;
|
|
}
|
|
|
|
message PostJournalRequest {
|
|
string profile_name = 1;
|
|
|
|
// Absent creates a new journal. Present must identify an existing journal;
|
|
// an unknown id is never treated as a request to create one.
|
|
optional int64 journal_id = 2;
|
|
|
|
// Currency of the amounts supplied by this request. Required when creating;
|
|
// empty uses the profile accounting currency when appending. Journal amounts
|
|
// are stored and returned in the profile accounting currency.
|
|
string currency = 3;
|
|
|
|
// Applied when creating and required to be empty when appending.
|
|
string description = 4;
|
|
|
|
// At least one line is required. The lines are inserted atomically and the
|
|
// journal is allowed to remain unbalanced.
|
|
repeated JournalLineInput lines = 5;
|
|
|
|
// Required, unique within the profile, and at most 10 characters when
|
|
// creating. Must be empty when appending to an existing journal selected by
|
|
// journal_id.
|
|
string journal_name = 6;
|
|
|
|
// Accounting date in YYYY-MM-DD. Empty defaults to the current UTC date when
|
|
// creating. Must be empty when appending. Rejected when it falls at or before
|
|
// the latest closed or approved accounting boundary for the profile.
|
|
string accounting_date = 7;
|
|
|
|
}
|
|
|
|
message JournalLineInput {
|
|
JournalSide side = 1;
|
|
// Slash-delimited root-to-leaf account path.
|
|
string account = 2;
|
|
string amount = 3;
|
|
string description = 4;
|
|
// Empty uses previous publication and ECB. Set this per line when the
|
|
// accountant needs a different rule, a saved custom rate, or a one-off rate.
|
|
optional komp_ac.ecb.ExchangeRateSelection exchange_rate_selection = 5;
|
|
}
|
|
|
|
message CloseJournalRequest {
|
|
string profile_name = 1;
|
|
int64 journal_id = 2;
|
|
}
|
|
|
|
message ReopenJournalRequest {
|
|
string profile_name = 1;
|
|
int64 journal_id = 2;
|
|
}
|
|
|
|
message GetJournalRequest {
|
|
string profile_name = 1;
|
|
int64 journal_id = 2;
|
|
|
|
// False returns the live journal. True also returns superseded/deleted lines
|
|
// so an authorized journal reader can inspect the correction trail.
|
|
bool include_deleted = 3;
|
|
}
|
|
|
|
message GetAccountingStatusRequest {
|
|
string profile_name = 1;
|
|
}
|
|
|
|
message SearchJournalsRequest {
|
|
string profile_name = 1;
|
|
|
|
// Case-insensitive literal substring. Empty returns all profile journals.
|
|
string name_query = 2;
|
|
|
|
// Zero uses 50. The maximum is 500.
|
|
int32 page_size = 3;
|
|
|
|
// Opaque cursor returned by the previous response.
|
|
string page_token = 4;
|
|
}
|
|
|
|
message JournalSummary {
|
|
int64 journal_id = 1;
|
|
string journal_name = 2;
|
|
string currency = 3;
|
|
string description = 4;
|
|
string total_debit = 5;
|
|
string total_credit = 6;
|
|
string balance = 7;
|
|
int64 active_line_count = 8;
|
|
bool closed = 9;
|
|
string created_at = 10;
|
|
string accounting_date = 11;
|
|
}
|
|
|
|
message SearchJournalsResponse {
|
|
repeated JournalSummary journals = 1;
|
|
int64 total_count = 2;
|
|
string next_page_token = 3;
|
|
}
|
|
|
|
message AccountingStatus {
|
|
bool all_journals_balanced = 1;
|
|
int64 journal_count = 2;
|
|
int64 balanced_journal_count = 3;
|
|
int64 unbalanced_journal_count = 4;
|
|
string calculated_at = 5;
|
|
}
|
|
|
|
message ListUnbalancedJournalsRequest {
|
|
string profile_name = 1;
|
|
|
|
// Zero uses 50. The maximum is 500.
|
|
int32 page_size = 2;
|
|
|
|
// Opaque cursor returned by the previous response. Empty starts at the
|
|
// oldest unbalanced journal.
|
|
string page_token = 3;
|
|
|
|
// Optional ISO 4217 currency filter. Empty includes every currency.
|
|
string currency = 4;
|
|
}
|
|
|
|
message UnbalancedJournalSummary {
|
|
int64 journal_id = 1;
|
|
string description = 2;
|
|
string currency = 3;
|
|
string total_debit = 4;
|
|
string total_credit = 5;
|
|
|
|
// Signed credits-minus-debits difference.
|
|
string balance = 6;
|
|
|
|
// Side and positive amount needed to make the journal balance zero.
|
|
JournalSide missing_side = 7;
|
|
string missing_amount = 8;
|
|
int64 active_line_count = 9;
|
|
string created_at = 10;
|
|
string journal_name = 11;
|
|
string accounting_date = 12;
|
|
}
|
|
|
|
message ListUnbalancedJournalsResponse {
|
|
repeated UnbalancedJournalSummary journals = 1;
|
|
int64 total_unbalanced_count = 2;
|
|
string next_page_token = 3;
|
|
}
|
|
|
|
message SoftDeleteJournalLineRequest {
|
|
string profile_name = 1;
|
|
int64 journal_id = 2;
|
|
int64 journal_line_id = 3;
|
|
}
|
|
|
|
message CorrectJournalRequest {
|
|
string profile_name = 1;
|
|
int64 journal_id = 2;
|
|
// One or more line replacements committed as a single correction. Batching
|
|
// lets both sides of a closed balanced journal be corrected together.
|
|
repeated JournalLineCorrection corrections = 3;
|
|
}
|
|
|
|
message JournalLineCorrection {
|
|
int64 journal_line_id = 1;
|
|
// Full replacement line. Its amount is expressed in currency.
|
|
JournalLineInput replacement = 2;
|
|
string currency = 3;
|
|
// Required independently of any exceptional exchange-rate reason and stored
|
|
// permanently beside this original/replacement pair.
|
|
string correction_reason = 4;
|
|
}
|
|
|
|
message JournalLine {
|
|
int64 id = 1;
|
|
int32 line_number = 2;
|
|
JournalSide side = 3;
|
|
// Slash-delimited root-to-leaf path of the posted account.
|
|
string account = 4;
|
|
string amount = 5;
|
|
string description = 6;
|
|
bool deleted = 7;
|
|
string created_at = 8;
|
|
string deleted_at = 9;
|
|
string source_table_name = 10;
|
|
int64 source_record_id = 11;
|
|
int64 source_row_revision = 12;
|
|
// Populated on a replacement created by CorrectJournal.
|
|
int64 supersedes_line_id = 13;
|
|
string correction_reason = 14;
|
|
string corrected_by_user_id = 15;
|
|
// Original foreign-currency input and immutable conversion evidence. Empty/
|
|
// zero when the line did not require conversion.
|
|
string original_amount = 16;
|
|
string original_currency = 17;
|
|
int64 conversion_evidence_id = 18;
|
|
}
|
|
|
|
message Journal {
|
|
int64 id = 1;
|
|
string profile_name = 2;
|
|
string currency = 3;
|
|
string description = 4;
|
|
string created_at = 5;
|
|
repeated JournalLine lines = 6;
|
|
string total_debit = 7;
|
|
string total_credit = 8;
|
|
// Informational difference calculated as credits minus debits.
|
|
string balance = 9;
|
|
bool closed = 10;
|
|
string closed_at = 11;
|
|
string closed_by_user_id = 12;
|
|
string journal_name = 13;
|
|
string accounting_date = 14;
|
|
}
|
|
|
|
message ConfigureAccountingPeriodRequest {
|
|
string profile_name = 1;
|
|
// First day of the period, YYYY-MM-DD. Must be the first day of a month.
|
|
string period_start = 2;
|
|
// Optional link to the preceding period in a carry chain.
|
|
optional int64 previous_period_id = 4;
|
|
// Required. Decides the length of the period.
|
|
AccountingPeriodType period_type = 5;
|
|
// Last day of the period, YYYY-MM-DD. Required for PARTIAL and rejected for
|
|
// every other type, whose end follows from the start.
|
|
string period_end = 6;
|
|
}
|
|
|
|
message CloseAccountingPeriodRequest {
|
|
int64 period_id = 1;
|
|
}
|
|
|
|
message ReopenAccountingPeriodRequest {
|
|
int64 period_id = 1;
|
|
}
|
|
|
|
message ApproveProfileRequest {
|
|
string profile_name = 1;
|
|
}
|
|
|
|
message GetProfileApprovalRequest {
|
|
string profile_name = 1;
|
|
}
|
|
|
|
// Approval state of one profile's financial statement.
|
|
message ProfileApproval {
|
|
string profile_name = 1;
|
|
bool approved = 2;
|
|
// Empty while the profile is unapproved.
|
|
string approved_at = 3;
|
|
string approved_by_user_id = 4;
|
|
}
|
|
|
|
message GetAccountingPeriodRequest {
|
|
int64 period_id = 1;
|
|
}
|
|
|
|
message ListAccountingPeriodsRequest {
|
|
string profile_name = 1;
|
|
}
|
|
|
|
message ListAccountingPeriodsResponse {
|
|
repeated AccountingPeriod periods = 1;
|
|
}
|
|
|
|
message AccountingPeriod {
|
|
int64 id = 1;
|
|
string profile_name = 2;
|
|
string period_start = 3;
|
|
string period_end = 4;
|
|
AccountingPeriodStatus status = 5;
|
|
int64 previous_period_id = 6;
|
|
string closed_at = 7;
|
|
string closed_by_user_id = 8;
|
|
AccountingPeriodType period_type = 11;
|
|
}
|
|
|
|
message ListPeriodBalancesRequest {
|
|
int64 period_id = 1;
|
|
}
|
|
|
|
message PeriodBalance {
|
|
int64 period_id = 1;
|
|
// Slash-delimited root-to-leaf path of this frozen balance's account.
|
|
string account = 2;
|
|
string currency = 3;
|
|
// Signed nets use debit-positive convention.
|
|
string opening_balance = 4;
|
|
string period_debit = 5;
|
|
string period_credit = 6;
|
|
string closing_balance = 7;
|
|
}
|
|
|
|
message PeriodDenominationBalance {
|
|
int64 period_id = 1;
|
|
// Exact denominated account. Unlike book balances, this quantity is not
|
|
// rolled up into parent accounts with a different denomination.
|
|
string account = 2;
|
|
string denomination_currency = 3;
|
|
// Signed nets use debit-positive convention and remain in the denomination
|
|
// currency without conversion during carry-forward.
|
|
string opening_quantity = 4;
|
|
string period_debit_quantity = 5;
|
|
string period_credit_quantity = 6;
|
|
string closing_quantity = 7;
|
|
}
|
|
|
|
message ListPeriodBalancesResponse {
|
|
repeated PeriodBalance balances = 1;
|
|
repeated PeriodDenominationBalance denomination_balances = 2;
|
|
}
|
|
|
|
message GenerateAccountingTransferRequest {
|
|
string profile_name = 1;
|
|
string table_name = 2;
|
|
int64 source_period_id = 3;
|
|
int64 target_period_id = 4;
|
|
}
|
|
|
|
message GenerateAccountingTransferResponse {
|
|
int64 table_definition_id = 1;
|
|
int64 generated_row_count = 2;
|
|
}
|
|
|
|
message MapOpeningBalanceAccountRequest {
|
|
// Open period whose profile receives the opening balance. Its configured
|
|
// previous_period_id identifies the source profile and period.
|
|
int64 target_period_id = 1;
|
|
string source_account = 2;
|
|
string target_account = 3;
|
|
}
|
|
|
|
message UnmapOpeningBalanceAccountRequest {
|
|
int64 target_period_id = 1;
|
|
string target_account = 2;
|
|
}
|
|
|
|
message UnmapOpeningBalanceAccountResponse {
|
|
bool removed = 1;
|
|
}
|
|
|
|
message ListOpeningBalanceAccountsRequest {
|
|
int64 target_period_id = 1;
|
|
}
|
|
|
|
enum OpeningBalanceStatus {
|
|
OPENING_BALANCE_STATUS_UNSPECIFIED = 0;
|
|
// The predecessor is still open, so its closed journal activity can change.
|
|
OPENING_BALANCE_STATUS_PROVISIONAL = 1;
|
|
// The value comes from the predecessor's frozen period snapshot.
|
|
OPENING_BALANCE_STATUS_FINAL = 2;
|
|
}
|
|
|
|
message OpeningBalanceAccountMapping {
|
|
int64 target_period_id = 1;
|
|
int64 source_period_id = 2;
|
|
string source_profile_name = 3;
|
|
string source_account = 4;
|
|
string target_profile_name = 5;
|
|
string target_account = 6;
|
|
string currency = 7;
|
|
// Signed balances use the debit-positive convention.
|
|
string opening_balance = 8;
|
|
string period_debit = 9;
|
|
string period_credit = 10;
|
|
string current_balance = 11;
|
|
OpeningBalanceStatus status = 12;
|
|
string created_at = 13;
|
|
string created_by_user_id = 14;
|
|
string denomination_currency = 15;
|
|
string denomination_opening_quantity = 16;
|
|
string denomination_period_debit_quantity = 17;
|
|
string denomination_period_credit_quantity = 18;
|
|
string denomination_current_quantity = 19;
|
|
}
|
|
|
|
// A portion of a predecessor account's value that no mapping carries into the
|
|
// target period. Closing the target period drops this value, so each entry must
|
|
// either be covered by a broader mapping or deliberately closed out.
|
|
message UnmappedSourceBalance {
|
|
int64 source_period_id = 1;
|
|
string source_profile_name = 2;
|
|
string source_account = 3;
|
|
string currency = 4;
|
|
// Signed portion not covered by a mapping, using the debit-positive
|
|
// convention. This is never zero and may be less than the account's
|
|
// aggregate closing balance when descendants are mapped separately.
|
|
string unmapped_balance = 5;
|
|
OpeningBalanceStatus status = 6;
|
|
}
|
|
|
|
message UnmappedSourceDenominationBalance {
|
|
int64 source_period_id = 1;
|
|
string source_profile_name = 2;
|
|
string source_account = 3;
|
|
string denomination_currency = 4;
|
|
// Exact foreign-currency quantity that no mapping carries forward.
|
|
string unmapped_quantity = 5;
|
|
OpeningBalanceStatus status = 6;
|
|
}
|
|
|
|
message ListOpeningBalanceAccountsResponse {
|
|
repeated OpeningBalanceAccountMapping mappings = 1;
|
|
|
|
// Empty while the target period still inherits every predecessor balance by
|
|
// account path. Populated once the period carries balances by explicit
|
|
// mapping only, which happens when the predecessor belongs to another
|
|
// profile or when the period has at least one mapping of its own.
|
|
repeated UnmappedSourceBalance unmapped_source_balances = 2;
|
|
repeated UnmappedSourceDenominationBalance
|
|
unmapped_source_denomination_balances = 3;
|
|
}
|