teamcraft/domain/
as_built.rs1use serde::{Deserialize, Serialize};
4
5use super::ItemType;
6
7impl ItemType {
8 pub fn can_be_built_to(self) -> bool {
11 matches!(
12 self,
13 ItemType::Part | ItemType::Assembly | ItemType::Software
14 )
15 }
16}
17
18#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
20#[serde(rename_all = "snake_case")]
21pub enum DeviationKind {
22 Dimension,
24 Material,
26 Component,
29 Process,
31 Other,
32}
33
34impl DeviationKind {
35 pub const ALL: [DeviationKind; 5] = [
36 DeviationKind::Dimension,
37 DeviationKind::Material,
38 DeviationKind::Component,
39 DeviationKind::Process,
40 DeviationKind::Other,
41 ];
42
43 pub fn as_str(self) -> &'static str {
44 match self {
45 DeviationKind::Dimension => "dimension",
46 DeviationKind::Material => "material",
47 DeviationKind::Component => "component",
48 DeviationKind::Process => "process",
49 DeviationKind::Other => "other",
50 }
51 }
52
53 pub fn label(self) -> &'static str {
54 match self {
55 DeviationKind::Dimension => "Dimension",
56 DeviationKind::Material => "Material",
57 DeviationKind::Component => "Component",
58 DeviationKind::Process => "Process",
59 DeviationKind::Other => "Other",
60 }
61 }
62
63 pub fn parse(s: &str) -> Option<DeviationKind> {
64 DeviationKind::ALL
65 .into_iter()
66 .find(|k| k.as_str() == s.trim().to_ascii_lowercase())
67 }
68}
69
70#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
72#[serde(rename_all = "snake_case")]
73pub enum Disposition {
74 Open,
76 UseAsIs,
78 Rework,
80 Repair,
82 Scrap,
84}
85
86impl Disposition {
87 pub const ALL: [Disposition; 5] = [
88 Disposition::Open,
89 Disposition::UseAsIs,
90 Disposition::Rework,
91 Disposition::Repair,
92 Disposition::Scrap,
93 ];
94
95 pub fn as_str(self) -> &'static str {
96 match self {
97 Disposition::Open => "open",
98 Disposition::UseAsIs => "use_as_is",
99 Disposition::Rework => "rework",
100 Disposition::Repair => "repair",
101 Disposition::Scrap => "scrap",
102 }
103 }
104
105 pub fn label(self) -> &'static str {
106 match self {
107 Disposition::Open => "Open",
108 Disposition::UseAsIs => "Use as is",
109 Disposition::Rework => "Rework",
110 Disposition::Repair => "Repair",
111 Disposition::Scrap => "Scrap",
112 }
113 }
114
115 pub fn parse(s: &str) -> Option<Disposition> {
117 let s = s.trim().to_ascii_lowercase().replace(['-', ' '], "_");
118 if s.is_empty() {
119 return Some(Disposition::Open);
120 }
121 Disposition::ALL.into_iter().find(|d| d.as_str() == s)
122 }
123}
124
125#[cfg(test)]
126mod tests {
127 use super::*;
128 use crate::domain::{NumberContext, NumberScheme};
129
130 #[test]
131 fn as_built_type_and_enums() {
132 let ctx = NumberContext {
133 project: "ROVER",
134 item_type: ItemType::AsBuilt,
135 year: 2026,
136 month: 11,
137 };
138 assert_eq!(NumberScheme::default_scheme().format(&ctx, 7), "AB-000007");
139 assert_eq!(ItemType::parse("As-Built"), Some(ItemType::AsBuilt));
140 assert_eq!(ItemType::parse("as built"), Some(ItemType::AsBuilt));
141 assert!(ItemType::Assembly.can_be_built_to());
142 assert!(!ItemType::AsBuilt.can_be_built_to());
143 assert!(!ItemType::Simulation.can_be_built_to());
144 assert!(!ItemType::Document.can_be_built_to());
145 for k in DeviationKind::ALL {
146 assert_eq!(DeviationKind::parse(k.as_str()), Some(k));
147 }
148 assert_eq!(
149 DeviationKind::parse(" Dimension "),
150 Some(DeviationKind::Dimension)
151 );
152 assert_eq!(DeviationKind::parse("colour"), None);
153 for d in Disposition::ALL {
154 assert_eq!(Disposition::parse(d.as_str()), Some(d));
155 }
156 assert_eq!(Disposition::parse("Use-as-is"), Some(Disposition::UseAsIs));
157 assert_eq!(Disposition::parse("use as is"), Some(Disposition::UseAsIs));
158 assert_eq!(Disposition::parse(""), Some(Disposition::Open));
159 assert_eq!(Disposition::parse("ship it"), None);
160 }
161
162 #[test]
164 fn labels() {
165 let kinds: Vec<&str> = DeviationKind::ALL.iter().map(|k| k.label()).collect();
166 assert_eq!(
167 kinds,
168 ["Dimension", "Material", "Component", "Process", "Other"]
169 );
170 let dispositions: Vec<&str> = Disposition::ALL.iter().map(|d| d.label()).collect();
171 assert_eq!(
172 dispositions,
173 ["Open", "Use as is", "Rework", "Repair", "Scrap"]
174 );
175 }
176}