Files
biggus-dickus/crates/domain/src/object.rs
T

109 lines
3.2 KiB
Rust

use serde::{Deserialize, Serialize};
use time::{Date, OffsetDateTime};
use crate::ObjectId;
/// Publication state of a catalogue record.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
#[serde(rename_all = "lowercase")]
pub enum Visibility {
/// Work in progress; not shown anywhere public.
#[default]
Draft,
/// Complete but internal-only.
Internal,
/// Published; eligible for the public API.
Public,
}
impl Visibility {
pub fn as_str(&self) -> &'static str {
match self {
Visibility::Draft => "draft",
Visibility::Internal => "internal",
Visibility::Public => "public",
}
}
pub fn from_db(s: &str) -> Option<Self> {
match s {
"draft" => Some(Visibility::Draft),
"internal" => Some(Visibility::Internal),
"public" => Some(Visibility::Public),
_ => None,
}
}
}
/// The mutable inventory-minimum fields of a catalogue object.
#[derive(Debug, Clone, PartialEq)]
pub struct ObjectInput {
pub object_number: String,
pub object_name: String,
pub number_of_objects: i32,
pub brief_description: Option<String>,
pub current_location: Option<String>,
pub current_owner: Option<String>,
pub recorder: Option<String>,
pub recording_date: Option<Date>,
pub visibility: Visibility,
}
/// A catalogue object (or group of objects), read back from storage.
#[derive(Debug, Clone, PartialEq)]
pub struct CatalogueObject {
pub id: ObjectId,
pub object_number: String,
pub object_name: String,
pub number_of_objects: i32,
pub brief_description: Option<String>,
pub current_location: Option<String>,
pub current_owner: Option<String>,
pub recorder: Option<String>,
pub recording_date: Option<Date>,
pub visibility: Visibility,
pub created_at: OffsetDateTime,
pub updated_at: OffsetDateTime,
}
impl CatalogueObject {
/// The mutable fields as an [`ObjectInput`] (used to diff against an update).
pub fn to_input(&self) -> ObjectInput {
ObjectInput {
object_number: self.object_number.clone(),
object_name: self.object_name.clone(),
number_of_objects: self.number_of_objects,
brief_description: self.brief_description.clone(),
current_location: self.current_location.clone(),
current_owner: self.current_owner.clone(),
recorder: self.recorder.clone(),
recording_date: self.recording_date,
visibility: self.visibility,
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn visibility_round_trips_and_defaults_to_draft() {
for v in [Visibility::Draft, Visibility::Internal, Visibility::Public] {
assert_eq!(Visibility::from_db(v.as_str()), Some(v));
}
assert_eq!(Visibility::from_db("secret"), None);
assert_eq!(Visibility::default(), Visibility::Draft);
}
#[test]
fn visibility_serde_matches_as_str() {
for v in [Visibility::Draft, Visibility::Internal, Visibility::Public] {
assert_eq!(
serde_json::to_value(v).unwrap(),
serde_json::Value::String(v.as_str().to_owned())
);
}
}
}