diff --git a/common/proto/analytics.proto b/common/proto/analytics.proto index 898e7f96..aabd4389 100644 --- a/common/proto/analytics.proto +++ b/common/proto/analytics.proto @@ -30,7 +30,6 @@ message AnalyticsTable { string name = 2; repeated AnalyticsCatalogColumn columns = 3; repeated AnalyticsTableLink links = 4; - string base_currency = 5; } message AnalyticsCatalogColumn { @@ -39,6 +38,8 @@ message AnalyticsCatalogColumn { string field_type = 2; bool is_system = 3; string rounding = 4; + // Canonical ISO-4217 code for MONEY; empty for every other type. + string currency = 5; } message AnalyticsTableLink { diff --git a/common/proto/table_definition.proto b/common/proto/table_definition.proto index b3572b34..38197ffd 100644 --- a/common/proto/table_definition.proto +++ b/common/proto/table_definition.proto @@ -83,9 +83,6 @@ message PostTableDefinitionRequest { // like "public", "information_schema", or ones starting with "pg_". string profile_name = 5; - // ISO-4217 base currency used by every MONEY column in this table. - string base_currency = 6; - // Columns whose values identify a row to users in pickers, in the order // they are shown. Each must name one of the user-defined columns above. // Empty means the row is identified by its id alone. @@ -94,7 +91,7 @@ message PostTableDefinitionRequest { // ISO-4217 currency the profile keeps its accounting in. A profile is one // accounting entity and keeps one set of books, so this is required only when // the request creates the profile, and is ignored afterwards. It is unrelated - // to base_currency: tables may hold money in any currency, and amounts convert + // to individual MONEY-column currencies: tables may hold money in any currency, and amounts convert // to this one when they reach the ledger. string accounting_currency = 8; } @@ -116,7 +113,6 @@ message CreateInvoiceTemplateTableRequest { string profile_name = 1; string table_name = 2; string typst_source = 3; - string base_currency = 4; repeated string row_display_columns = 5; } @@ -150,9 +146,6 @@ message AddTableColumnsRequest { // Optional indexes for the new columns only. repeated string indexes = 4; - // Required when adding the first MONEY column to a table. - string base_currency = 5; - } enum MoneyRounding { @@ -176,7 +169,7 @@ message ColumnDefinition { // RAW_DATETIME (timezone-free civil datetime) // PHONE (international or national phone number; generates extension/type/country/calling-code companions) // TIME (timezone-free time of day) - // MONEY (= unconstrained NUMERIC; currency comes from the table) + // MONEY (= unconstrained NUMERIC; currency is declared below) // ACCOUNTING (creates schema-managed name, account, debit, and credit fields; // account always selects a row from the profile's managed accounts table; // name is limited to 10 characters and one stored row contributes @@ -197,6 +190,10 @@ message ColumnDefinition { // When true, this numeric column is server-owned and projected from the // profile quantity ledger. bool quantity_ledger = 4; + + // Canonical uppercase ISO-4217 currency code. Required for MONEY and forbidden + // for every other field type. + string currency = 5; } // Response after table creation (success + DDL preview). @@ -299,7 +296,6 @@ message TableDetail { int64 id = 2; repeated ColumnDefinition columns = 3; repeated ScriptInfo scripts = 4; - string base_currency = 5; repeated string row_display_columns = 6; map column_behaviors = 7; string table_kind = 8; diff --git a/common/proto/table_script.proto b/common/proto/table_script.proto index 0f72a3bd..a5ae6163 100644 --- a/common/proto/table_script.proto +++ b/common/proto/table_script.proto @@ -210,8 +210,8 @@ message HydratedColumnValue { string value = 4; // Logical database type used to create a typed client ScriptValue. string field_type = 5; - // Related table's base currency for MONEY values; otherwise empty. - string base_currency = 6; + // Related MONEY column's currency; otherwise empty. + string currency = 6; } // One declared related-collection aggregate input for the client Steel context. @@ -229,8 +229,8 @@ message HydratedAggregateValue { string value = 5; // Logical source-column type; empty for row-only aggregates. string field_type = 6; - // Aggregate table's base currency for MONEY values; otherwise empty. - string base_currency = 7; + // Aggregated MONEY column's currency; otherwise empty. + string currency = 7; } // Complete external dependency snapshot for client-side Steel execution. diff --git a/common/src/proto/descriptor.bin b/common/src/proto/descriptor.bin index 339888cf..a869dc61 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.analytics.rs b/common/src/proto/komp_ac.analytics.rs index 8d6a2731..8d66dd7a 100644 --- a/common/src/proto/komp_ac.analytics.rs +++ b/common/src/proto/komp_ac.analytics.rs @@ -22,8 +22,6 @@ pub struct AnalyticsTable { pub columns: ::prost::alloc::vec::Vec, #[prost(message, repeated, tag = "4")] pub links: ::prost::alloc::vec::Vec, - #[prost(string, tag = "5")] - pub base_currency: ::prost::alloc::string::String, } #[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)] pub struct AnalyticsCatalogColumn { @@ -36,6 +34,9 @@ pub struct AnalyticsCatalogColumn { pub is_system: bool, #[prost(string, tag = "4")] pub rounding: ::prost::alloc::string::String, + /// Canonical ISO-4217 code for MONEY; empty for every other type. + #[prost(string, tag = "5")] + pub currency: ::prost::alloc::string::String, } #[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)] pub struct AnalyticsTableLink { diff --git a/common/src/proto/komp_ac.table_definition.rs b/common/src/proto/komp_ac.table_definition.rs index cd323526..a0900e5a 100644 --- a/common/src/proto/komp_ac.table_definition.rs +++ b/common/src/proto/komp_ac.table_definition.rs @@ -42,9 +42,6 @@ pub struct PostTableDefinitionRequest { /// like "public", "information_schema", or ones starting with "pg\_". #[prost(string, tag = "5")] pub profile_name: ::prost::alloc::string::String, - /// ISO-4217 base currency used by every MONEY column in this table. - #[prost(string, tag = "6")] - pub base_currency: ::prost::alloc::string::String, /// Columns whose values identify a row to users in pickers, in the order /// they are shown. Each must name one of the user-defined columns above. /// Empty means the row is identified by its id alone. @@ -53,7 +50,7 @@ pub struct PostTableDefinitionRequest { /// ISO-4217 currency the profile keeps its accounting in. A profile is one /// accounting entity and keeps one set of books, so this is required only when /// the request creates the profile, and is ignored afterwards. It is unrelated - /// to base_currency: tables may hold money in any currency, and amounts convert + /// to individual MONEY-column currencies: tables may hold money in any currency, and amounts convert /// to this one when they reach the ledger. #[prost(string, tag = "8")] pub accounting_currency: ::prost::alloc::string::String, @@ -80,8 +77,6 @@ pub struct CreateInvoiceTemplateTableRequest { 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, repeated, tag = "5")] pub row_display_columns: ::prost::alloc::vec::Vec<::prost::alloc::string::String>, } @@ -125,9 +120,6 @@ pub struct AddTableColumnsRequest { /// Optional indexes for the new columns only. #[prost(string, repeated, tag = "4")] pub indexes: ::prost::alloc::vec::Vec<::prost::alloc::string::String>, - /// Required when adding the first MONEY column to a table. - #[prost(string, tag = "5")] - pub base_currency: ::prost::alloc::string::String, } /// Describes one user-defined column for a table. #[derive(serde::Serialize, serde::Deserialize)] @@ -147,7 +139,7 @@ pub struct ColumnDefinition { /// RAW_DATETIME (timezone-free civil datetime) /// PHONE (international or national phone number; generates extension/type/country/calling-code companions) /// TIME (timezone-free time of day) - /// MONEY (= unconstrained NUMERIC; currency comes from the table) + /// MONEY (= unconstrained NUMERIC; currency is declared below) /// ACCOUNTING (creates schema-managed name, account, debit, and credit fields; /// account always selects a row from the profile's managed accounts table; /// name is limited to 10 characters and one stored row contributes @@ -169,6 +161,10 @@ pub struct ColumnDefinition { /// profile quantity ledger. #[prost(bool, tag = "4")] pub quantity_ledger: bool, + /// Canonical uppercase ISO-4217 currency code. Required for MONEY and forbidden + /// for every other field type. + #[prost(string, tag = "5")] + pub currency: ::prost::alloc::string::String, } /// Response after table creation (success + DDL preview). #[derive(serde::Serialize, serde::Deserialize)] @@ -310,8 +306,6 @@ pub struct TableDetail { pub columns: ::prost::alloc::vec::Vec, #[prost(message, repeated, tag = "4")] pub scripts: ::prost::alloc::vec::Vec, - #[prost(string, tag = "5")] - pub base_currency: ::prost::alloc::string::String, #[prost(string, repeated, tag = "6")] pub row_display_columns: ::prost::alloc::vec::Vec<::prost::alloc::string::String>, #[prost(map = "string, message", tag = "7")] diff --git a/common/src/proto/komp_ac.table_script.rs b/common/src/proto/komp_ac.table_script.rs index ef724177..6eef1846 100644 --- a/common/src/proto/komp_ac.table_script.rs +++ b/common/src/proto/komp_ac.table_script.rs @@ -168,9 +168,9 @@ pub struct HydratedColumnValue { /// Logical database type used to create a typed client ScriptValue. #[prost(string, tag = "5")] pub field_type: ::prost::alloc::string::String, - /// Related table's base currency for MONEY values; otherwise empty. + /// Related MONEY column's currency; otherwise empty. #[prost(string, tag = "6")] - pub base_currency: ::prost::alloc::string::String, + pub currency: ::prost::alloc::string::String, } /// One declared related-collection aggregate input for the client Steel context. #[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)] @@ -194,9 +194,9 @@ pub struct HydratedAggregateValue { /// Logical source-column type; empty for row-only aggregates. #[prost(string, tag = "6")] pub field_type: ::prost::alloc::string::String, - /// Aggregate table's base currency for MONEY values; otherwise empty. + /// Aggregated MONEY column's currency; otherwise empty. #[prost(string, tag = "7")] - pub base_currency: ::prost::alloc::string::String, + pub currency: ::prost::alloc::string::String, } /// Complete external dependency snapshot for client-side Steel execution. #[derive(Clone, PartialEq, ::prost::Message)] diff --git a/invoice-print-setup.md b/invoice-print-setup.md index 14b254e6..373ae277 100644 --- a/invoice-print-setup.md +++ b/invoice-print-setup.md @@ -146,7 +146,6 @@ grpcurl -plaintext -H "$AUTH_HEADER" \ "profile_name":"fakturacia_2026", "table_name":"faktura", "row_display_column":"cislo", - "base_currency":"EUR", "links":[ {"linked_table_name":"dodavatel","required":true}, {"linked_table_name":"odberatel","required":true} @@ -158,9 +157,9 @@ grpcurl -plaintext -H "$AUTH_HEADER" \ {"name":"datum_splatnosti","field_type":"DATE"}, {"name":"variabilny_symbol","field_type":"TEXT"}, {"name":"sposob_uhrady","field_type":"TEXT"}, - {"name":"zaklad_dane","field_type":"MONEY","rounding":"MONEY_ROUNDING_HALF_UP","recompute_on_dependency_change":true}, - {"name":"dph_celkom","field_type":"MONEY","rounding":"MONEY_ROUNDING_HALF_UP","recompute_on_dependency_change":true}, - {"name":"celkom_spolu","field_type":"MONEY","rounding":"MONEY_ROUNDING_HALF_UP","recompute_on_dependency_change":true}, + {"name":"zaklad_dane","field_type":"MONEY","currency":"EUR","rounding":"MONEY_ROUNDING_HALF_UP","recompute_on_dependency_change":true}, + {"name":"dph_celkom","field_type":"MONEY","currency":"EUR","rounding":"MONEY_ROUNDING_HALF_UP","recompute_on_dependency_change":true}, + {"name":"celkom_spolu","field_type":"MONEY","currency":"EUR","rounding":"MONEY_ROUNDING_HALF_UP","recompute_on_dependency_change":true}, {"name":"poznamka","field_type":"TEXT"} ] }' \ @@ -176,17 +175,16 @@ grpcurl -plaintext -H "$AUTH_HEADER" \ "profile_name":"fakturacia_2026", "table_name":"polozka", "row_display_column":"nazov", - "base_currency":"EUR", "links":[{"linked_table_name":"faktura","required":true}], "columns":[ {"name":"nazov","field_type":"TEXT"}, {"name":"mnozstvo","field_type":"DECIMAL(12,3)"}, {"name":"mj","field_type":"TEXT"}, - {"name":"cena","field_type":"MONEY","rounding":"MONEY_ROUNDING_HALF_UP"}, + {"name":"cena","field_type":"MONEY","currency":"EUR","rounding":"MONEY_ROUNDING_HALF_UP"}, {"name":"dph","field_type":"DECIMAL(5,2)"}, - {"name":"bez","field_type":"MONEY","rounding":"MONEY_ROUNDING_HALF_UP","recompute_on_dependency_change":true}, - {"name":"dph_suma","field_type":"MONEY","rounding":"MONEY_ROUNDING_HALF_UP","recompute_on_dependency_change":true}, - {"name":"spolu","field_type":"MONEY","rounding":"MONEY_ROUNDING_HALF_UP","recompute_on_dependency_change":true} + {"name":"bez","field_type":"MONEY","currency":"EUR","rounding":"MONEY_ROUNDING_HALF_UP","recompute_on_dependency_change":true}, + {"name":"dph_suma","field_type":"MONEY","currency":"EUR","rounding":"MONEY_ROUNDING_HALF_UP","recompute_on_dependency_change":true}, + {"name":"spolu","field_type":"MONEY","currency":"EUR","rounding":"MONEY_ROUNDING_HALF_UP","recompute_on_dependency_change":true} ] }' \ "$GRPC_ADDR" komp_ac.table_definition.TableDefinition/PostTableDefinition diff --git a/server b/server index 453d16c4..c637ba78 160000 --- a/server +++ b/server @@ -1 +1 @@ -Subproject commit 453d16c4308393f1d612998c6ed70e0a4a5a814a +Subproject commit c637ba7883e613ffb346ed6967a8add06139a676 diff --git a/web/src/pages/add_table/draft.rs b/web/src/pages/add_table/draft.rs index dd260613..93b420e1 100644 --- a/web/src/pages/add_table/draft.rs +++ b/web/src/pages/add_table/draft.rs @@ -140,6 +140,7 @@ pub(crate) struct ColumnDefinition { pub indexed: bool, pub quantity_ledger: bool, pub money_mode: MoneyMode, + pub currency: String, } impl ColumnDefinition { @@ -147,9 +148,9 @@ impl ColumnDefinition { pub(crate) fn option_label(&self) -> String { let is_money = self.data_type.eq_ignore_ascii_case("money"); match (self.indexed, is_money) { - (true, true) => format!("indexed, {}", self.money_mode.label()), + (true, true) => format!("indexed, {}, {}", self.currency, self.money_mode.label()), (true, false) => "indexed".to_string(), - (false, true) => self.money_mode.label().to_string(), + (false, true) => format!("{}, {}", self.currency, self.money_mode.label()), (false, false) => String::new(), } } @@ -181,7 +182,6 @@ pub(crate) struct TableDraft { pub accounting_currency: String, pub table_name: String, - pub base_currency: String, // The column-input panel: one pending column being described. pub column_name_input: String, @@ -191,6 +191,7 @@ pub(crate) struct TableDraft { pub column_indexing_input: String, pub column_quantity_ledger_input: String, pub column_rounding_input: String, + pub column_currency_input: String, pub columns: Vec, pub links: Vec, @@ -208,10 +209,10 @@ impl TableDraft { pub(crate) fn new() -> Self { Self { accounting_currency: "EUR".to_string(), - base_currency: "EUR".to_string(), column_indexing_input: "no".to_string(), column_quantity_ledger_input: "no".to_string(), column_rounding_input: "none".to_string(), + column_currency_input: "EUR".to_string(), ..Self::default() } } @@ -276,10 +277,6 @@ impl TableDraft { self.is_money_column_input() } - pub(crate) fn show_base_currency(&self) -> bool { - self.is_money_column_input() || self.money_column_count() > 0 - } - // ---- mutations ------------------------------------------------------- /// Appends the pending column, then clears the input panel. @@ -320,6 +317,11 @@ impl TableDraft { let is_money = column_type.eq_ignore_ascii_case("money") || column_type.eq_ignore_ascii_case("accounting"); + let currency = if is_money { + normalize_currency_input(&self.column_currency_input)? + } else { + String::new() + }; self.columns.push(ColumnDefinition { name: column_name.clone(), data_type: column_type, @@ -333,6 +335,7 @@ impl TableDraft { } else { MoneyMode::Exact }, + currency, }); self.clear_column_inputs(); @@ -347,6 +350,7 @@ impl TableDraft { self.column_indexing_input = "no".to_string(); self.column_quantity_ledger_input = "no".to_string(); self.column_rounding_input = "none".to_string(); + self.column_currency_input = "EUR".to_string(); } /// Removes one column, and drops it from the display columns with it. @@ -440,16 +444,6 @@ impl TableDraft { .any(|name| name == &self.table_name) } - pub(crate) fn money_column_count(&self) -> usize { - self.columns - .iter() - .filter(|column| { - column.data_type.eq_ignore_ascii_case("money") - || column.data_type.eq_ignore_ascii_case("accounting") - }) - .count() - } - pub(crate) fn selected_index_names(&self) -> Vec { self.columns .iter() @@ -561,9 +555,6 @@ impl TableDraft { return Err(format!("Column `{}`: {error}", column.name)); } } - if let Some(error) = validate_base_currency(self) { - return Err(error); - } Ok(()) } @@ -585,6 +576,7 @@ impl TableDraft { MoneyMode::Exact => MoneyRounding::None.into(), }, quantity_ledger: column.quantity_ledger, + currency: column.currency.clone(), }) .collect(), indexes: self.selected_index_names(), @@ -597,11 +589,6 @@ impl TableDraft { required: link.mode.is_required(), }) .collect(), - base_currency: if self.money_column_count() == 0 { - String::new() - } else { - self.base_currency.trim().to_ascii_uppercase() - }, accounting_currency: if self.creating_new_profile { self.accounting_currency.trim().to_ascii_uppercase() } else { @@ -612,15 +599,12 @@ impl TableDraft { } } -pub(crate) fn validate_base_currency(draft: &TableDraft) -> Option { - if draft.money_column_count() == 0 { - return None; +fn normalize_currency_input(value: &str) -> Result { + let currency = value.trim().to_ascii_uppercase(); + if rusty_money::iso::find(¤cy).is_none() { + return Err("Currency must be a three-letter ISO-4217 code".to_string()); } - let currency = draft.base_currency.trim(); - if currency.len() != 3 || !currency.chars().all(|c| c.is_ascii_alphabetic()) { - return Some("Base currency must be a three-letter ISO-4217 code".to_string()); - } - None + Ok(currency) } pub(crate) fn validate_accounting_currency(draft: &TableDraft) -> Option { @@ -720,6 +704,11 @@ mod tests { indexed: false, quantity_ledger: false, money_mode: MoneyMode::Exact, + currency: if matches!(data_type, "money" | "accounting") { + "EUR".to_string() + } else { + String::new() + }, }); draft } @@ -795,14 +784,16 @@ mod tests { } #[test] - fn money_columns_require_a_valid_base_currency() { - let mut draft = draft_with_column("total", "money"); - draft.base_currency = "EU".to_string(); - assert!(draft.validate().is_err()); + fn money_columns_require_a_valid_currency() { + let mut draft = TableDraft::new(); + draft.column_name_input = "total".to_string(); + draft.column_type_input = "money".to_string(); + draft.column_currency_input = "EU".to_string(); + assert!(draft.add_column_from_inputs().is_err()); - draft.base_currency = "eur".to_string(); - assert!(draft.validate().is_ok()); - assert_eq!(draft.into_request().unwrap().base_currency, "EUR"); + draft.column_currency_input = "eur".to_string(); + draft.add_column_from_inputs().unwrap(); + assert_eq!(draft.columns[0].currency, "EUR"); } #[test] @@ -826,8 +817,6 @@ mod tests { assert_eq!(request.accounting_currency, ""); assert_eq!(request.profile_name, "billing"); - // No money column, so no base currency either. - assert_eq!(request.base_currency, ""); } #[test] @@ -886,6 +875,7 @@ mod tests { indexed: false, quantity_ledger: false, money_mode: MoneyMode::Exact, + currency: String::new(), }); draft.toggle_row_display_candidate(2); // issued_on diff --git a/web/src/pages/add_table/state.rs b/web/src/pages/add_table/state.rs index eff4e24a..94a53241 100644 --- a/web/src/pages/add_table/state.rs +++ b/web/src/pages/add_table/state.rs @@ -28,8 +28,6 @@ pub(crate) struct BuilderForm { pub accounting_currency: String, #[serde(default)] pub table_name: String, - #[serde(default)] - pub base_currency: String, // The pending column being described in the input panel. #[serde(default)] @@ -46,6 +44,8 @@ pub(crate) struct BuilderForm { pub column_quantity_ledger_input: String, #[serde(default)] pub column_rounding_input: String, + #[serde(default)] + pub column_currency_input: String, // One entry per already-added column, in order. #[serde(default)] @@ -58,6 +58,8 @@ pub(crate) struct BuilderForm { pub column_quantity_ledger: Vec, #[serde(default)] pub column_rounding: Vec, + #[serde(default)] + pub column_currencies: Vec, // One entry per link target offered by the profile, in order. #[serde(default)] @@ -92,6 +94,7 @@ impl BuilderForm { self.column_indexed.len(), self.column_quantity_ledger.len(), self.column_rounding.len(), + self.column_currencies.len(), ] .into_iter() .min() @@ -108,6 +111,7 @@ impl BuilderForm { } else { MoneyMode::Exact }, + currency: self.column_currencies[index].clone(), }) .collect::>(); @@ -138,7 +142,6 @@ impl BuilderForm { creating_new_profile, accounting_currency: self.accounting_currency.clone(), table_name: self.table_name.clone(), - base_currency: self.base_currency.clone(), column_name_input: self.column_name_input.clone(), column_type_input: self.column_type_input.clone(), temporal_type_input: self.temporal_type_input.clone(), @@ -146,6 +149,7 @@ impl BuilderForm { column_indexing_input: self.column_indexing_input.clone(), column_quantity_ledger_input: self.column_quantity_ledger_input.clone(), column_rounding_input: self.column_rounding_input.clone(), + column_currency_input: self.column_currency_input.clone(), columns, links, row_display_columns, @@ -231,6 +235,7 @@ mod tests { column_indexed: vec!["yes".into(), "no".into()], column_quantity_ledger: vec!["no".into(), "no".into()], column_rounding: vec!["exact".into(), "half-up".into()], + column_currencies: vec![String::new(), "EUR".into()], link_tables: vec!["customer".into(), "project".into()], link_modes: vec!["required".into(), "none".into()], row_display_columns: vec!["number".into()], diff --git a/web/src/pages/add_table/ui.rs b/web/src/pages/add_table/ui.rs index 2d1c1fba..8a9764e5 100644 --- a/web/src/pages/add_table/ui.rs +++ b/web/src/pages/add_table/ui.rs @@ -70,6 +70,7 @@ mod tests { indexed: true, quantity_ledger: false, money_mode: MoneyMode::Exact, + currency: String::new(), }); draft.set_available_relation_tables(vec!["customer".to_string()]); draft.cycle_link_mode(0); @@ -126,7 +127,7 @@ mod tests { state.draft.column_type_input = "gtin".to_string(); assert!(render_builder(&state).contains(r#"name="gtin_type_input""#)); - // Money reveals rounding, and the base currency becomes editable. + // Money reveals its currency and rounding inputs. state.draft.column_type_input = "money".to_string(); let html = render_builder(&state); assert!(html.contains(r#"name="column_rounding_input""#)); diff --git a/web/src/pages/analytics/loader.rs b/web/src/pages/analytics/loader.rs index 5f5255a9..84ce9e22 100644 --- a/web/src/pages/analytics/loader.rs +++ b/web/src/pages/analytics/loader.rs @@ -144,7 +144,6 @@ fn catalog_view(catalog: &GetAnalyticsCatalogResponse) -> CatalogView { fn catalog_table_view(table: &AnalyticsTable) -> CatalogTableView { CatalogTableView { name: table.name.clone(), - base_currency: table.base_currency.clone(), starter_query: format!("SELECT *\nFROM {}\nLIMIT 100;", quote_identifier(&table.name)), columns: table .columns @@ -157,6 +156,9 @@ fn catalog_table_view(table: &AnalyticsTable) -> CatalogTableView { if !column.rounding.is_empty() { details.push_str(&format!(", rounding {}", column.rounding)); } + if !column.currency.is_empty() { + details.push_str(&format!(", currency {}", column.currency)); + } CatalogColumnView { name: column.name.clone(), insert_text: quote_identifier(&column.name), @@ -193,9 +195,6 @@ AVAILABLE ANALYTICS SCHEMA\n", for table in &catalog.tables { text.push_str(&format!("\nTABLE {}\n", quote_identifier(&table.name))); - if !table.base_currency.is_empty() { - text.push_str(&format!(" Base currency: {}\n", table.base_currency)); - } text.push_str(" Columns:\n"); for column in &table.columns { text.push_str(&format!( @@ -209,6 +208,9 @@ AVAILABLE ANALYTICS SCHEMA\n", if !column.rounding.is_empty() { text.push_str(&format!(" [rounding: {}]", column.rounding)); } + if !column.currency.is_empty() { + text.push_str(&format!(" [currency: {}]", column.currency)); + } text.push('\n'); } if !table.links.is_empty() { diff --git a/web/src/pages/analytics/state.rs b/web/src/pages/analytics/state.rs index c4b5c03d..0906cad2 100644 --- a/web/src/pages/analytics/state.rs +++ b/web/src/pages/analytics/state.rs @@ -48,7 +48,6 @@ pub(crate) struct CatalogView { pub(crate) struct CatalogTableView { pub name: String, - pub base_currency: String, pub starter_query: String, pub columns: Vec, pub links: Vec, diff --git a/web/templates/pages/add_table/builder.html b/web/templates/pages/add_table/builder.html index 2762eadc..d6123d19 100644 --- a/web/templates/pages/add_table/builder.html +++ b/web/templates/pages/add_table/builder.html @@ -48,15 +48,6 @@ hx-target="#builder" hx-swap="innerHTML" hx-vals='{"action": "refresh"}'> - {% if page.draft.show_base_currency() %} - - {% else %} - - {% endif %} @@ -100,6 +91,10 @@ {% endif %} {% if page.draft.show_rounding() %} +