account field and ledger_accounts is now fully system

This commit is contained in:
Priec
2026-08-17 19:43:41 +02:00
parent 444ca26d47
commit 8b43a9eb41
3 changed files with 23 additions and 7 deletions

2
client

Submodule client updated: 455e109f47...42f163beae

2
server

Submodule server updated: 03a8e1887a...8d8f153863

View File

@@ -33,6 +33,9 @@ use crate::definitions::table_definition::{
/// The compound type that posts a row to the profile's books. /// The compound type that posts a row to the profile's books.
pub(crate) const ACCOUNTING_FIELD_TYPE: &str = "accounting"; pub(crate) const ACCOUNTING_FIELD_TYPE: &str = "accounting";
/// The public text path for a row in the profile's account catalogue.
pub(crate) const ACCOUNT_FIELD_TYPE: &str = "account";
/// The compound type that moves a balance between two accounting periods. /// The compound type that moves a balance between two accounting periods.
pub(crate) const ACCOUNTING_TRANSFER_FIELD_TYPE: &str = "accounting_transfer"; pub(crate) const ACCOUNTING_TRANSFER_FIELD_TYPE: &str = "accounting_transfer";
@@ -41,7 +44,11 @@ pub(crate) const ACCOUNTING_TRANSFER_FIELD_TYPE: &str = "accounting_transfer";
/// Both post to a profile's books, and a global table belongs to every profile /// Both post to a profile's books, and a global table belongs to every profile
/// at once — there is no one set of books for it to post to, so the server /// at once — there is no one set of books for it to post to, so the server
/// refuses the pair outright rather than picking a profile for them. /// refuses the pair outright rather than picking a profile for them.
const PROFILE_ONLY_TYPES: [&str; 2] = [ACCOUNTING_FIELD_TYPE, ACCOUNTING_TRANSFER_FIELD_TYPE]; const PROFILE_ONLY_TYPES: [&str; 3] = [
ACCOUNT_FIELD_TYPE,
ACCOUNTING_FIELD_TYPE,
ACCOUNTING_TRANSFER_FIELD_TYPE,
];
/// The profile's chart of accounts. A row reaches it through an ACCOUNTING /// The profile's chart of accounts. A row reaches it through an ACCOUNTING
/// definition row, never through a link declared by hand. /// definition row, never through a link declared by hand.
@@ -51,6 +58,7 @@ const TYPE_DISPLAY_ORDER: &[&str] = &[
"text", "text",
"boolean", "boolean",
"money", "money",
"account",
"accounting", "accounting",
"accounting_transfer", "accounting_transfer",
"int", "int",
@@ -154,7 +162,7 @@ impl ColumnCatalog {
/// the creation-only types: they bring schema-managed companion columns /// the creation-only types: they bring schema-managed companion columns
/// that cannot be bolted onto a table that already exists. /// that cannot be bolted onto a table that already exists.
/// ///
/// `global` drops the two types that post to a profile's books, which a /// `global` drops the profile accounting types, which a
/// table shared by every profile has no single one of. /// table shared by every profile has no single one of.
pub(crate) fn offered_types(&self, creating_table: bool, global: bool) -> Vec<String> { pub(crate) fn offered_types(&self, creating_table: bool, global: bool) -> Vec<String> {
let mut offered = Vec::new(); let mut offered = Vec::new();
@@ -1615,6 +1623,11 @@ pub(crate) mod tests {
/// the types a client may not declare as well as the ones it may. /// the types a client may not declare as well as the ones it may.
pub(crate) fn catalog() -> ColumnCatalog { pub(crate) fn catalog() -> ColumnCatalog {
ColumnCatalog::new(vec![ ColumnCatalog::new(vec![
ColumnType {
sql_type: "BIGINT".to_string(),
creation_only: true,
..declarable("account")
},
ColumnType { ColumnType {
requires_currency: true, requires_currency: true,
// The companions the server reports with the type, in the // The companions the server reports with the type, in the
@@ -1730,6 +1743,7 @@ pub(crate) mod tests {
let offered = draft().offered_types(); let offered = draft().offered_types();
assert!(offered.contains(&"numeric".to_string())); assert!(offered.contains(&"numeric".to_string()));
assert!(offered.contains(&"account".to_string()));
assert!(offered.contains(&"accounting_transfer".to_string())); assert!(offered.contains(&"accounting_transfer".to_string()));
assert!(offered.contains(&"decimal".to_string())); assert!(offered.contains(&"decimal".to_string()));
// Families are one choice, resolved by a follow-up field. // Families are one choice, resolved by a follow-up field.
@@ -1752,6 +1766,7 @@ pub(crate) mod tests {
assert!(!appendable.contains(&"accounting".to_string())); assert!(!appendable.contains(&"accounting".to_string()));
assert!(!appendable.contains(&"accounting_transfer".to_string())); assert!(!appendable.contains(&"accounting_transfer".to_string()));
assert!(!appendable.contains(&"account".to_string()));
assert!(appendable.contains(&"money".to_string())); assert!(appendable.contains(&"money".to_string()));
} }
@@ -1849,7 +1864,7 @@ pub(crate) mod tests {
#[test] #[test]
fn an_append_panel_refuses_a_creation_only_column() { fn an_append_panel_refuses_a_creation_only_column() {
for field_type in ["accounting", "accounting_transfer"] { for field_type in ["account", "accounting", "accounting_transfer"] {
let mut draft = ColumnDraft::for_append(catalog()); let mut draft = ColumnDraft::for_append(catalog());
draft.type_input = field_type.to_string(); draft.type_input = field_type.to_string();
assert!(draft.add_from_inputs(crate::i18n::Locale::default()).is_err()); assert!(draft.add_from_inputs(crate::i18n::Locale::default()).is_err());
@@ -1935,7 +1950,7 @@ pub(crate) mod tests {
/// type's name and there is nothing to index. /// type's name and there is nothing to index.
#[test] #[test]
fn a_compound_column_is_named_after_its_type_and_never_indexed() { fn a_compound_column_is_named_after_its_type_and_never_indexed() {
for field_type in ["accounting", "accounting_transfer"] { for field_type in ["account", "accounting", "accounting_transfer"] {
let mut draft = draft(); let mut draft = draft();
draft.name_input = "whatever".to_string(); draft.name_input = "whatever".to_string();
draft.type_input = field_type.to_string(); draft.type_input = field_type.to_string();
@@ -2262,9 +2277,10 @@ pub(crate) mod tests {
let offered = draft.offered_types(); let offered = draft.offered_types();
assert!(!offered.contains(&"accounting".to_string())); assert!(!offered.contains(&"accounting".to_string()));
assert!(!offered.contains(&"accounting_transfer".to_string())); assert!(!offered.contains(&"accounting_transfer".to_string()));
assert!(!offered.contains(&"account".to_string()));
assert!(offered.contains(&"money".to_string())); assert!(offered.contains(&"money".to_string()));
for field_type in ["accounting", "accounting_transfer"] { for field_type in ["account", "accounting", "accounting_transfer"] {
let mut draft = draft.clone(); let mut draft = draft.clone();
draft.type_input = field_type.to_string(); draft.type_input = field_type.to_string();
let error = draft.add_from_inputs(crate::i18n::Locale::default()).unwrap_err(); let error = draft.add_from_inputs(crate::i18n::Locale::default()).unwrap_err();