From 8146bce65482fc2448e063d2b56e9685f846b2a2 Mon Sep 17 00:00:00 2001 From: Priec Date: Sun, 26 Jul 2026 11:58:09 +0200 Subject: [PATCH] accounting locking --- common/proto/accounting.proto | 121 +++- common/src/proto/descriptor.bin | Bin 123126 -> 129881 bytes common/src/proto/komp_ac.accounting.rs | 861 ++++++++++++++++++++++++- server | 2 +- 4 files changed, 953 insertions(+), 31 deletions(-) diff --git a/common/proto/accounting.proto b/common/proto/accounting.proto index 37bfa0e..10fc82a 100644 --- a/common/proto/accounting.proto +++ b/common/proto/accounting.proto @@ -3,14 +3,18 @@ package komp_ac.accounting; // 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 { // 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); - // Permanently lock a balanced journal. This is an explicit action; becoming - // balanced never locks a journal automatically. - rpc LockJournal(LockJournalRequest) 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); @@ -28,6 +32,22 @@ service Accounting { // Soft-delete one line while retaining it for audit display. rpc SoftDeleteJournalLine(SoftDeleteJournalLineRequest) 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; approval makes it final. + rpc CloseAccountingPeriod(CloseAccountingPeriodRequest) returns (AccountingPeriod); + rpc ReopenAccountingPeriod(ReopenAccountingPeriodRequest) returns (AccountingPeriod); + rpc ApproveAccountingPeriod(ApproveAccountingPeriodRequest) returns (AccountingPeriod); + + rpc GetAccountingPeriod(GetAccountingPeriodRequest) returns (AccountingPeriod); + rpc ListAccountingPeriods(ListAccountingPeriodsRequest) + returns (ListAccountingPeriodsResponse); + rpc ListPeriodBalances(ListPeriodBalancesRequest) returns (ListPeriodBalancesResponse); } enum JournalSide { @@ -36,6 +56,13 @@ enum JournalSide { JOURNAL_SIDE_CREDIT = 2; } +enum AccountingPeriodStatus { + ACCOUNTING_PERIOD_STATUS_UNSPECIFIED = 0; + ACCOUNTING_PERIOD_STATUS_OPEN = 1; + ACCOUNTING_PERIOD_STATUS_CLOSED = 2; + ACCOUNTING_PERIOD_STATUS_APPROVED = 3; +} + message PostJournalRequest { string profile_name = 1; @@ -58,6 +85,11 @@ message PostJournalRequest { // 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 { @@ -67,7 +99,12 @@ message JournalLineInput { string description = 4; } -message LockJournalRequest { +message CloseJournalRequest { + string profile_name = 1; + int64 journal_id = 2; +} + +message ReopenJournalRequest { string profile_name = 1; int64 journal_id = 2; } @@ -107,8 +144,9 @@ message JournalSummary { string total_credit = 6; string balance = 7; int64 active_line_count = 8; - bool locked = 9; + bool closed = 9; string created_at = 10; + string accounting_date = 11; } message SearchJournalsResponse { @@ -155,6 +193,7 @@ message UnbalancedJournalSummary { int64 active_line_count = 9; string created_at = 10; string journal_name = 11; + string accounting_date = 12; } message ListUnbalancedJournalsResponse { @@ -196,8 +235,74 @@ message Journal { string total_credit = 8; // Informational difference calculated as credits minus debits. string balance = 9; - bool locked = 10; - string locked_at = 11; - string locked_by_user_id = 12; + 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; + // Inclusive range in YYYY-MM-DD. + string period_start = 2; + string period_end = 3; + // Optional link to the preceding period in a carry chain. + optional int64 previous_period_id = 4; +} + +message CloseAccountingPeriodRequest { + int64 period_id = 1; +} + +message ReopenAccountingPeriodRequest { + int64 period_id = 1; +} + +message ApproveAccountingPeriodRequest { + int64 period_id = 1; +} + +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; + string approved_at = 9; + string approved_by_user_id = 10; +} + +message ListPeriodBalancesRequest { + int64 period_id = 1; +} + +message PeriodBalance { + int64 period_id = 1; + string account_code = 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 ListPeriodBalancesResponse { + repeated PeriodBalance balances = 1; } diff --git a/common/src/proto/descriptor.bin b/common/src/proto/descriptor.bin index abffa43aa2af07647119ea5434d87bb5269622e4..2c09d325fca16a0735ff728eb486771184344e0b 100644 GIT binary patch delta 12436 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 J)~kPC`adkhG)w>h diff --git a/common/src/proto/komp_ac.accounting.rs b/common/src/proto/komp_ac.accounting.rs index 5530fc4..d92a5e7 100644 --- a/common/src/proto/komp_ac.accounting.rs +++ b/common/src/proto/komp_ac.accounting.rs @@ -23,6 +23,11 @@ pub struct PostJournalRequest { /// journal_id. #[prost(string, tag = "6")] pub journal_name: ::prost::alloc::string::String, + /// 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. + #[prost(string, tag = "7")] + pub accounting_date: ::prost::alloc::string::String, } #[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)] pub struct JournalLineInput { @@ -36,7 +41,14 @@ pub struct JournalLineInput { pub description: ::prost::alloc::string::String, } #[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)] -pub struct LockJournalRequest { +pub struct CloseJournalRequest { + #[prost(string, tag = "1")] + pub profile_name: ::prost::alloc::string::String, + #[prost(int64, tag = "2")] + pub journal_id: i64, +} +#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)] +pub struct ReopenJournalRequest { #[prost(string, tag = "1")] pub profile_name: ::prost::alloc::string::String, #[prost(int64, tag = "2")] @@ -91,9 +103,11 @@ pub struct JournalSummary { #[prost(int64, tag = "8")] pub active_line_count: i64, #[prost(bool, tag = "9")] - pub locked: bool, + pub closed: bool, #[prost(string, tag = "10")] pub created_at: ::prost::alloc::string::String, + #[prost(string, tag = "11")] + pub accounting_date: ::prost::alloc::string::String, } #[derive(Clone, PartialEq, ::prost::Message)] pub struct SearchJournalsResponse { @@ -158,6 +172,8 @@ pub struct UnbalancedJournalSummary { pub created_at: ::prost::alloc::string::String, #[prost(string, tag = "11")] pub journal_name: ::prost::alloc::string::String, + #[prost(string, tag = "12")] + pub accounting_date: ::prost::alloc::string::String, } #[derive(Clone, PartialEq, ::prost::Message)] pub struct ListUnbalancedJournalsResponse { @@ -226,13 +242,109 @@ pub struct Journal { #[prost(string, tag = "9")] pub balance: ::prost::alloc::string::String, #[prost(bool, tag = "10")] - pub locked: bool, + pub closed: bool, #[prost(string, tag = "11")] - pub locked_at: ::prost::alloc::string::String, + pub closed_at: ::prost::alloc::string::String, #[prost(string, tag = "12")] - pub locked_by_user_id: ::prost::alloc::string::String, + pub closed_by_user_id: ::prost::alloc::string::String, #[prost(string, tag = "13")] pub journal_name: ::prost::alloc::string::String, + #[prost(string, tag = "14")] + pub accounting_date: ::prost::alloc::string::String, +} +#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)] +pub struct ConfigureAccountingPeriodRequest { + #[prost(string, tag = "1")] + pub profile_name: ::prost::alloc::string::String, + /// Inclusive range in YYYY-MM-DD. + #[prost(string, tag = "2")] + pub period_start: ::prost::alloc::string::String, + #[prost(string, tag = "3")] + pub period_end: ::prost::alloc::string::String, + /// Optional link to the preceding period in a carry chain. + #[prost(int64, optional, tag = "4")] + pub previous_period_id: ::core::option::Option, +} +#[derive(Clone, Copy, PartialEq, Eq, Hash, ::prost::Message)] +pub struct CloseAccountingPeriodRequest { + #[prost(int64, tag = "1")] + pub period_id: i64, +} +#[derive(Clone, Copy, PartialEq, Eq, Hash, ::prost::Message)] +pub struct ReopenAccountingPeriodRequest { + #[prost(int64, tag = "1")] + pub period_id: i64, +} +#[derive(Clone, Copy, PartialEq, Eq, Hash, ::prost::Message)] +pub struct ApproveAccountingPeriodRequest { + #[prost(int64, tag = "1")] + pub period_id: i64, +} +#[derive(Clone, Copy, PartialEq, Eq, Hash, ::prost::Message)] +pub struct GetAccountingPeriodRequest { + #[prost(int64, tag = "1")] + pub period_id: i64, +} +#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)] +pub struct ListAccountingPeriodsRequest { + #[prost(string, tag = "1")] + pub profile_name: ::prost::alloc::string::String, +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct ListAccountingPeriodsResponse { + #[prost(message, repeated, tag = "1")] + pub periods: ::prost::alloc::vec::Vec, +} +#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)] +pub struct AccountingPeriod { + #[prost(int64, tag = "1")] + pub id: i64, + #[prost(string, tag = "2")] + pub profile_name: ::prost::alloc::string::String, + #[prost(string, tag = "3")] + pub period_start: ::prost::alloc::string::String, + #[prost(string, tag = "4")] + pub period_end: ::prost::alloc::string::String, + #[prost(enumeration = "AccountingPeriodStatus", tag = "5")] + pub status: i32, + #[prost(int64, tag = "6")] + pub previous_period_id: i64, + #[prost(string, tag = "7")] + pub closed_at: ::prost::alloc::string::String, + #[prost(string, tag = "8")] + pub closed_by_user_id: ::prost::alloc::string::String, + #[prost(string, tag = "9")] + pub approved_at: ::prost::alloc::string::String, + #[prost(string, tag = "10")] + pub approved_by_user_id: ::prost::alloc::string::String, +} +#[derive(Clone, Copy, PartialEq, Eq, Hash, ::prost::Message)] +pub struct ListPeriodBalancesRequest { + #[prost(int64, tag = "1")] + pub period_id: i64, +} +#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)] +pub struct PeriodBalance { + #[prost(int64, tag = "1")] + pub period_id: i64, + #[prost(string, tag = "2")] + pub account_code: ::prost::alloc::string::String, + #[prost(string, tag = "3")] + pub currency: ::prost::alloc::string::String, + /// Signed nets use debit-positive convention. + #[prost(string, tag = "4")] + pub opening_balance: ::prost::alloc::string::String, + #[prost(string, tag = "5")] + pub period_debit: ::prost::alloc::string::String, + #[prost(string, tag = "6")] + pub period_credit: ::prost::alloc::string::String, + #[prost(string, tag = "7")] + pub closing_balance: ::prost::alloc::string::String, +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct ListPeriodBalancesResponse { + #[prost(message, repeated, tag = "1")] + pub balances: ::prost::alloc::vec::Vec, } #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)] #[repr(i32)] @@ -263,6 +375,38 @@ impl JournalSide { } } } +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)] +#[repr(i32)] +pub enum AccountingPeriodStatus { + Unspecified = 0, + Open = 1, + Closed = 2, + Approved = 3, +} +impl AccountingPeriodStatus { + /// String value of the enum field names used in the ProtoBuf definition. + /// + /// The values are not transformed in any way and thus are considered stable + /// (if the ProtoBuf definition does not change) and safe for programmatic use. + pub fn as_str_name(&self) -> &'static str { + match self { + Self::Unspecified => "ACCOUNTING_PERIOD_STATUS_UNSPECIFIED", + Self::Open => "ACCOUNTING_PERIOD_STATUS_OPEN", + Self::Closed => "ACCOUNTING_PERIOD_STATUS_CLOSED", + Self::Approved => "ACCOUNTING_PERIOD_STATUS_APPROVED", + } + } + /// Creates an enum from field names used in the ProtoBuf definition. + pub fn from_str_name(value: &str) -> ::core::option::Option { + match value { + "ACCOUNTING_PERIOD_STATUS_UNSPECIFIED" => Some(Self::Unspecified), + "ACCOUNTING_PERIOD_STATUS_OPEN" => Some(Self::Open), + "ACCOUNTING_PERIOD_STATUS_CLOSED" => Some(Self::Closed), + "ACCOUNTING_PERIOD_STATUS_APPROVED" => Some(Self::Approved), + _ => None, + } + } +} /// Generated client implementations. pub mod accounting_client { #![allow( @@ -276,6 +420,9 @@ pub mod accounting_client { use tonic::codegen::http::Uri; /// 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. #[derive(Debug, Clone)] pub struct AccountingClient { inner: tonic::client::Grpc, @@ -379,11 +526,11 @@ pub mod accounting_client { .insert(GrpcMethod::new("komp_ac.accounting.Accounting", "PostJournal")); self.inner.unary(req, path, codec).await } - /// Permanently lock a balanced journal. This is an explicit action; becoming - /// balanced never locks a journal automatically. - pub async fn lock_journal( + /// Close a balanced journal. Closed journals can be reopened while their + /// accounting period is open. + pub async fn close_journal( &mut self, - request: impl tonic::IntoRequest, + request: impl tonic::IntoRequest, ) -> std::result::Result, tonic::Status> { self.inner .ready() @@ -395,11 +542,36 @@ pub mod accounting_client { })?; let codec = tonic_prost::ProstCodec::default(); let path = http::uri::PathAndQuery::from_static( - "/komp_ac.accounting.Accounting/LockJournal", + "/komp_ac.accounting.Accounting/CloseJournal", ); let mut req = request.into_request(); req.extensions_mut() - .insert(GrpcMethod::new("komp_ac.accounting.Accounting", "LockJournal")); + .insert( + GrpcMethod::new("komp_ac.accounting.Accounting", "CloseJournal"), + ); + self.inner.unary(req, path, codec).await + } + pub async fn reopen_journal( + &mut self, + request: impl tonic::IntoRequest, + ) -> std::result::Result, tonic::Status> { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::unknown( + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic_prost::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/komp_ac.accounting.Accounting/ReopenJournal", + ); + let mut req = request.into_request(); + req.extensions_mut() + .insert( + GrpcMethod::new("komp_ac.accounting.Accounting", "ReopenJournal"), + ); self.inner.unary(req, path, codec).await } /// Return journal lines and credits-minus-debits informational balance. @@ -539,6 +711,213 @@ pub mod accounting_client { ); self.inner.unary(req, path, codec).await } + /// 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. + pub async fn configure_accounting_period( + &mut self, + request: impl tonic::IntoRequest, + ) -> std::result::Result< + tonic::Response, + tonic::Status, + > { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::unknown( + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic_prost::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/komp_ac.accounting.Accounting/ConfigureAccountingPeriod", + ); + let mut req = request.into_request(); + req.extensions_mut() + .insert( + GrpcMethod::new( + "komp_ac.accounting.Accounting", + "ConfigureAccountingPeriod", + ), + ); + self.inner.unary(req, path, codec).await + } + /// Closing snapshots balances and blocks mutations through the period end. + /// A closed period may be reopened; approval makes it final. + pub async fn close_accounting_period( + &mut self, + request: impl tonic::IntoRequest, + ) -> std::result::Result< + tonic::Response, + tonic::Status, + > { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::unknown( + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic_prost::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/komp_ac.accounting.Accounting/CloseAccountingPeriod", + ); + let mut req = request.into_request(); + req.extensions_mut() + .insert( + GrpcMethod::new( + "komp_ac.accounting.Accounting", + "CloseAccountingPeriod", + ), + ); + self.inner.unary(req, path, codec).await + } + pub async fn reopen_accounting_period( + &mut self, + request: impl tonic::IntoRequest, + ) -> std::result::Result< + tonic::Response, + tonic::Status, + > { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::unknown( + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic_prost::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/komp_ac.accounting.Accounting/ReopenAccountingPeriod", + ); + let mut req = request.into_request(); + req.extensions_mut() + .insert( + GrpcMethod::new( + "komp_ac.accounting.Accounting", + "ReopenAccountingPeriod", + ), + ); + self.inner.unary(req, path, codec).await + } + pub async fn approve_accounting_period( + &mut self, + request: impl tonic::IntoRequest, + ) -> std::result::Result< + tonic::Response, + tonic::Status, + > { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::unknown( + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic_prost::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/komp_ac.accounting.Accounting/ApproveAccountingPeriod", + ); + let mut req = request.into_request(); + req.extensions_mut() + .insert( + GrpcMethod::new( + "komp_ac.accounting.Accounting", + "ApproveAccountingPeriod", + ), + ); + self.inner.unary(req, path, codec).await + } + pub async fn get_accounting_period( + &mut self, + request: impl tonic::IntoRequest, + ) -> std::result::Result< + tonic::Response, + tonic::Status, + > { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::unknown( + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic_prost::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/komp_ac.accounting.Accounting/GetAccountingPeriod", + ); + let mut req = request.into_request(); + req.extensions_mut() + .insert( + GrpcMethod::new( + "komp_ac.accounting.Accounting", + "GetAccountingPeriod", + ), + ); + self.inner.unary(req, path, codec).await + } + pub async fn list_accounting_periods( + &mut self, + request: impl tonic::IntoRequest, + ) -> std::result::Result< + tonic::Response, + tonic::Status, + > { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::unknown( + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic_prost::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/komp_ac.accounting.Accounting/ListAccountingPeriods", + ); + let mut req = request.into_request(); + req.extensions_mut() + .insert( + GrpcMethod::new( + "komp_ac.accounting.Accounting", + "ListAccountingPeriods", + ), + ); + self.inner.unary(req, path, codec).await + } + pub async fn list_period_balances( + &mut self, + request: impl tonic::IntoRequest, + ) -> std::result::Result< + tonic::Response, + tonic::Status, + > { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::unknown( + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic_prost::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/komp_ac.accounting.Accounting/ListPeriodBalances", + ); + let mut req = request.into_request(); + req.extensions_mut() + .insert( + GrpcMethod::new( + "komp_ac.accounting.Accounting", + "ListPeriodBalances", + ), + ); + self.inner.unary(req, path, codec).await + } } } /// Generated server implementations. @@ -560,11 +939,15 @@ pub mod accounting_server { &self, request: tonic::Request, ) -> std::result::Result, tonic::Status>; - /// Permanently lock a balanced journal. This is an explicit action; becoming - /// balanced never locks a journal automatically. - async fn lock_journal( + /// Close a balanced journal. Closed journals can be reopened while their + /// accounting period is open. + async fn close_journal( &self, - request: tonic::Request, + request: tonic::Request, + ) -> std::result::Result, tonic::Status>; + async fn reopen_journal( + &self, + request: tonic::Request, ) -> std::result::Result, tonic::Status>; /// Return journal lines and credits-minus-debits informational balance. async fn get_journal( @@ -601,9 +984,65 @@ pub mod accounting_server { &self, request: tonic::Request, ) -> std::result::Result, tonic::Status>; + /// 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. + async fn configure_accounting_period( + &self, + request: tonic::Request, + ) -> std::result::Result< + tonic::Response, + tonic::Status, + >; + /// Closing snapshots balances and blocks mutations through the period end. + /// A closed period may be reopened; approval makes it final. + async fn close_accounting_period( + &self, + request: tonic::Request, + ) -> std::result::Result< + tonic::Response, + tonic::Status, + >; + async fn reopen_accounting_period( + &self, + request: tonic::Request, + ) -> std::result::Result< + tonic::Response, + tonic::Status, + >; + async fn approve_accounting_period( + &self, + request: tonic::Request, + ) -> std::result::Result< + tonic::Response, + tonic::Status, + >; + async fn get_accounting_period( + &self, + request: tonic::Request, + ) -> std::result::Result< + tonic::Response, + tonic::Status, + >; + async fn list_accounting_periods( + &self, + request: tonic::Request, + ) -> std::result::Result< + tonic::Response, + tonic::Status, + >; + async fn list_period_balances( + &self, + request: tonic::Request, + ) -> std::result::Result< + tonic::Response, + tonic::Status, + >; } /// 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. #[derive(Debug)] pub struct AccountingServer { inner: Arc, @@ -725,13 +1164,13 @@ pub mod accounting_server { }; Box::pin(fut) } - "/komp_ac.accounting.Accounting/LockJournal" => { + "/komp_ac.accounting.Accounting/CloseJournal" => { #[allow(non_camel_case_types)] - struct LockJournalSvc(pub Arc); + struct CloseJournalSvc(pub Arc); impl< T: Accounting, - > tonic::server::UnaryService - for LockJournalSvc { + > tonic::server::UnaryService + for CloseJournalSvc { type Response = super::Journal; type Future = BoxFuture< tonic::Response, @@ -739,11 +1178,11 @@ pub mod accounting_server { >; fn call( &mut self, - request: tonic::Request, + request: tonic::Request, ) -> Self::Future { let inner = Arc::clone(&self.0); let fut = async move { - ::lock_journal(&inner, request).await + ::close_journal(&inner, request).await }; Box::pin(fut) } @@ -754,7 +1193,52 @@ pub mod accounting_server { let max_encoding_message_size = self.max_encoding_message_size; let inner = self.inner.clone(); let fut = async move { - let method = LockJournalSvc(inner); + let method = CloseJournalSvc(inner); + let codec = tonic_prost::ProstCodec::default(); + let mut grpc = tonic::server::Grpc::new(codec) + .apply_compression_config( + accept_compression_encodings, + send_compression_encodings, + ) + .apply_max_message_size_config( + max_decoding_message_size, + max_encoding_message_size, + ); + let res = grpc.unary(method, req).await; + Ok(res) + }; + Box::pin(fut) + } + "/komp_ac.accounting.Accounting/ReopenJournal" => { + #[allow(non_camel_case_types)] + struct ReopenJournalSvc(pub Arc); + impl< + T: Accounting, + > tonic::server::UnaryService + for ReopenJournalSvc { + type Response = super::Journal; + type Future = BoxFuture< + tonic::Response, + tonic::Status, + >; + fn call( + &mut self, + request: tonic::Request, + ) -> Self::Future { + let inner = Arc::clone(&self.0); + let fut = async move { + ::reopen_journal(&inner, request).await + }; + Box::pin(fut) + } + } + let accept_compression_encodings = self.accept_compression_encodings; + let send_compression_encodings = self.send_compression_encodings; + let max_decoding_message_size = self.max_decoding_message_size; + let max_encoding_message_size = self.max_encoding_message_size; + let inner = self.inner.clone(); + let fut = async move { + let method = ReopenJournalSvc(inner); let codec = tonic_prost::ProstCodec::default(); let mut grpc = tonic::server::Grpc::new(codec) .apply_compression_config( @@ -998,6 +1482,339 @@ pub mod accounting_server { }; Box::pin(fut) } + "/komp_ac.accounting.Accounting/ConfigureAccountingPeriod" => { + #[allow(non_camel_case_types)] + struct ConfigureAccountingPeriodSvc(pub Arc); + impl< + T: Accounting, + > tonic::server::UnaryService< + super::ConfigureAccountingPeriodRequest, + > for ConfigureAccountingPeriodSvc { + type Response = super::AccountingPeriod; + type Future = BoxFuture< + tonic::Response, + tonic::Status, + >; + fn call( + &mut self, + request: tonic::Request< + super::ConfigureAccountingPeriodRequest, + >, + ) -> Self::Future { + let inner = Arc::clone(&self.0); + let fut = async move { + ::configure_accounting_period( + &inner, + request, + ) + .await + }; + Box::pin(fut) + } + } + let accept_compression_encodings = self.accept_compression_encodings; + let send_compression_encodings = self.send_compression_encodings; + let max_decoding_message_size = self.max_decoding_message_size; + let max_encoding_message_size = self.max_encoding_message_size; + let inner = self.inner.clone(); + let fut = async move { + let method = ConfigureAccountingPeriodSvc(inner); + let codec = tonic_prost::ProstCodec::default(); + let mut grpc = tonic::server::Grpc::new(codec) + .apply_compression_config( + accept_compression_encodings, + send_compression_encodings, + ) + .apply_max_message_size_config( + max_decoding_message_size, + max_encoding_message_size, + ); + let res = grpc.unary(method, req).await; + Ok(res) + }; + Box::pin(fut) + } + "/komp_ac.accounting.Accounting/CloseAccountingPeriod" => { + #[allow(non_camel_case_types)] + struct CloseAccountingPeriodSvc(pub Arc); + impl< + T: Accounting, + > tonic::server::UnaryService + for CloseAccountingPeriodSvc { + type Response = super::AccountingPeriod; + type Future = BoxFuture< + tonic::Response, + tonic::Status, + >; + fn call( + &mut self, + request: tonic::Request, + ) -> Self::Future { + let inner = Arc::clone(&self.0); + let fut = async move { + ::close_accounting_period(&inner, request) + .await + }; + Box::pin(fut) + } + } + let accept_compression_encodings = self.accept_compression_encodings; + let send_compression_encodings = self.send_compression_encodings; + let max_decoding_message_size = self.max_decoding_message_size; + let max_encoding_message_size = self.max_encoding_message_size; + let inner = self.inner.clone(); + let fut = async move { + let method = CloseAccountingPeriodSvc(inner); + let codec = tonic_prost::ProstCodec::default(); + let mut grpc = tonic::server::Grpc::new(codec) + .apply_compression_config( + accept_compression_encodings, + send_compression_encodings, + ) + .apply_max_message_size_config( + max_decoding_message_size, + max_encoding_message_size, + ); + let res = grpc.unary(method, req).await; + Ok(res) + }; + Box::pin(fut) + } + "/komp_ac.accounting.Accounting/ReopenAccountingPeriod" => { + #[allow(non_camel_case_types)] + struct ReopenAccountingPeriodSvc(pub Arc); + impl< + T: Accounting, + > tonic::server::UnaryService + for ReopenAccountingPeriodSvc { + type Response = super::AccountingPeriod; + type Future = BoxFuture< + tonic::Response, + tonic::Status, + >; + fn call( + &mut self, + request: tonic::Request, + ) -> Self::Future { + let inner = Arc::clone(&self.0); + let fut = async move { + ::reopen_accounting_period(&inner, request) + .await + }; + Box::pin(fut) + } + } + let accept_compression_encodings = self.accept_compression_encodings; + let send_compression_encodings = self.send_compression_encodings; + let max_decoding_message_size = self.max_decoding_message_size; + let max_encoding_message_size = self.max_encoding_message_size; + let inner = self.inner.clone(); + let fut = async move { + let method = ReopenAccountingPeriodSvc(inner); + let codec = tonic_prost::ProstCodec::default(); + let mut grpc = tonic::server::Grpc::new(codec) + .apply_compression_config( + accept_compression_encodings, + send_compression_encodings, + ) + .apply_max_message_size_config( + max_decoding_message_size, + max_encoding_message_size, + ); + let res = grpc.unary(method, req).await; + Ok(res) + }; + Box::pin(fut) + } + "/komp_ac.accounting.Accounting/ApproveAccountingPeriod" => { + #[allow(non_camel_case_types)] + struct ApproveAccountingPeriodSvc(pub Arc); + impl< + T: Accounting, + > tonic::server::UnaryService + for ApproveAccountingPeriodSvc { + type Response = super::AccountingPeriod; + type Future = BoxFuture< + tonic::Response, + tonic::Status, + >; + fn call( + &mut self, + request: tonic::Request< + super::ApproveAccountingPeriodRequest, + >, + ) -> Self::Future { + let inner = Arc::clone(&self.0); + let fut = async move { + ::approve_accounting_period( + &inner, + request, + ) + .await + }; + Box::pin(fut) + } + } + let accept_compression_encodings = self.accept_compression_encodings; + let send_compression_encodings = self.send_compression_encodings; + let max_decoding_message_size = self.max_decoding_message_size; + let max_encoding_message_size = self.max_encoding_message_size; + let inner = self.inner.clone(); + let fut = async move { + let method = ApproveAccountingPeriodSvc(inner); + let codec = tonic_prost::ProstCodec::default(); + let mut grpc = tonic::server::Grpc::new(codec) + .apply_compression_config( + accept_compression_encodings, + send_compression_encodings, + ) + .apply_max_message_size_config( + max_decoding_message_size, + max_encoding_message_size, + ); + let res = grpc.unary(method, req).await; + Ok(res) + }; + Box::pin(fut) + } + "/komp_ac.accounting.Accounting/GetAccountingPeriod" => { + #[allow(non_camel_case_types)] + struct GetAccountingPeriodSvc(pub Arc); + impl< + T: Accounting, + > tonic::server::UnaryService + for GetAccountingPeriodSvc { + type Response = super::AccountingPeriod; + type Future = BoxFuture< + tonic::Response, + tonic::Status, + >; + fn call( + &mut self, + request: tonic::Request, + ) -> Self::Future { + let inner = Arc::clone(&self.0); + let fut = async move { + ::get_accounting_period(&inner, request) + .await + }; + Box::pin(fut) + } + } + let accept_compression_encodings = self.accept_compression_encodings; + let send_compression_encodings = self.send_compression_encodings; + let max_decoding_message_size = self.max_decoding_message_size; + let max_encoding_message_size = self.max_encoding_message_size; + let inner = self.inner.clone(); + let fut = async move { + let method = GetAccountingPeriodSvc(inner); + let codec = tonic_prost::ProstCodec::default(); + let mut grpc = tonic::server::Grpc::new(codec) + .apply_compression_config( + accept_compression_encodings, + send_compression_encodings, + ) + .apply_max_message_size_config( + max_decoding_message_size, + max_encoding_message_size, + ); + let res = grpc.unary(method, req).await; + Ok(res) + }; + Box::pin(fut) + } + "/komp_ac.accounting.Accounting/ListAccountingPeriods" => { + #[allow(non_camel_case_types)] + struct ListAccountingPeriodsSvc(pub Arc); + impl< + T: Accounting, + > tonic::server::UnaryService + for ListAccountingPeriodsSvc { + type Response = super::ListAccountingPeriodsResponse; + type Future = BoxFuture< + tonic::Response, + tonic::Status, + >; + fn call( + &mut self, + request: tonic::Request, + ) -> Self::Future { + let inner = Arc::clone(&self.0); + let fut = async move { + ::list_accounting_periods(&inner, request) + .await + }; + Box::pin(fut) + } + } + let accept_compression_encodings = self.accept_compression_encodings; + let send_compression_encodings = self.send_compression_encodings; + let max_decoding_message_size = self.max_decoding_message_size; + let max_encoding_message_size = self.max_encoding_message_size; + let inner = self.inner.clone(); + let fut = async move { + let method = ListAccountingPeriodsSvc(inner); + let codec = tonic_prost::ProstCodec::default(); + let mut grpc = tonic::server::Grpc::new(codec) + .apply_compression_config( + accept_compression_encodings, + send_compression_encodings, + ) + .apply_max_message_size_config( + max_decoding_message_size, + max_encoding_message_size, + ); + let res = grpc.unary(method, req).await; + Ok(res) + }; + Box::pin(fut) + } + "/komp_ac.accounting.Accounting/ListPeriodBalances" => { + #[allow(non_camel_case_types)] + struct ListPeriodBalancesSvc(pub Arc); + impl< + T: Accounting, + > tonic::server::UnaryService + for ListPeriodBalancesSvc { + type Response = super::ListPeriodBalancesResponse; + type Future = BoxFuture< + tonic::Response, + tonic::Status, + >; + fn call( + &mut self, + request: tonic::Request, + ) -> Self::Future { + let inner = Arc::clone(&self.0); + let fut = async move { + ::list_period_balances(&inner, request) + .await + }; + Box::pin(fut) + } + } + let accept_compression_encodings = self.accept_compression_encodings; + let send_compression_encodings = self.send_compression_encodings; + let max_decoding_message_size = self.max_decoding_message_size; + let max_encoding_message_size = self.max_encoding_message_size; + let inner = self.inner.clone(); + let fut = async move { + let method = ListPeriodBalancesSvc(inner); + let codec = tonic_prost::ProstCodec::default(); + let mut grpc = tonic::server::Grpc::new(codec) + .apply_compression_config( + accept_compression_encodings, + send_compression_encodings, + ) + .apply_max_message_size_config( + max_decoding_message_size, + max_encoding_message_size, + ); + let res = grpc.unary(method, req).await; + Ok(res) + }; + Box::pin(fut) + } _ => { Box::pin(async move { let mut response = http::Response::new( diff --git a/server b/server index 3eda197..454acc6 160000 --- a/server +++ b/server @@ -1 +1 @@ -Subproject commit 3eda197a1fd2128273f8413ed0feb4683ec23da8 +Subproject commit 454acc6f2b0286b165188236f64b436dfa4a5555