diff --git a/client b/client index 1a472c7..087f2af 160000 --- a/client +++ b/client @@ -1 +1 @@ -Subproject commit 1a472c764b689208693748f2371ea501d933b616 +Subproject commit 087f2afaa3bb0fd961327ccbfa9037446e4cdc7c diff --git a/common/build.rs b/common/build.rs index 33b35f6..0074096 100644 --- a/common/build.rs +++ b/common/build.rs @@ -169,6 +169,18 @@ fn main() -> Result<(), Box> { ".komp_ac.table_definition.PostTableDefinitionRequest", "#[derive(serde::Serialize, serde::Deserialize)]", ) + .type_attribute( + ".komp_ac.table_definition.CreateInvoiceTemplateTableRequest", + "#[derive(serde::Serialize, serde::Deserialize)]", + ) + .type_attribute( + ".komp_ac.table_definition.GeneratedInvoiceTemplateTable", + "#[derive(serde::Serialize, serde::Deserialize)]", + ) + .type_attribute( + ".komp_ac.table_definition.CreateInvoiceTemplateTableResponse", + "#[derive(serde::Serialize, serde::Deserialize)]", + ) .type_attribute( ".komp_ac.table_definition.AddTableColumnsRequest", "#[derive(serde::Serialize, serde::Deserialize)]", diff --git a/common/proto/table_definition.proto b/common/proto/table_definition.proto index 0136ef0..a674534 100644 --- a/common/proto/table_definition.proto +++ b/common/proto/table_definition.proto @@ -14,6 +14,11 @@ service TableDefinition { // Also inserts metadata and default validation rules. Entirely transactional. rpc PostTableDefinition(PostTableDefinitionRequest) returns (TableDefinitionResponse); + // 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. + rpc CreateInvoiceTemplateTable(CreateInvoiceTemplateTableRequest) returns (CreateInvoiceTemplateTableResponse); + // Appends new user-defined columns to an existing table. // Existing columns, links, and table logic are never changed by this call. rpc AddTableColumns(AddTableColumnsRequest) returns (TableDefinitionResponse); @@ -86,6 +91,44 @@ message PostTableDefinitionRequest { string row_display_column = 7; } +// Defines the input for explicitly creating a table backed by one invoice +// template. typst_source must contain exactly one declaration of the form: +// +// #let komp_ac_fields = ( +// "invoice.number": (source: "local", field_type: "TEXT", write: "user"), +// "items[].product": (source: "reference", table: "stock", required: true), +// "items[].quantity": (source: "local", field_type: "DECIMAL(12,3)", write: "user"), +// "items[].total": (source: "local", field_type: "MONEY", write: "script"), +// ) +// +// Root fields create columns and references on table_name. Every [] collection +// creates a child table with a required FK to its immediate parent; fields in +// that collection create columns and references on the child table. Multiple +// template paths in one scope may reuse the same reference. +message CreateInvoiceTemplateTableRequest { + string profile_name = 1; + string table_name = 2; + string typst_source = 3; + string base_currency = 4; + string row_display_column = 5; +} + +// One physical dynamic table created for an invoice template scope. The root +// has an empty collection_path and parent_table_name. Each [] scope names its +// collection and the generated table that owns those repeated rows. +message GeneratedInvoiceTemplateTable { + string table_name = 1; + string collection_path = 2; + string parent_table_name = 3; + string sql = 4; +} + +// Reports the complete table bundle created from one invoice template. +message CreateInvoiceTemplateTableResponse { + bool success = 1; + repeated GeneratedInvoiceTemplateTable tables = 2; +} + // Defines append-only column additions for an existing table. message AddTableColumnsRequest { // Existing profile/schema name. diff --git a/common/src/proto/descriptor.bin b/common/src/proto/descriptor.bin index 172bac1..2a2ab42 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 71dc7a9..ca30eae 100644 --- a/common/src/proto/komp_ac.table_definition.rs +++ b/common/src/proto/komp_ac.table_definition.rs @@ -50,6 +50,58 @@ pub struct PostTableDefinitionRequest { #[prost(string, tag = "7")] pub row_display_column: ::prost::alloc::string::String, } +/// Defines the input for explicitly creating a table backed by one invoice +/// template. typst_source must contain exactly one declaration of the form: +/// +/// \#let komp_ac_fields = ( +/// "invoice.number": (source: "local", field_type: "TEXT", write: "user"), +/// "items\[\].product": (source: "reference", table: "stock", required: true), +/// "items\[\].quantity": (source: "local", field_type: "DECIMAL(12,3)", write: "user"), +/// "items\[\].total": (source: "local", field_type: "MONEY", write: "script"), +/// ) +/// +/// Root fields create columns and references on table_name. Every \[\] collection +/// creates a child table with a required FK to its immediate parent; fields in +/// that collection create columns and references on the child table. Multiple +/// template paths in one scope may reuse the same reference. +#[derive(serde::Serialize, serde::Deserialize)] +#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)] +pub struct CreateInvoiceTemplateTableRequest { + #[prost(string, tag = "1")] + pub profile_name: ::prost::alloc::string::String, + #[prost(string, tag = "2")] + pub table_name: ::prost::alloc::string::String, + #[prost(string, tag = "3")] + pub typst_source: ::prost::alloc::string::String, + #[prost(string, tag = "4")] + pub base_currency: ::prost::alloc::string::String, + #[prost(string, tag = "5")] + pub row_display_column: ::prost::alloc::string::String, +} +/// One physical dynamic table created for an invoice template scope. The root +/// has an empty collection_path and parent_table_name. Each \[\] scope names its +/// collection and the generated table that owns those repeated rows. +#[derive(serde::Serialize, serde::Deserialize)] +#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)] +pub struct GeneratedInvoiceTemplateTable { + #[prost(string, tag = "1")] + pub table_name: ::prost::alloc::string::String, + #[prost(string, tag = "2")] + pub collection_path: ::prost::alloc::string::String, + #[prost(string, tag = "3")] + pub parent_table_name: ::prost::alloc::string::String, + #[prost(string, tag = "4")] + pub sql: ::prost::alloc::string::String, +} +/// Reports the complete table bundle created from one invoice template. +#[derive(serde::Serialize, serde::Deserialize)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct CreateInvoiceTemplateTableResponse { + #[prost(bool, tag = "1")] + pub success: bool, + #[prost(message, repeated, tag = "2")] + pub tables: ::prost::alloc::vec::Vec, +} /// Defines append-only column additions for an existing table. #[derive(serde::Serialize, serde::Deserialize)] #[derive(Clone, PartialEq, ::prost::Message)] @@ -481,6 +533,38 @@ pub mod table_definition_client { ); 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. + pub async fn create_invoice_template_table( + &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.table_definition.TableDefinition/CreateInvoiceTemplateTable", + ); + let mut req = request.into_request(); + req.extensions_mut() + .insert( + GrpcMethod::new( + "komp_ac.table_definition.TableDefinition", + "CreateInvoiceTemplateTable", + ), + ); + self.inner.unary(req, path, codec).await + } /// Appends new user-defined columns to an existing table. /// Existing columns, links, and table logic are never changed by this call. pub async fn add_table_columns( @@ -719,6 +803,16 @@ pub mod table_definition_server { 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. + async fn create_invoice_template_table( + &self, + request: tonic::Request, + ) -> std::result::Result< + tonic::Response, + tonic::Status, + >; /// Appends new user-defined columns to an existing table. /// Existing columns, links, and table logic are never changed by this call. async fn add_table_columns( @@ -908,6 +1002,58 @@ pub mod table_definition_server { }; Box::pin(fut) } + "/komp_ac.table_definition.TableDefinition/CreateInvoiceTemplateTable" => { + #[allow(non_camel_case_types)] + struct CreateInvoiceTemplateTableSvc(pub Arc); + impl< + T: TableDefinition, + > tonic::server::UnaryService< + super::CreateInvoiceTemplateTableRequest, + > for CreateInvoiceTemplateTableSvc { + type Response = super::CreateInvoiceTemplateTableResponse; + type Future = BoxFuture< + tonic::Response, + tonic::Status, + >; + fn call( + &mut self, + request: tonic::Request< + super::CreateInvoiceTemplateTableRequest, + >, + ) -> Self::Future { + let inner = Arc::clone(&self.0); + let fut = async move { + ::create_invoice_template_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 = CreateInvoiceTemplateTableSvc(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/AddTableColumns" => { #[allow(non_camel_case_types)] struct AddTableColumnsSvc(pub Arc); diff --git a/server b/server index d32d24d..e52b2ab 160000 --- a/server +++ b/server @@ -1 +1 @@ -Subproject commit d32d24d447f1999b0a7fb4da75745ebba5aae63f +Subproject commit e52b2ab6e45571abfd515af1e3a891cc5128c42c