use serde::Deserialize;
use std::collections::HashMap;
use std::sync::OnceLock;
const EMBEDDED_JSON: &str = include_str!("../../data/artikel_id_codelist.json");
#[derive(Debug, Deserialize)]
struct RawFile {
version: String,
codes: HashMap<String, RawEntry>,
}
#[derive(Debug, Deserialize)]
struct RawEntry {
description: String,
einheit: String,
utilmd: MessageFlags,
pricat: MessageFlags,
invoic: MessageFlags,
}
#[derive(Debug, Clone, Copy, Deserialize)]
pub struct MessageFlags {
pub codeverwendung: bool,
pub preisangabe: bool,
}
#[derive(Debug, Clone)]
pub struct ArtikelIdEntry {
pub description: String,
pub einheit: String,
pub utilmd: MessageFlags,
pub pricat: MessageFlags,
pub invoic: MessageFlags,
}
#[derive(Debug, Clone, Copy)]
pub enum CodelistColumn {
UtilmdCodeverwendung,
UtilmdPreisangabe,
PricatCodeverwendung,
PricatPreisangabe,
InvoicCodeverwendung,
InvoicPreisangabe,
}
#[derive(Debug)]
pub struct ArtikelIdCodelist {
version: String,
codes: HashMap<String, ArtikelIdEntry>,
}
impl ArtikelIdCodelist {
pub fn from_json(json: &str) -> Result<Self, serde_json::Error> {
let raw: RawFile = serde_json::from_str(json)?;
let codes = raw
.codes
.into_iter()
.map(|(k, v)| {
(
k,
ArtikelIdEntry {
description: v.description,
einheit: v.einheit,
utilmd: v.utilmd,
pricat: v.pricat,
invoic: v.invoic,
},
)
})
.collect();
Ok(Self {
version: raw.version,
codes,
})
}
pub fn embedded() -> &'static Self {
static CELL: OnceLock<ArtikelIdCodelist> = OnceLock::new();
CELL.get_or_init(|| {
ArtikelIdCodelist::from_json(EMBEDDED_JSON)
.expect("embedded artikel_id_codelist.json is malformed")
})
}
pub fn version(&self) -> &str {
&self.version
}
pub fn flag(&self, code: &str, column: CodelistColumn) -> Option<bool> {
let entry = self.codes.get(code)?;
use CodelistColumn::*;
Some(match column {
UtilmdCodeverwendung => entry.utilmd.codeverwendung,
UtilmdPreisangabe => entry.utilmd.preisangabe,
PricatCodeverwendung => entry.pricat.codeverwendung,
PricatPreisangabe => entry.pricat.preisangabe,
InvoicCodeverwendung => entry.invoic.codeverwendung,
InvoicPreisangabe => entry.invoic.preisangabe,
})
}
pub fn contains(&self, code: &str) -> bool {
self.codes.contains_key(code)
}
}