Skip to main content

epcis_models/
document.rs

1//! `EPCISDocument` schema definition.
2
3#![deny(missing_docs)]
4#![deny(unsafe_code)]
5#![warn(clippy::pedantic)]
6#![allow(clippy::module_name_repetitions)]
7
8use serde::{Deserialize, Serialize};
9use chrono::{DateTime, Utc};
10use crate::events::EPCISEvent;
11
12/// Represents the top-level EPCIS 2.0 JSON-LD Document.
13#[derive(Debug, Clone, Serialize, Deserialize)]
14#[serde(rename_all = "camelCase")]
15pub struct EPCISDocument {
16    /// Context property containing schema mappings for JSON-LD compliance.
17    #[serde(rename = "@context")]
18    pub context: serde_json::Value,
19    
20    /// Document identifier (optional).
21    #[serde(skip_serializing_if = "Option::is_none")]
22    pub id: Option<String>,
23    
24    /// Type identifier, always "`EPCISDocument`".
25    #[serde(rename = "type")]
26    pub r#type: String,
27    
28    /// Schema version, typically "2.0".
29    pub schema_version: String,
30    
31    /// Creation timestamp of this document.
32    pub creation_date: DateTime<Utc>,
33    
34    /// Header containing master data vocabulary context (optional).
35    #[serde(skip_serializing_if = "Option::is_none")]
36    pub epcis_header: Option<EPCISHeader>,
37    
38    /// Body containing the list of actual tracking events.
39    pub epcis_body: EPCISBody,
40    
41    /// Extension elements.
42    #[serde(flatten)]
43    pub extensions: serde_json::Map<String, serde_json::Value>,
44}
45
46impl EPCISDocument {
47    /// Creates a standard EPCIS 2.0 document from a list of events.
48    #[must_use]
49    pub fn new(event_list: Vec<EPCISEvent>) -> Self {
50        Self {
51            context: serde_json::json!([
52                "https://ref.gs1.org/standards/epcis/2.0.0/epcis-context.jsonld"
53            ]),
54            id: None,
55            r#type: "EPCISDocument".to_string(),
56            schema_version: "2.0".to_string(),
57            creation_date: Utc::now(),
58            epcis_header: None,
59            epcis_body: EPCISBody { event_list },
60            extensions: serde_json::Map::new(),
61        }
62    }
63}
64
65/// Header containing metadata and master data dictionary elements.
66#[derive(Debug, Clone, Serialize, Deserialize)]
67#[serde(rename_all = "camelCase")]
68pub struct EPCISHeader {
69    /// Optional master data vocabulary list
70    #[serde(skip_serializing_if = "Option::is_none")]
71    pub epcis_master_data: Option<EPCISMasterData>,
72}
73
74/// List of master data elements mapped to vocabularies.
75#[derive(Debug, Clone, Serialize, Deserialize)]
76#[serde(rename_all = "camelCase")]
77pub struct EPCISMasterData {
78    /// The master data vocabulary list
79    pub vocabulary_list: Vec<VocabularyElement>,
80}
81
82/// Vocabularies mapping IDs to types and attributes.
83#[derive(Debug, Clone, Serialize, Deserialize)]
84#[serde(rename_all = "camelCase")]
85pub struct VocabularyElement {
86    /// Type of the vocabulary element
87    #[serde(rename = "type")]
88    pub r#type: String,
89    /// List of attributes and mappings
90    pub element_list: Vec<VocabularyElementList>,
91}
92
93/// A specific master data attribute / children list mapping.
94#[derive(Debug, Clone, Serialize, Deserialize)]
95#[serde(rename_all = "camelCase")]
96pub struct VocabularyElementList {
97    /// Identifier of the element
98    pub id: String,
99    /// Attributes linked to the identifier (optional)
100    #[serde(skip_serializing_if = "Option::is_none")]
101    pub attributes: Option<Vec<VocabularyAttribute>>,
102    /// List of child IDs under this element
103    #[serde(skip_serializing_if = "Option::is_none")]
104    pub children: Option<Vec<String>>,
105}
106
107/// Attribute property value within vocabulary configuration.
108#[derive(Debug, Clone, Serialize, Deserialize)]
109#[serde(rename_all = "camelCase")]
110pub struct VocabularyAttribute {
111    /// Attribute identifier
112    pub id: String,
113    /// Attribute value
114    pub value: serde_json::Value,
115}
116
117/// Body container holding the array of EPCIS events.
118#[derive(Debug, Clone, Serialize, Deserialize)]
119#[serde(rename_all = "camelCase")]
120pub struct EPCISBody {
121    /// List of events in the body
122    pub event_list: Vec<EPCISEvent>,
123}