Skip to main content

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}