use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use crate::rest::{ResourceOperation, ResourcePath, RestResource};
use crate::HttpMethod;
#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq, Eq)]
pub struct CountryHarmonizedSystemCode {
#[serde(skip_serializing_if = "Option::is_none")]
pub harmonized_system_code: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub country_code: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq, Eq)]
pub struct InventoryItem {
#[serde(skip_serializing)]
pub id: Option<u64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub sku: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub cost: Option<String>,
#[serde(skip_serializing)]
pub created_at: Option<DateTime<Utc>>,
#[serde(skip_serializing)]
pub updated_at: Option<DateTime<Utc>>,
#[serde(skip_serializing)]
pub requires_shipping: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
pub tracked: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
pub country_code_of_origin: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub province_code_of_origin: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub harmonized_system_code: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub country_harmonized_system_codes: Option<Vec<CountryHarmonizedSystemCode>>,
#[serde(skip_serializing)]
pub admin_graphql_api_id: Option<String>,
}
impl RestResource for InventoryItem {
type Id = u64;
type FindParams = InventoryItemFindParams;
type AllParams = InventoryItemListParams;
type CountParams = ();
const NAME: &'static str = "InventoryItem";
const PLURAL: &'static str = "inventory_items";
const PATHS: &'static [ResourcePath] = &[
ResourcePath::new(
HttpMethod::Get,
ResourceOperation::Find,
&["id"],
"inventory_items/{id}",
),
ResourcePath::new(
HttpMethod::Get,
ResourceOperation::All,
&[],
"inventory_items",
),
ResourcePath::new(
HttpMethod::Put,
ResourceOperation::Update,
&["id"],
"inventory_items/{id}",
),
];
fn get_id(&self) -> Option<Self::Id> {
self.id
}
}
#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq, Eq)]
pub struct InventoryItemFindParams {
}
#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq, Eq)]
pub struct InventoryItemListParams {
#[serde(skip_serializing_if = "Option::is_none")]
pub ids: Option<Vec<u64>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub limit: Option<u32>,
#[serde(skip_serializing_if = "Option::is_none")]
pub page_info: Option<String>,
}
#[cfg(test)]
mod tests {
use super::*;
use crate::rest::{get_path, ResourceOperation};
#[test]
fn test_inventory_item_struct_serialization() {
let item = InventoryItem {
id: Some(12345), sku: Some("SKU-001".to_string()),
cost: Some("15.99".to_string()),
created_at: Some(
DateTime::parse_from_rfc3339("2024-01-15T10:30:00Z")
.unwrap()
.with_timezone(&Utc),
), updated_at: Some(
DateTime::parse_from_rfc3339("2024-06-20T15:45:00Z")
.unwrap()
.with_timezone(&Utc),
), requires_shipping: Some(true), tracked: Some(true),
country_code_of_origin: Some("US".to_string()),
province_code_of_origin: Some("CA".to_string()),
harmonized_system_code: Some("6109.10".to_string()),
country_harmonized_system_codes: Some(vec![CountryHarmonizedSystemCode {
harmonized_system_code: Some("6109.10.0000".to_string()),
country_code: Some("CA".to_string()),
}]),
admin_graphql_api_id: Some("gid://shopify/InventoryItem/12345".to_string()), };
let json = serde_json::to_string(&item).unwrap();
let parsed: serde_json::Value = serde_json::from_str(&json).unwrap();
assert_eq!(parsed["sku"], "SKU-001");
assert_eq!(parsed["cost"], "15.99");
assert_eq!(parsed["tracked"], true);
assert_eq!(parsed["country_code_of_origin"], "US");
assert_eq!(parsed["province_code_of_origin"], "CA");
assert_eq!(parsed["harmonized_system_code"], "6109.10");
assert!(parsed.get("id").is_none());
assert!(parsed.get("created_at").is_none());
assert!(parsed.get("updated_at").is_none());
assert!(parsed.get("requires_shipping").is_none());
assert!(parsed.get("admin_graphql_api_id").is_none());
let codes = parsed["country_harmonized_system_codes"]
.as_array()
.unwrap();
assert_eq!(codes.len(), 1);
assert_eq!(codes[0]["harmonized_system_code"], "6109.10.0000");
assert_eq!(codes[0]["country_code"], "CA");
}
#[test]
fn test_inventory_item_deserialization() {
let json = r#"{
"id": 808950810,
"sku": "IPOD-342-N",
"cost": "25.00",
"created_at": "2024-01-15T10:30:00Z",
"updated_at": "2024-06-20T15:45:00Z",
"requires_shipping": true,
"tracked": true,
"country_code_of_origin": "US",
"province_code_of_origin": "CA",
"harmonized_system_code": "8523.29.90",
"country_harmonized_system_codes": [
{
"harmonized_system_code": "8523.29.9000",
"country_code": "CA"
},
{
"harmonized_system_code": "8523.29.9090",
"country_code": "GB"
}
],
"admin_graphql_api_id": "gid://shopify/InventoryItem/808950810"
}"#;
let item: InventoryItem = serde_json::from_str(json).unwrap();
assert_eq!(item.id, Some(808950810));
assert_eq!(item.sku, Some("IPOD-342-N".to_string()));
assert_eq!(item.cost, Some("25.00".to_string()));
assert!(item.created_at.is_some());
assert!(item.updated_at.is_some());
assert_eq!(item.requires_shipping, Some(true));
assert_eq!(item.tracked, Some(true));
assert_eq!(item.country_code_of_origin, Some("US".to_string()));
assert_eq!(item.province_code_of_origin, Some("CA".to_string()));
assert_eq!(item.harmonized_system_code, Some("8523.29.90".to_string()));
assert_eq!(
item.admin_graphql_api_id,
Some("gid://shopify/InventoryItem/808950810".to_string())
);
let codes = item.country_harmonized_system_codes.unwrap();
assert_eq!(codes.len(), 2);
assert_eq!(
codes[0].harmonized_system_code,
Some("8523.29.9000".to_string())
);
assert_eq!(codes[0].country_code, Some("CA".to_string()));
assert_eq!(
codes[1].harmonized_system_code,
Some("8523.29.9090".to_string())
);
assert_eq!(codes[1].country_code, Some("GB".to_string()));
}
#[test]
fn test_inventory_item_list_params_with_ids() {
let params = InventoryItemListParams {
ids: Some(vec![808950810, 808950811, 808950812]),
limit: Some(50),
page_info: None,
};
let json = serde_json::to_value(¶ms).unwrap();
assert_eq!(
json["ids"],
serde_json::json!([808950810, 808950811, 808950812])
);
assert_eq!(json["limit"], 50);
assert!(json.get("page_info").is_none());
let empty_params = InventoryItemListParams::default();
let empty_json = serde_json::to_value(&empty_params).unwrap();
assert_eq!(empty_json, serde_json::json!({}));
}
#[test]
fn test_inventory_item_get_id_returns_correct_value() {
let item_with_id = InventoryItem {
id: Some(808950810),
sku: Some("TEST-SKU".to_string()),
..Default::default()
};
assert_eq!(item_with_id.get_id(), Some(808950810));
let item_without_id = InventoryItem {
id: None,
sku: Some("NEW-SKU".to_string()),
..Default::default()
};
assert_eq!(item_without_id.get_id(), None);
assert_eq!(InventoryItem::NAME, "InventoryItem");
assert_eq!(InventoryItem::PLURAL, "inventory_items");
}
#[test]
fn test_inventory_item_path_constants_are_correct() {
let find_path = get_path(InventoryItem::PATHS, ResourceOperation::Find, &["id"]);
assert!(find_path.is_some());
assert_eq!(find_path.unwrap().template, "inventory_items/{id}");
assert_eq!(find_path.unwrap().http_method, HttpMethod::Get);
let all_path = get_path(InventoryItem::PATHS, ResourceOperation::All, &[]);
assert!(all_path.is_some());
assert_eq!(all_path.unwrap().template, "inventory_items");
assert_eq!(all_path.unwrap().http_method, HttpMethod::Get);
let update_path = get_path(InventoryItem::PATHS, ResourceOperation::Update, &["id"]);
assert!(update_path.is_some());
assert_eq!(update_path.unwrap().template, "inventory_items/{id}");
assert_eq!(update_path.unwrap().http_method, HttpMethod::Put);
let create_path = get_path(InventoryItem::PATHS, ResourceOperation::Create, &[]);
assert!(create_path.is_none());
let delete_path = get_path(InventoryItem::PATHS, ResourceOperation::Delete, &["id"]);
assert!(delete_path.is_none());
let count_path = get_path(InventoryItem::PATHS, ResourceOperation::Count, &[]);
assert!(count_path.is_none());
}
#[test]
fn test_country_harmonized_system_code_struct() {
let code = CountryHarmonizedSystemCode {
harmonized_system_code: Some("8523.29.9000".to_string()),
country_code: Some("CA".to_string()),
};
let json = serde_json::to_value(&code).unwrap();
assert_eq!(json["harmonized_system_code"], "8523.29.9000");
assert_eq!(json["country_code"], "CA");
let json_str = r#"{"harmonized_system_code": "1234.56.7890", "country_code": "US"}"#;
let parsed: CountryHarmonizedSystemCode = serde_json::from_str(json_str).unwrap();
assert_eq!(
parsed.harmonized_system_code,
Some("1234.56.7890".to_string())
);
assert_eq!(parsed.country_code, Some("US".to_string()));
let empty_code = CountryHarmonizedSystemCode::default();
let empty_json = serde_json::to_value(&empty_code).unwrap();
assert_eq!(empty_json, serde_json::json!({}));
}
}