syntax = "proto3"; package komp_ac.ecb; // Read-only access to ECB conversion previews and audit evidence. // // This service exists for manual visual verification before and after posting. // Preview performs the authoritative unrounded backend calculation without // writing; evidence exposes conversions already recorded by posting workflows. service EcbService { // Preview the exact conversion the backend would currently perform. // This reads local verified ECB data and never persists conversion evidence. rpc PreviewEcbConversion(PreviewEcbConversionRequest) returns (PreviewEcbConversionResponse); // List immutable ECB conversion evidence for one money value. rpc ListEcbConversionEvidence(ListEcbConversionEvidenceRequest) returns (ListEcbConversionEvidenceResponse); } // Accounting date rule used to select an ECB publication. enum EcbConversionContext { ECB_CONVERSION_CONTEXT_UNSPECIFIED = 0; ECB_CONVERSION_CONTEXT_ORDINARY_TRANSACTION = 1; ECB_CONVERSION_CONTEXT_FINANCIAL_STATEMENT = 2; ECB_CONVERSION_CONTEXT_DECISIVE_DATE = 3; } // Exact inputs for a conversion preview. Decimal values are strings so the // client never loses precision through binary floating point. message PreviewEcbConversionRequest { string original_amount = 1; string original_currency = 2; EcbConversionContext conversion_context = 3; // ISO calendar date (YYYY-MM-DD). Its meaning is selected by // conversion_context: transaction, statement, or decisive date. string anchor_date = 4; // Required. Profile whose custom exchange rate table is consulted before the // ECB observations, so the preview matches what posting into that profile // would do. string profile_name = 5; } // The conversion and immutable local ECB observation that would be used now. // No rounding is performed and no conversion evidence is persisted. message PreviewEcbConversionResponse { string original_amount = 1; string original_currency = 2; string eur_amount = 3; EcbConversionContext conversion_context = 4; string anchor_date = 5; string determination_method = 6; string rounding_method = 7; optional string rate_date = 8; optional string units_per_eur = 9; optional int64 rate_observation_id = 10; optional string observation_hash = 11; optional string source_payload_hash = 12; optional string rate_fetched_at = 13; optional int64 import_batch_id = 14; optional string source_endpoint = 15; // Present only when determination_method is custom_rate. rate_date and // units_per_eur then describe the hand-entered row identified here, and the // ECB observation fields above are empty. optional int64 custom_rate_table_definition_id = 16; optional int64 custom_rate_record_id = 17; optional int64 custom_rate_row_revision = 18; optional string custom_rate_note = 19; } // Identify one logical money cell whose conversion history should be inspected. message ListEcbConversionEvidenceRequest { // Required. Profile containing the table. string profile_name = 1; // Required. Logical table name within the profile. string table_name = 2; // Required. Dynamic table row id. int64 record_id = 3; // Required. Current display name of the money column. The server resolves it // to the stable physical column name used by immutable evidence. string column_name = 4; // Optional. Maximum rows to return. Zero uses 100; maximum is 500. int32 limit = 5; // Optional cursor. Return evidence ids lower than this value. optional int64 before_evidence_id = 6; } // One immutable explanation of how a posted EUR value was determined. message EcbConversionEvidence { int64 evidence_id = 1; // Exact committed version of the target dynamic-table row. int64 row_revision = 2; string original_amount = 3; string original_currency = 4; string eur_amount = 5; string conversion_context = 6; string anchor_date = 7; string determination_method = 8; string rounding_method = 9; optional string rate_date = 10; optional string units_per_eur = 11; optional int64 rate_observation_id = 12; optional string observation_hash = 13; optional string source_payload_hash = 14; optional string rate_fetched_at = 15; optional int64 import_batch_id = 16; optional string source_endpoint = 17; string evidence_created_at = 18; // Present only when determination_method is custom_rate. The hand-entered row // that supplied rate_date and units_per_eur. The row itself stays editable, so // the figures above are the immutable record of what was actually applied. optional int64 custom_rate_table_definition_id = 19; optional int64 custom_rate_record_id = 20; optional int64 custom_rate_row_revision = 21; optional string custom_rate_note = 22; } message ListEcbConversionEvidenceResponse { // True when at least one evidence row for this cell used a rate, whether it // came from ECB or from a hand-entered custom row. bool has_exchange = 1; // Newest-first immutable history for this page. repeated EcbConversionEvidence evidence = 2; // True when another page exists using the last evidence_id as the cursor. bool has_more = 3; }