use serde::{Deserialize, Serialize};
use super::MOD_PATH;
use crate::common::event::{Event, EventPayload};
use crate::common::related_party::RelatedParty;
use crate::tmf673::geographic_address::GeographicAddress;
use crate::{gen_code, HasId, HasName, TMFEvent};
use chrono::Utc;
use tmflib_derive::{HasId, HasName};
use uuid::Uuid;
const CLASS_PATH: &str = "geographicSite";
const DEFAULT_TZ: &str = "AEST";
const CODE_PREFIX: &str = "S-";
#[derive(Clone, Debug, Default, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct PlaceRefOrValue {
id: String,
href: String,
name: String,
}
impl From<GeographicAddress> for PlaceRefOrValue {
fn from(value: GeographicAddress) -> Self {
PlaceRefOrValue {
id: value.get_id(),
href: value.get_href(),
name: value.get_name(),
}
}
}
#[derive(Clone, Debug, Default, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct HourPeriod {
start_hour: String,
end_hour: String,
}
#[derive(Clone, Debug, Default, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct CalendarPeriod {
day: Option<String>,
status: Option<String>,
time_zone: Option<String>,
hour_period: Option<Vec<HourPeriod>>,
}
impl CalendarPeriod {
pub fn business_hours() -> CalendarPeriod {
CalendarPeriod {
day: Some("weekdays".to_string()),
status: Some("open".to_string()),
time_zone: Some(DEFAULT_TZ.to_string()),
hour_period: Some(vec![HourPeriod {
start_hour: "09:00 am".to_string(),
end_hour: "05:00 pm".to_string(),
}]),
}
}
}
#[derive(Clone, Debug, Default, Deserialize, HasId, HasName, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct GeographicSite {
#[serde(skip_serializing_if = "Option::is_none")]
pub id: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub href: Option<String>,
pub name: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub code: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
place: Option<PlaceRefOrValue>,
#[serde(skip_serializing_if = "Option::is_none")]
pub status: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub calendar: Option<Vec<CalendarPeriod>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub related_party: Option<Vec<RelatedParty>>,
}
impl GeographicSite {
pub fn new(name: impl Into<String>) -> GeographicSite {
let mut site = GeographicSite::create();
site.name = Some(name.into());
site.generate_code(None);
site
}
pub fn place(mut self, place: PlaceRefOrValue) -> GeographicSite {
self.place = Some(place);
self
}
pub fn calendar(mut self, calendar: CalendarPeriod) -> GeographicSite {
self.calendar.as_mut().unwrap().push(calendar);
self
}
pub fn generate_code(&mut self, offset: Option<u32>) {
let (code, _hash) = gen_code(
self.get_name(),
self.get_id(),
offset,
Some(CODE_PREFIX.to_string()),
None,
);
self.code = Some(code);
}
}
#[derive(Clone, Debug, Deserialize, Serialize)]
pub enum GeographicSiteEventType {
GeographicSiteCreateEvent,
GeographicSiteAttributeValueChangeEvent,
GeographicSiteStatusChangeEvent,
GeographicSiteDeleteEvent,
}
#[derive(Clone, Debug, Default, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct GeographicSiteEvent {
pub geographic_site: GeographicSite,
}
impl TMFEvent<GeographicSiteEvent> for GeographicSite {
fn event(&self) -> GeographicSiteEvent {
GeographicSiteEvent {
geographic_site: self.clone(),
}
}
}
impl EventPayload<GeographicSiteEvent> for GeographicSite {
type Subject = GeographicSite;
type EventType = GeographicSiteEventType;
fn to_event(&self, event_type: Self::EventType) -> Event<GeographicSiteEvent, Self::EventType> {
let now = Utc::now();
let event_time = chrono::DateTime::from_timestamp(now.timestamp(), 0).unwrap();
let desc = format!(
"{:?} for {} [{}]",
event_type,
self.get_name(),
self.get_id()
);
Event {
correlation_id: None,
description: Some(desc),
domain: Some(GeographicSite::get_class()),
event_id: Uuid::new_v4().to_string(),
field_path: None,
href: Some(self.get_href()),
id: Some(self.get_id()),
title: Some(self.get_name()),
event_time: event_time.to_string(),
priority: None,
time_occurred: Some(event_time.to_string()),
event_type,
event: self.event(),
}
}
}