Skip to main content

datasynth_core/models/
quality_inspection.rs

1//! Quality inspection models for manufacturing processes.
2//!
3//! These models represent quality inspections performed on materials
4//! during incoming receipt, in-process production, and final output.
5
6use chrono::NaiveDate;
7use rust_decimal::Decimal;
8use serde::{Deserialize, Serialize};
9use std::collections::HashMap;
10
11use super::graph_properties::{GraphPropertyValue, ToNodeProperties};
12
13/// Result of a quality inspection.
14#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, Default)]
15#[serde(rename_all = "snake_case")]
16pub enum InspectionResult {
17    /// Material accepted without conditions
18    #[default]
19    Accepted,
20    /// Material rejected
21    Rejected,
22    /// Material accepted with conditions or concessions
23    Conditionally,
24    /// Inspection not yet completed
25    Pending,
26}
27
28/// Type of quality inspection.
29#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, Default)]
30#[serde(rename_all = "snake_case")]
31pub enum InspectionType {
32    /// Inspection of incoming materials from vendors
33    #[default]
34    Incoming,
35    /// Inspection during production process
36    InProcess,
37    /// Final inspection before delivery or storage
38    Final,
39    /// Random sampling inspection
40    Random,
41    /// Scheduled periodic inspection
42    Periodic,
43}
44
45/// A quality inspection record for a material lot.
46#[derive(Debug, Clone, Serialize, Deserialize)]
47pub struct QualityInspection {
48    /// Unique inspection identifier
49    pub inspection_id: String,
50    /// Company code this inspection belongs to
51    pub company_code: String,
52    /// Type of reference document (e.g., "production_order", "goods_receipt")
53    pub reference_type: String,
54    /// Identifier of the reference document
55    pub reference_id: String,
56    /// Material being inspected
57    pub material_id: String,
58    /// Description of the material being inspected
59    pub material_description: String,
60    /// Type of inspection performed
61    pub inspection_type: InspectionType,
62    /// Date the inspection was performed
63    pub inspection_date: NaiveDate,
64    /// Inspector who performed the inspection
65    pub inspector_id: Option<String>,
66    /// Total lot size under inspection
67    #[serde(with = "rust_decimal::serde::str")]
68    pub lot_size: Decimal,
69    /// Sample size drawn for inspection
70    #[serde(with = "rust_decimal::serde::str")]
71    pub sample_size: Decimal,
72    /// Number of defects found
73    pub defect_count: u32,
74    /// Defect rate (defect_count / sample_size)
75    pub defect_rate: f64,
76    /// Overall inspection result
77    pub result: InspectionResult,
78    /// Individual inspection characteristics measured
79    pub characteristics: Vec<InspectionCharacteristic>,
80    /// Disposition action (e.g., "use_as_is", "return_to_vendor", "scrap")
81    pub disposition: Option<String>,
82    /// Additional notes or observations
83    pub notes: Option<String>,
84}
85
86impl ToNodeProperties for QualityInspection {
87    fn node_type_name(&self) -> &'static str {
88        "quality_inspection"
89    }
90    fn node_type_code(&self) -> u16 {
91        341
92    }
93    fn to_node_properties(&self) -> HashMap<String, GraphPropertyValue> {
94        let mut p = HashMap::new();
95        p.insert(
96            "inspectionId".into(),
97            GraphPropertyValue::String(self.inspection_id.clone()),
98        );
99        p.insert(
100            "entityCode".into(),
101            GraphPropertyValue::String(self.company_code.clone()),
102        );
103        p.insert(
104            "referenceType".into(),
105            GraphPropertyValue::String(self.reference_type.clone()),
106        );
107        p.insert(
108            "referenceId".into(),
109            GraphPropertyValue::String(self.reference_id.clone()),
110        );
111        p.insert(
112            "materialId".into(),
113            GraphPropertyValue::String(self.material_id.clone()),
114        );
115        p.insert(
116            "materialDescription".into(),
117            GraphPropertyValue::String(self.material_description.clone()),
118        );
119        p.insert(
120            "inspectionType".into(),
121            GraphPropertyValue::String(format!("{:?}", self.inspection_type)),
122        );
123        p.insert(
124            "inspectionDate".into(),
125            GraphPropertyValue::Date(self.inspection_date),
126        );
127        p.insert("lotSize".into(), GraphPropertyValue::Decimal(self.lot_size));
128        p.insert(
129            "inspectedQuantity".into(),
130            GraphPropertyValue::Decimal(self.sample_size),
131        );
132        p.insert(
133            "defectQuantity".into(),
134            GraphPropertyValue::Int(self.defect_count as i64),
135        );
136        p.insert(
137            "defectRate".into(),
138            GraphPropertyValue::Float(self.defect_rate),
139        );
140        p.insert(
141            "result".into(),
142            GraphPropertyValue::String(format!("{:?}", self.result)),
143        );
144        p.insert(
145            "isPassed".into(),
146            GraphPropertyValue::Bool(matches!(
147                self.result,
148                InspectionResult::Accepted | InspectionResult::Conditionally
149            )),
150        );
151        p
152    }
153}
154
155/// A single measured characteristic within a quality inspection.
156#[derive(Debug, Clone, Serialize, Deserialize)]
157pub struct InspectionCharacteristic {
158    /// Name of the characteristic (e.g., "diameter", "weight", "tensile_strength")
159    pub name: String,
160    /// Target specification value
161    pub target_value: f64,
162    /// Actual measured value
163    pub actual_value: f64,
164    /// Lower specification limit
165    pub lower_limit: f64,
166    /// Upper specification limit
167    pub upper_limit: f64,
168    /// Whether this characteristic passed inspection
169    pub passed: bool,
170}