diff --git a/client b/client index 42f163be..bfe8d72e 160000 --- a/client +++ b/client @@ -1 +1 @@ -Subproject commit 42f163beaec0c66337487698542924e02f5172b3 +Subproject commit bfe8d72e32be69ad5a3358397d9418939fbbba10 diff --git a/common/proto/table_definition.proto b/common/proto/table_definition.proto index 36d94322..afc76d58 100644 --- a/common/proto/table_definition.proto +++ b/common/proto/table_definition.proto @@ -14,6 +14,10 @@ service TableDefinition { // Also inserts metadata and default validation rules. Entirely transactional. rpc PostTableDefinition(PostTableDefinitionRequest) returns (TableDefinitionResponse); + // Explicitly creates the optional administrator-managed exchange-rate table + // in an existing profile. The server owns its core shape and constraints. + rpc CreateCustomExchangeRatesTable(CreateCustomExchangeRatesTableRequest) returns (CreateCustomExchangeRatesTableResponse); + // Creates a regular user-table bundle from the restricted komp_ac_fields // contract embedded in a Typst invoice template. This is invoked explicitly // by the user; templates do not provision tables merely by existing. @@ -53,14 +57,23 @@ service TableDefinition { rpc DeleteTable(DeleteTableRequest) returns (DeleteTableResponse); } +message CreateCustomExchangeRatesTableRequest { + string profile_name = 1; +} + +message CreateCustomExchangeRatesTableResponse { + int64 table_definition_id = 1; + bool created = 2; +} + // Defines the input for creating a new table definition. message PostTableDefinitionRequest { // Table name to create inside the target profile. // Must be lowercase, alphanumeric with underscores, // start with a letter, and be <= 63 chars. - // Forbidden names: "id", "deleted", "created_at", "row_revision" -- the - // system columns, which share one namespace with table names wherever the - // two are named side by side. The "_id" suffix is allowed. + // Forbidden names include the system columns and tables owned by dedicated + // server operations, such as "custom_exchange_rates". The "_id" suffix is + // allowed. string table_name = 1; // The table's columns, including its links and stored linked projections. diff --git a/common/src/proto/descriptor.bin b/common/src/proto/descriptor.bin index 12ce2b91..ddd598db 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.table_definition.rs b/common/src/proto/komp_ac.table_definition.rs index 615930dc..6773edab 100644 --- a/common/src/proto/komp_ac.table_definition.rs +++ b/common/src/proto/komp_ac.table_definition.rs @@ -1,4 +1,16 @@ // This file is @generated by prost-build. +#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)] +pub struct CreateCustomExchangeRatesTableRequest { + #[prost(string, tag = "1")] + pub profile_name: ::prost::alloc::string::String, +} +#[derive(Clone, Copy, PartialEq, Eq, Hash, ::prost::Message)] +pub struct CreateCustomExchangeRatesTableResponse { + #[prost(int64, tag = "1")] + pub table_definition_id: i64, + #[prost(bool, tag = "2")] + pub created: bool, +} /// Defines the input for creating a new table definition. #[derive(serde::Serialize, serde::Deserialize)] #[derive(Clone, PartialEq, ::prost::Message)] @@ -6,9 +18,9 @@ pub struct PostTableDefinitionRequest { /// Table name to create inside the target profile. /// Must be lowercase, alphanumeric with underscores, /// start with a letter, and be \<= 63 chars. - /// Forbidden names: "id", "deleted", "created_at", "row_revision" -- the - /// system columns, which share one namespace with table names wherever the - /// two are named side by side. The "\_id" suffix is allowed. + /// Forbidden names include the system columns and tables owned by dedicated + /// server operations, such as "custom_exchange_rates". The "\_id" suffix is + /// allowed. #[prost(string, tag = "1")] pub table_name: ::prost::alloc::string::String, /// The table's columns, including its links and stored linked projections. @@ -778,6 +790,39 @@ pub mod table_definition_client { ); self.inner.unary(req, path, codec).await } + /// Explicitly creates the optional administrator-managed exchange-rate table + /// in an existing profile. The server owns its core shape and constraints. + pub async fn create_custom_exchange_rates_table( + &mut self, + request: impl tonic::IntoRequest< + super::CreateCustomExchangeRatesTableRequest, + >, + ) -> 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.table_definition.TableDefinition/CreateCustomExchangeRatesTable", + ); + let mut req = request.into_request(); + req.extensions_mut() + .insert( + GrpcMethod::new( + "komp_ac.table_definition.TableDefinition", + "CreateCustomExchangeRatesTable", + ), + ); + self.inner.unary(req, path, codec).await + } /// Creates a regular user-table bundle from the restricted komp_ac_fields /// contract embedded in a Typst invoice template. This is invoked explicitly /// by the user; templates do not provision tables merely by existing. @@ -1111,6 +1156,15 @@ pub mod table_definition_server { tonic::Response, tonic::Status, >; + /// Explicitly creates the optional administrator-managed exchange-rate table + /// in an existing profile. The server owns its core shape and constraints. + async fn create_custom_exchange_rates_table( + &self, + request: tonic::Request, + ) -> std::result::Result< + tonic::Response, + tonic::Status, + >; /// Creates a regular user-table bundle from the restricted komp_ac_fields /// contract embedded in a Typst invoice template. This is invoked explicitly /// by the user; templates do not provision tables merely by existing. @@ -1329,6 +1383,60 @@ pub mod table_definition_server { }; Box::pin(fut) } + "/komp_ac.table_definition.TableDefinition/CreateCustomExchangeRatesTable" => { + #[allow(non_camel_case_types)] + struct CreateCustomExchangeRatesTableSvc( + pub Arc, + ); + impl< + T: TableDefinition, + > tonic::server::UnaryService< + super::CreateCustomExchangeRatesTableRequest, + > for CreateCustomExchangeRatesTableSvc { + type Response = super::CreateCustomExchangeRatesTableResponse; + type Future = BoxFuture< + tonic::Response, + tonic::Status, + >; + fn call( + &mut self, + request: tonic::Request< + super::CreateCustomExchangeRatesTableRequest, + >, + ) -> Self::Future { + let inner = Arc::clone(&self.0); + let fut = async move { + ::create_custom_exchange_rates_table( + &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 = CreateCustomExchangeRatesTableSvc(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.table_definition.TableDefinition/CreateInvoiceTemplateTable" => { #[allow(non_camel_case_types)] struct CreateInvoiceTemplateTableSvc(pub Arc); diff --git a/server b/server index 2cec55d9..4fa445cc 160000 --- a/server +++ b/server @@ -1 +1 @@ -Subproject commit 2cec55d9e90ff116ecfa0c9908d15ca5a7fa3be1 +Subproject commit 4fa445ccf882e1341c732b4eef2e025b4fc60733 diff --git a/web/src/schema/mod.rs b/web/src/schema/mod.rs index 9bcdd80b..1b2c809c 100644 --- a/web/src/schema/mod.rs +++ b/web/src/schema/mod.rs @@ -1235,11 +1235,12 @@ pub(crate) const MAX_TABLE_NAME_LENGTH: usize = MAX_IDENTIFIER_LENGTH /// constants of three server modules rather than anything the catalog carries. /// A name the server adds to that set is a name this list will not know about /// until it is added here as well. -pub(crate) const RESERVED_TABLE_NAMES: [&str; 4] = [ +pub(crate) const RESERVED_TABLE_NAMES: [&str; 5] = [ "general_ledger", "journal_lines", "quantity_ledger", LEDGER_ACCOUNTS_TABLE, + "custom_exchange_rates", ]; /// The identifier rules, plus the two a table name alone is held to.