diff --git a/client b/client index 534f7236..f4eb4c32 160000 --- a/client +++ b/client @@ -1 +1 @@ -Subproject commit 534f72363dd0cd53799fd740f65c16a6002ce39b +Subproject commit f4eb4c32abe815f7acf808918359e3a0d37452cf diff --git a/client-gui2 b/client-gui2 index 58593ae5..acac1b05 160000 --- a/client-gui2 +++ b/client-gui2 @@ -1 +1 @@ -Subproject commit 58593ae57767d068fba037e6399784bab6edb214 +Subproject commit acac1b056ca82d5f9e477cd5cf192dd5b8067792 diff --git a/common/proto/table_definition.proto b/common/proto/table_definition.proto index 67946424..045c08c3 100644 --- a/common/proto/table_definition.proto +++ b/common/proto/table_definition.proto @@ -23,6 +23,10 @@ service TableDefinition { // by the user; templates do not provision tables merely by existing. rpc CreateInvoiceTemplateTable(CreateInvoiceTemplateTableRequest) returns (CreateInvoiceTemplateTableResponse); + // Applies the administrator-reviewed, explicitly typed table bundle and + // exact komp_ac_fields bindings for an imported Typst template. + rpc ApplyInvoiceTemplateTable(ApplyInvoiceTemplateTableRequest) 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); @@ -170,6 +174,46 @@ message CreateInvoiceTemplateTableRequest { repeated string row_display_columns = 3; } +message ApplyInvoiceTemplateTableRequest { + string profile_name = 1; + string template_name = 2; + repeated InvoiceTemplateTableDefinition tables = 3; + repeated InvoiceTemplateFieldBinding field_bindings = 4; + + // The immutable version whose komp_ac_fields the administrator mapped. + // Applying never silently switches to a newer version with a different + // contract between inspection and submission. + int64 template_version_id = 5; +} + +// One administrator-designed table in the template input bundle. The empty +// collection_path is the root; a path ending in [] owns that repeated scope. +// The nested table definition retains every normal table option, including +// ACCOUNTING, generated aliases, ledgers, indexes, links and display columns. +message InvoiceTemplateTableDefinition { + string collection_path = 1; + PostTableDefinitionRequest definition = 2; +} + +enum InvoiceTemplateAccountingRole { + INVOICE_TEMPLATE_ACCOUNTING_ROLE_UNSPECIFIED = 0; + INVOICE_TEMPLATE_ACCOUNTING_NAME = 1; + INVOICE_TEMPLATE_ACCOUNTING_TAX_POINT_DATE = 2; + INVOICE_TEMPLATE_ACCOUNTING_ACCOUNT = 3; + INVOICE_TEMPLATE_ACCOUNTING_DEBIT = 4; + INVOICE_TEMPLATE_ACCOUNTING_CREDIT = 5; +} + +// Maps one path from komp_ac_fields to one table column. A regular binding +// names a declared column. An accounting binding names a semantic generated +// role, so aliases and the order of Typst fields cannot change its meaning. +message InvoiceTemplateFieldBinding { + string field_path = 1; + string collection_path = 2; + string column_name = 3; + InvoiceTemplateAccountingRole accounting_role = 4; +} + // 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. @@ -184,6 +228,7 @@ message GeneratedInvoiceTemplateTable { message CreateInvoiceTemplateTableResponse { bool success = 1; repeated GeneratedInvoiceTemplateTable tables = 2; + int64 template_version_id = 3; } // Defines append-only column additions for an existing table. diff --git a/common/src/proto/descriptor.bin b/common/src/proto/descriptor.bin index 53877eda..da6d65db 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 27cd74db..38150198 100644 --- a/common/src/proto/komp_ac.table_definition.rs +++ b/common/src/proto/komp_ac.table_definition.rs @@ -114,6 +114,50 @@ pub struct CreateInvoiceTemplateTableRequest { #[prost(string, repeated, tag = "3")] pub row_display_columns: ::prost::alloc::vec::Vec<::prost::alloc::string::String>, } +#[derive(serde::Serialize, serde::Deserialize)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct ApplyInvoiceTemplateTableRequest { + #[prost(string, tag = "1")] + pub profile_name: ::prost::alloc::string::String, + #[prost(string, tag = "2")] + pub template_name: ::prost::alloc::string::String, + #[prost(message, repeated, tag = "3")] + pub tables: ::prost::alloc::vec::Vec, + #[prost(message, repeated, tag = "4")] + pub field_bindings: ::prost::alloc::vec::Vec, + /// The immutable version whose komp_ac_fields the administrator mapped. + /// Applying never silently switches to a newer version with a different + /// contract between inspection and submission. + #[prost(int64, tag = "5")] + pub template_version_id: i64, +} +/// One administrator-designed table in the template input bundle. The empty +/// collection_path is the root; a path ending in \[\] owns that repeated scope. +/// The nested table definition retains every normal table option, including +/// ACCOUNTING, generated aliases, ledgers, indexes, links and display columns. +#[derive(serde::Serialize, serde::Deserialize)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct InvoiceTemplateTableDefinition { + #[prost(string, tag = "1")] + pub collection_path: ::prost::alloc::string::String, + #[prost(message, optional, tag = "2")] + pub definition: ::core::option::Option, +} +/// Maps one path from komp_ac_fields to one table column. A regular binding +/// names a declared column. An accounting binding names a semantic generated +/// role, so aliases and the order of Typst fields cannot change its meaning. +#[derive(serde::Serialize, serde::Deserialize)] +#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)] +pub struct InvoiceTemplateFieldBinding { + #[prost(string, tag = "1")] + pub field_path: ::prost::alloc::string::String, + #[prost(string, tag = "2")] + pub collection_path: ::prost::alloc::string::String, + #[prost(string, tag = "3")] + pub column_name: ::prost::alloc::string::String, + #[prost(enumeration = "InvoiceTemplateAccountingRole", tag = "4")] + pub accounting_role: i32, +} /// 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. @@ -137,6 +181,8 @@ pub struct CreateInvoiceTemplateTableResponse { pub success: bool, #[prost(message, repeated, tag = "2")] pub tables: ::prost::alloc::vec::Vec, + #[prost(int64, tag = "3")] + pub template_version_id: i64, } /// Defines append-only column additions for an existing table. #[derive(serde::Serialize, serde::Deserialize)] @@ -704,6 +750,59 @@ pub mod list_column_types_response { #[derive(serde::Serialize, serde::Deserialize)] #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)] #[repr(i32)] +pub enum InvoiceTemplateAccountingRole { + Unspecified = 0, + InvoiceTemplateAccountingName = 1, + InvoiceTemplateAccountingTaxPointDate = 2, + InvoiceTemplateAccountingAccount = 3, + InvoiceTemplateAccountingDebit = 4, + InvoiceTemplateAccountingCredit = 5, +} +impl InvoiceTemplateAccountingRole { + /// 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 => "INVOICE_TEMPLATE_ACCOUNTING_ROLE_UNSPECIFIED", + Self::InvoiceTemplateAccountingName => "INVOICE_TEMPLATE_ACCOUNTING_NAME", + Self::InvoiceTemplateAccountingTaxPointDate => { + "INVOICE_TEMPLATE_ACCOUNTING_TAX_POINT_DATE" + } + Self::InvoiceTemplateAccountingAccount => { + "INVOICE_TEMPLATE_ACCOUNTING_ACCOUNT" + } + Self::InvoiceTemplateAccountingDebit => "INVOICE_TEMPLATE_ACCOUNTING_DEBIT", + Self::InvoiceTemplateAccountingCredit => "INVOICE_TEMPLATE_ACCOUNTING_CREDIT", + } + } + /// Creates an enum from field names used in the ProtoBuf definition. + pub fn from_str_name(value: &str) -> ::core::option::Option { + match value { + "INVOICE_TEMPLATE_ACCOUNTING_ROLE_UNSPECIFIED" => Some(Self::Unspecified), + "INVOICE_TEMPLATE_ACCOUNTING_NAME" => { + Some(Self::InvoiceTemplateAccountingName) + } + "INVOICE_TEMPLATE_ACCOUNTING_TAX_POINT_DATE" => { + Some(Self::InvoiceTemplateAccountingTaxPointDate) + } + "INVOICE_TEMPLATE_ACCOUNTING_ACCOUNT" => { + Some(Self::InvoiceTemplateAccountingAccount) + } + "INVOICE_TEMPLATE_ACCOUNTING_DEBIT" => { + Some(Self::InvoiceTemplateAccountingDebit) + } + "INVOICE_TEMPLATE_ACCOUNTING_CREDIT" => { + Some(Self::InvoiceTemplateAccountingCredit) + } + _ => None, + } + } +} +#[derive(serde::Serialize, serde::Deserialize)] +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)] +#[repr(i32)] pub enum MoneyRounding { None = 0, HalfUp = 1, @@ -983,6 +1082,37 @@ pub mod table_definition_client { ); self.inner.unary(req, path, codec).await } + /// Applies the administrator-reviewed, explicitly typed table bundle and + /// exact komp_ac_fields bindings for an imported Typst template. + pub async fn apply_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/ApplyInvoiceTemplateTable", + ); + let mut req = request.into_request(); + req.extensions_mut() + .insert( + GrpcMethod::new( + "komp_ac.table_definition.TableDefinition", + "ApplyInvoiceTemplateTable", + ), + ); + 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( @@ -1367,6 +1497,15 @@ pub mod table_definition_server { tonic::Response, tonic::Status, >; + /// Applies the administrator-reviewed, explicitly typed table bundle and + /// exact komp_ac_fields bindings for an imported Typst template. + async fn apply_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( @@ -1701,6 +1840,58 @@ pub mod table_definition_server { }; Box::pin(fut) } + "/komp_ac.table_definition.TableDefinition/ApplyInvoiceTemplateTable" => { + #[allow(non_camel_case_types)] + struct ApplyInvoiceTemplateTableSvc(pub Arc); + impl< + T: TableDefinition, + > tonic::server::UnaryService< + super::ApplyInvoiceTemplateTableRequest, + > for ApplyInvoiceTemplateTableSvc { + type Response = super::CreateInvoiceTemplateTableResponse; + type Future = BoxFuture< + tonic::Response, + tonic::Status, + >; + fn call( + &mut self, + request: tonic::Request< + super::ApplyInvoiceTemplateTableRequest, + >, + ) -> Self::Future { + let inner = Arc::clone(&self.0); + let fut = async move { + ::apply_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 = ApplyInvoiceTemplateTableSvc(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/flake.nix b/flake.nix index 1f68d047..b6621f00 100644 --- a/flake.nix +++ b/flake.nix @@ -35,8 +35,8 @@ ]; # Keep font discovery deterministic when running the prebuilt GUI. - FONTCONFIG_FILE = "${pkgs.fontconfig}/etc/fonts/fonts.conf"; - FONTCONFIG_PATH = "${pkgs.fontconfig}/etc/fonts"; + FONTCONFIG_FILE = "${pkgs.fontconfig.out}/etc/fonts/fonts.conf"; + FONTCONFIG_PATH = "${pkgs.fontconfig.out}/etc/fonts"; buildInputs = with pkgs; [ mermaid-cli