use serde::{Deserialize, Serialize};
use crate::rest::{ResourceOperation, ResourcePath, RestResource};
use crate::HttpMethod;
use super::Province;
#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq)]
pub struct Country {
#[serde(skip_serializing)]
pub id: Option<u64>,
#[serde(skip_serializing)]
pub name: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub code: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub tax: Option<String>,
#[serde(skip_serializing)]
pub provinces: Option<Vec<Province>>,
}
impl RestResource for Country {
type Id = u64;
type FindParams = CountryFindParams;
type AllParams = CountryListParams;
type CountParams = CountryCountParams;
const NAME: &'static str = "Country";
const PLURAL: &'static str = "countries";
const PATHS: &'static [ResourcePath] = &[
ResourcePath::new(
HttpMethod::Get,
ResourceOperation::Find,
&["id"],
"countries/{id}",
),
ResourcePath::new(HttpMethod::Get, ResourceOperation::All, &[], "countries"),
ResourcePath::new(
HttpMethod::Get,
ResourceOperation::Count,
&[],
"countries/count",
),
ResourcePath::new(
HttpMethod::Post,
ResourceOperation::Create,
&[],
"countries",
),
ResourcePath::new(
HttpMethod::Put,
ResourceOperation::Update,
&["id"],
"countries/{id}",
),
ResourcePath::new(
HttpMethod::Delete,
ResourceOperation::Delete,
&["id"],
"countries/{id}",
),
];
fn get_id(&self) -> Option<Self::Id> {
self.id
}
}
#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq, Eq)]
pub struct CountryFindParams {
#[serde(skip_serializing_if = "Option::is_none")]
pub fields: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq, Eq)]
pub struct CountryListParams {
#[serde(skip_serializing_if = "Option::is_none")]
pub since_id: Option<u64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub fields: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq, Eq)]
pub struct CountryCountParams {}
#[cfg(test)]
mod tests {
use super::*;
use crate::rest::{get_path, ResourceOperation};
#[test]
fn test_country_serialization() {
let country = Country {
id: Some(879921427),
name: Some("Canada".to_string()),
code: Some("CA".to_string()),
tax: Some("0.05".to_string()),
provinces: Some(vec![]),
};
let json = serde_json::to_string(&country).unwrap();
let parsed: serde_json::Value = serde_json::from_str(&json).unwrap();
assert_eq!(parsed["code"], "CA");
assert_eq!(parsed["tax"], "0.05");
assert!(parsed.get("id").is_none());
assert!(parsed.get("name").is_none());
assert!(parsed.get("provinces").is_none());
}
#[test]
fn test_country_deserialization_with_provinces() {
let json = r#"{
"id": 879921427,
"name": "Canada",
"code": "CA",
"tax": "0.05",
"provinces": [
{
"id": 224293623,
"country_id": 879921427,
"name": "Ontario",
"code": "ON",
"tax": 0.08,
"tax_name": "HST",
"tax_type": "compounded",
"tax_percentage": 8.0
},
{
"id": 702530425,
"country_id": 879921427,
"name": "Quebec",
"code": "QC",
"tax": 0.0975,
"tax_name": "QST",
"tax_type": "compounded",
"tax_percentage": 9.75
}
]
}"#;
let country: Country = serde_json::from_str(json).unwrap();
assert_eq!(country.id, Some(879921427));
assert_eq!(country.name, Some("Canada".to_string()));
assert_eq!(country.code, Some("CA".to_string()));
assert_eq!(country.tax, Some("0.05".to_string()));
assert!(country.provinces.is_some());
let provinces = country.provinces.unwrap();
assert_eq!(provinces.len(), 2);
assert_eq!(provinces[0].name, Some("Ontario".to_string()));
assert_eq!(provinces[1].name, Some("Quebec".to_string()));
}
#[test]
fn test_country_full_crud_paths() {
let find_path = get_path(Country::PATHS, ResourceOperation::Find, &["id"]);
assert!(find_path.is_some());
assert_eq!(find_path.unwrap().template, "countries/{id}");
let all_path = get_path(Country::PATHS, ResourceOperation::All, &[]);
assert!(all_path.is_some());
assert_eq!(all_path.unwrap().template, "countries");
let count_path = get_path(Country::PATHS, ResourceOperation::Count, &[]);
assert!(count_path.is_some());
assert_eq!(count_path.unwrap().template, "countries/count");
let create_path = get_path(Country::PATHS, ResourceOperation::Create, &[]);
assert!(create_path.is_some());
assert_eq!(create_path.unwrap().template, "countries");
let update_path = get_path(Country::PATHS, ResourceOperation::Update, &["id"]);
assert!(update_path.is_some());
assert_eq!(update_path.unwrap().template, "countries/{id}");
let delete_path = get_path(Country::PATHS, ResourceOperation::Delete, &["id"]);
assert!(delete_path.is_some());
assert_eq!(delete_path.unwrap().template, "countries/{id}");
}
#[test]
fn test_country_constants() {
assert_eq!(Country::NAME, "Country");
assert_eq!(Country::PLURAL, "countries");
}
#[test]
fn test_country_get_id() {
let country_with_id = Country {
id: Some(879921427),
code: Some("CA".to_string()),
..Default::default()
};
assert_eq!(country_with_id.get_id(), Some(879921427));
let country_without_id = Country::default();
assert_eq!(country_without_id.get_id(), None);
}
}