use super::product_order_item::ProductOrderItem;
use crate::common::event::{Event, EventPayload};
use crate::common::note::Note;
use crate::common::related_party::RelatedParty;
use crate::common::tmf_error::TMFError;
use crate::tmf641::service_order::ServiceOrder;
use crate::tmf651::agreement::AgreementRef;
use crate::tmf663::shopping_cart::ShoppingCart;
use crate::{
vec_insert, DateTime, HasDescription, HasId, HasLastUpdate, HasNote, HasRelatedParty, TMFEvent,
Uri,
};
use chrono::Utc;
use serde::{Deserialize, Serialize};
use tmflib_derive::{HasDescription, HasId, HasNote, HasRelatedParty};
use super::MOD_PATH;
const CLASS_PATH: &str = "productOrder";
#[derive(Clone, Default, Debug, Deserialize, Serialize)]
pub struct ProductOrderRef {
pub href: Uri,
pub id: String,
pub name: String,
#[serde(skip_serializing_if = "Option::is_none")]
#[serde(rename = "@baseType")]
base_type: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
#[serde(rename = "@referredType")]
referred_type: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
#[serde(rename = "@schemaLocation")]
schema_location: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
#[serde(rename = "@type")]
r#type: Option<String>,
}
impl From<ProductOrder> for ProductOrderRef {
fn from(value: ProductOrder) -> Self {
let name = value
.description
.as_deref()
.unwrap_or("No Order Description");
ProductOrderRef {
href: value.get_href(),
id: value.get_id(),
name: name.to_string(),
r#type: Some("ProductOrder".to_string()),
..Default::default()
}
}
}
impl From<&ProductOrder> for ProductOrderRef {
fn from(value: &ProductOrder) -> Self {
let name = value
.description
.as_deref()
.unwrap_or("No Order Description");
ProductOrderRef {
href: value.get_href(),
id: value.get_id(),
name: name.to_string(),
r#type: Some("ProductOrder".to_string()),
..Default::default()
}
}
}
#[derive(Clone, Default, Debug, Deserialize, Serialize)]
pub enum ProductOrderEventType {
#[default]
ProductOrderCreateEvent,
ProductOrderAttributeValueChangeEvent,
ProductOrderDeleteEvent,
ProductOrderStateChangeEvent,
ProductOrderInformationRequiredEvent,
}
#[derive(Clone, Default, Debug, Deserialize, Serialize)]
pub struct ProductOrderEvent {
pub order: ProductOrder,
}
impl TMFEvent<ProductOrderEvent> for ProductOrder {
fn event(&self) -> ProductOrderEvent {
ProductOrderEvent {
order: self.clone(),
}
}
}
impl EventPayload<ProductOrderEvent> for ProductOrder {
type Subject = ProductOrder;
type EventType = ProductOrderEventType;
fn to_event(&self, event_type: Self::EventType) -> Event<ProductOrderEvent, Self::EventType> {
let desc = format!("{:?} for order {}", event_type, self.get_id());
let now = Utc::now();
let event_time = chrono::DateTime::from_timestamp(now.timestamp(), 0).unwrap();
Event {
id: Some(self.get_id()),
href: Some(self.get_href()),
description: Some(desc),
event_time: event_time.to_string(),
event: self.event(),
..Default::default()
}
}
}
#[derive(
Clone, Debug, Default, Deserialize, HasId, HasDescription, HasNote, HasRelatedParty, Serialize,
)]
#[serde(rename_all = "camelCase")]
pub struct ProductOrder {
#[serde(skip_serializing_if = "Option::is_none")]
id: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
href: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub cancellation_date: Option<DateTime>,
#[serde(skip_serializing_if = "Option::is_none")]
pub cancellation_reason: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub category: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub completion_date: Option<DateTime>,
#[serde(skip_serializing_if = "Option::is_none")]
pub description: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub expected_completion_date: Option<DateTime>,
#[serde(skip_serializing_if = "Option::is_none")]
pub external_id: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub order_date: Option<DateTime>,
#[serde(skip_serializing_if = "Option::is_none")]
pub product_order_item: Option<Vec<ProductOrderItem>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub related_party: Option<Vec<RelatedParty>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub note: Option<Vec<Note>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub agreement: Option<Vec<AgreementRef>>,
}
impl HasLastUpdate for ProductOrder {
fn set_last_update(&mut self, time: impl Into<String>) {
self.order_date = Some(time.into());
}
fn get_last_update(&self) -> Option<String> {
self.order_date.clone()
}
fn last_update(mut self, time: Option<String>) -> Self {
match time {
Some(t) => self.set_last_update(t),
None => self.set_last_update(ProductOrder::get_timestamp()),
};
self
}
}
impl ProductOrder {
pub fn new() -> ProductOrder {
ProductOrder {
..ProductOrder::create_with_time()
}
}
pub fn add_order_item(&mut self, order_item: ProductOrderItem) {
vec_insert(&mut self.product_order_item, order_item);
}
}
impl From<ServiceOrder> for ProductOrder {
fn from(value: ServiceOrder) -> Self {
let mut po = ProductOrder::new();
po.cancellation_reason
.clone_from(&value.cancellation_reason);
po.category.clone_from(&value.category);
po.description.clone_from(&value.description);
po.external_id.clone_from(&value.external_id);
po.note.clone_from(&value.note);
po.related_party.clone_from(&value.related_party);
po.completion_date.clone_from(&value.completion_date);
po.order_date.clone_from(&value.order_date);
po.cancellation_date.clone_from(&value.cancellation_date);
po.expected_completion_date
.clone_from(&value.expected_completion_date);
let items = match value.service_order_item {
Some(i) => {
let mut out = vec![];
i.into_iter().for_each(|i| {
let poi = ProductOrderItem::from(i);
out.push(poi);
});
Some(out)
}
None => None,
};
po.product_order_item = items;
po
}
}
impl From<ShoppingCart> for ProductOrder {
fn from(value: ShoppingCart) -> Self {
let mut order = ProductOrder::new();
order.description = Some("Order from Cart".into());
if value.cart_item.is_some() {
value.cart_item.unwrap().into_iter().for_each(|i| {
order
.product_order_item
.as_mut()
.unwrap()
.push(ProductOrderItem::from(i));
});
}
if value.related_party.is_some() {
value.related_party.unwrap().into_iter().for_each(|rp| {
order.add_party(rp);
});
}
order
}
}
#[cfg(test)]
mod test {
use super::*;
use crate::tmf641::service_order::ServiceOrder;
use crate::tmf663::shopping_cart::ShoppingCart;
const SERVICE_CAT: &str = "ServiceCategory";
#[test]
fn test_orderref_from_order() {
let order = ProductOrder::new();
let order_ref = ProductOrderRef::from(order.clone());
assert_eq!(order.get_id(), order_ref.id);
assert_eq!(order.get_href(), order_ref.href);
}
#[test]
fn test_orderref_from_order_ref() {
let order = ProductOrder::new();
let order_ref = ProductOrderRef::from(&order);
assert_eq!(order.get_id(), order_ref.id);
assert_eq!(order.get_href(), order_ref.href);
}
#[test]
fn test_prodorder_from_serviceorder() {
let mut service_order = ServiceOrder::new();
service_order.category = Some(SERVICE_CAT.to_string());
let product_order = ProductOrder::from(service_order.clone());
assert_eq!(product_order.category, service_order.category);
}
#[test]
fn test_productorder_from_shoppingcart() {
let cart = ShoppingCart::new();
let order = ProductOrder::from(cart.clone());
assert_eq!(order.description.is_some(), true);
assert_eq!(order.related_party.is_none(), true);
assert_eq!(order.product_order_item.is_none(), true);
}
}