datasynth_core/models/cost_center.rs
1//! Cost center hierarchy model for organizational cost accounting.
2//!
3//! Represents the two-level cost center hierarchy (departments → sub-departments)
4//! used in SAP-style management accounting (CO module).
5
6use serde::{Deserialize, Serialize};
7
8/// Category classification for cost centers.
9#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, Default)]
10#[serde(rename_all = "snake_case")]
11pub enum CostCenterCategory {
12 /// General and administrative functions (HR, Finance, Legal, IT)
13 #[default]
14 Administration,
15 /// Direct production or manufacturing cost centers
16 Production,
17 /// Sales and marketing cost centers
18 Sales,
19 /// Research and development cost centers
20 RAndD,
21 /// Group / holding company level cost centers
22 Corporate,
23}
24
25impl std::fmt::Display for CostCenterCategory {
26 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
27 match self {
28 Self::Administration => write!(f, "Administration"),
29 Self::Production => write!(f, "Production"),
30 Self::Sales => write!(f, "Sales"),
31 Self::RAndD => write!(f, "R&D"),
32 Self::Corporate => write!(f, "Corporate"),
33 }
34 }
35}
36
37/// A cost center node in the organizational cost hierarchy.
38///
39/// Cost centers are arranged in a two-level tree:
40/// - **Level 1** (parent): Represents a department (e.g., Finance, Production).
41/// These have `parent_id == None`.
42/// - **Level 2** (child): Represents a sub-department or functional unit
43/// (e.g., Accounts Payable within Finance). These have `parent_id == Some(...)`.
44#[derive(Debug, Clone, Serialize, Deserialize)]
45pub struct CostCenter {
46 /// Unique cost center identifier (e.g., "CC-C001-FIN")
47 pub id: String,
48
49 /// Human-readable name (e.g., "Finance Department")
50 pub name: String,
51
52 /// Parent cost center ID for level-2 nodes; `None` for level-1 department nodes.
53 pub parent_id: Option<String>,
54
55 /// Company code this cost center belongs to.
56 pub company_code: String,
57
58 /// Employee ID of the person responsible for this cost center.
59 pub responsible_person: Option<String>,
60
61 /// Functional category of this cost center.
62 pub category: CostCenterCategory,
63
64 /// Hierarchy level (1 = department, 2 = sub-department).
65 pub level: u8,
66
67 /// Whether this cost center is currently active.
68 pub is_active: bool,
69}
70
71impl CostCenter {
72 /// Create a new level-1 (department) cost center.
73 pub fn department(
74 id: impl Into<String>,
75 name: impl Into<String>,
76 company_code: impl Into<String>,
77 category: CostCenterCategory,
78 ) -> Self {
79 Self {
80 id: id.into(),
81 name: name.into(),
82 parent_id: None,
83 company_code: company_code.into(),
84 responsible_person: None,
85 category,
86 level: 1,
87 is_active: true,
88 }
89 }
90
91 /// Create a new level-2 (sub-department) cost center.
92 pub fn sub_department(
93 id: impl Into<String>,
94 name: impl Into<String>,
95 parent_id: impl Into<String>,
96 company_code: impl Into<String>,
97 category: CostCenterCategory,
98 ) -> Self {
99 Self {
100 id: id.into(),
101 name: name.into(),
102 parent_id: Some(parent_id.into()),
103 company_code: company_code.into(),
104 responsible_person: None,
105 category,
106 level: 2,
107 is_active: true,
108 }
109 }
110}