diff --git a/common/proto/accounting.proto b/common/proto/accounting.proto index 3818eda..0eca8bd 100644 --- a/common/proto/accounting.proto +++ b/common/proto/accounting.proto @@ -15,6 +15,10 @@ service Accounting { // 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); @@ -26,10 +30,6 @@ service Accounting { rpc SoftDeleteJournalLine(SoftDeleteJournalLineRequest) returns (Journal); } -// Tables with an active posting script define journal_id as a permanent BIGINT -// column. PostTableDataRequest.data must include it; the value is stored on the -// source row and selects the journal receiving generated lines. - enum JournalSide { JOURNAL_SIDE_UNSPECIFIED = 0; JOURNAL_SIDE_DEBIT = 1; @@ -53,6 +53,10 @@ message PostJournalRequest { // At least one line is required. The lines are inserted atomically and the // journal is allowed to remain unbalanced. repeated JournalLineInput lines = 5; + + // Required and unique within the profile when creating. Must be empty when + // appending to an existing journal selected by journal_id. + string journal_name = 6; } message JournalLineInput { @@ -80,6 +84,38 @@ 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 locked = 9; + string created_at = 10; +} + +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; @@ -117,6 +153,7 @@ message UnbalancedJournalSummary { string missing_amount = 8; int64 active_line_count = 9; string created_at = 10; + string journal_name = 11; } message ListUnbalancedJournalsResponse { @@ -161,4 +198,5 @@ message Journal { bool locked = 10; string locked_at = 11; string locked_by_user_id = 12; + string journal_name = 13; } diff --git a/common/src/proto/descriptor.bin b/common/src/proto/descriptor.bin index 08d5faa..f4e6650 100644 Binary files a/common/src/proto/descriptor.bin and b/common/src/proto/descriptor.bin differ diff --git a/common/src/proto/komp_ac.accounting.rs b/common/src/proto/komp_ac.accounting.rs index 2b83439..11eedb9 100644 --- a/common/src/proto/komp_ac.accounting.rs +++ b/common/src/proto/komp_ac.accounting.rs @@ -18,6 +18,10 @@ pub struct PostJournalRequest { /// journal is allowed to remain unbalanced. #[prost(message, repeated, tag = "5")] pub lines: ::prost::alloc::vec::Vec, + /// Required and unique within the profile when creating. Must be empty when + /// appending to an existing journal selected by journal_id. + #[prost(string, tag = "6")] + pub journal_name: ::prost::alloc::string::String, } #[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)] pub struct JournalLineInput { @@ -54,6 +58,52 @@ pub struct GetAccountingStatusRequest { pub profile_name: ::prost::alloc::string::String, } #[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)] +pub struct SearchJournalsRequest { + #[prost(string, tag = "1")] + pub profile_name: ::prost::alloc::string::String, + /// Case-insensitive literal substring. Empty returns all profile journals. + #[prost(string, tag = "2")] + pub name_query: ::prost::alloc::string::String, + /// Zero uses 50. The maximum is 500. + #[prost(int32, tag = "3")] + pub page_size: i32, + /// Opaque cursor returned by the previous response. + #[prost(string, tag = "4")] + pub page_token: ::prost::alloc::string::String, +} +#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)] +pub struct JournalSummary { + #[prost(int64, tag = "1")] + pub journal_id: i64, + #[prost(string, tag = "2")] + pub journal_name: ::prost::alloc::string::String, + #[prost(string, tag = "3")] + pub currency: ::prost::alloc::string::String, + #[prost(string, tag = "4")] + pub description: ::prost::alloc::string::String, + #[prost(string, tag = "5")] + pub total_debit: ::prost::alloc::string::String, + #[prost(string, tag = "6")] + pub total_credit: ::prost::alloc::string::String, + #[prost(string, tag = "7")] + pub balance: ::prost::alloc::string::String, + #[prost(int64, tag = "8")] + pub active_line_count: i64, + #[prost(bool, tag = "9")] + pub locked: bool, + #[prost(string, tag = "10")] + pub created_at: ::prost::alloc::string::String, +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct SearchJournalsResponse { + #[prost(message, repeated, tag = "1")] + pub journals: ::prost::alloc::vec::Vec, + #[prost(int64, tag = "2")] + pub total_count: i64, + #[prost(string, tag = "3")] + pub next_page_token: ::prost::alloc::string::String, +} +#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)] pub struct AccountingStatus { #[prost(bool, tag = "1")] pub all_journals_balanced: bool, @@ -105,6 +155,8 @@ pub struct UnbalancedJournalSummary { pub active_line_count: i64, #[prost(string, tag = "10")] pub created_at: ::prost::alloc::string::String, + #[prost(string, tag = "11")] + pub journal_name: ::prost::alloc::string::String, } #[derive(Clone, PartialEq, ::prost::Message)] pub struct ListUnbalancedJournalsResponse { @@ -180,6 +232,8 @@ pub struct Journal { pub locked_at: ::prost::alloc::string::String, #[prost(string, tag = "12")] pub locked_by_user_id: ::prost::alloc::string::String, + #[prost(string, tag = "13")] + pub journal_name: ::prost::alloc::string::String, } #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)] #[repr(i32)] @@ -371,6 +425,34 @@ pub mod accounting_client { .insert(GrpcMethod::new("komp_ac.accounting.Accounting", "GetJournal")); self.inner.unary(req, path, codec).await } + /// Search profile journals by user-facing name while retaining journal ids + /// as the stable relationship keys. + pub async fn search_journals( + &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/SearchJournals", + ); + let mut req = request.into_request(); + req.extensions_mut() + .insert( + GrpcMethod::new("komp_ac.accounting.Accounting", "SearchJournals"), + ); + self.inner.unary(req, path, codec).await + } /// Return the profile-wide count of balanced and unbalanced journals. pub async fn get_accounting_status( &mut self, @@ -490,6 +572,15 @@ pub mod accounting_server { &self, request: tonic::Request, ) -> std::result::Result, tonic::Status>; + /// Search profile journals by user-facing name while retaining journal ids + /// as the stable relationship keys. + async fn search_journals( + &self, + request: tonic::Request, + ) -> std::result::Result< + tonic::Response, + tonic::Status, + >; /// Return the profile-wide count of balanced and unbalanced journals. async fn get_accounting_status( &self, @@ -725,6 +816,51 @@ pub mod accounting_server { }; Box::pin(fut) } + "/komp_ac.accounting.Accounting/SearchJournals" => { + #[allow(non_camel_case_types)] + struct SearchJournalsSvc(pub Arc); + impl< + T: Accounting, + > tonic::server::UnaryService + for SearchJournalsSvc { + type Response = super::SearchJournalsResponse; + 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 { + ::search_journals(&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 = SearchJournalsSvc(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/GetAccountingStatus" => { #[allow(non_camel_case_types)] struct GetAccountingStatusSvc(pub Arc); diff --git a/tui-pages b/tui-pages index 30b2bf7..cfce2e5 160000 --- a/tui-pages +++ b/tui-pages @@ -1 +1 @@ -Subproject commit 30b2bf78914c0a18a872e0680059e7fd4bd18867 +Subproject commit cfce2e590b2277e0defcc0efbc3b227c0060d141