use async_trait::async_trait;
use reqwest::Method;
use serde::{Deserialize, Serialize};
use smbcloud_ascapi_core::jsonapi::{Document, Resource, UpdateBody, UpdateData};
use smbcloud_ascapi_core::Client;
use smbcloud_ascapi_core::Result;
pub const RESOURCE_TYPE: &str = "betaAppReviewDetails";
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct BetaAppReviewDetailAttributes {
pub contact_email: Option<String>,
pub contact_first_name: Option<String>,
pub contact_last_name: Option<String>,
pub contact_phone: Option<String>,
pub demo_account_name: Option<String>,
pub demo_account_password: Option<String>,
pub demo_account_required: Option<bool>,
pub notes: Option<String>,
}
pub type BetaAppReviewDetail = Resource<BetaAppReviewDetailAttributes>;
#[derive(Debug, Clone, Default, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct BetaAppReviewDetailUpdate {
#[serde(skip_serializing_if = "Option::is_none")]
pub contact_email: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub contact_first_name: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub contact_last_name: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub contact_phone: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub demo_account_name: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub demo_account_password: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub demo_account_required: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
pub notes: Option<String>,
}
#[async_trait]
pub trait BetaAppReviewDetailApi {
async fn get_beta_app_review_detail(&self, app_id: &str) -> Result<BetaAppReviewDetail>;
async fn update_beta_app_review_detail(
&self,
id: &str,
update: BetaAppReviewDetailUpdate,
) -> Result<BetaAppReviewDetail>;
}
#[async_trait]
impl BetaAppReviewDetailApi for Client {
async fn get_beta_app_review_detail(&self, app_id: &str) -> Result<BetaAppReviewDetail> {
let path = format!("/v1/apps/{app_id}/betaAppReviewDetail");
let doc: Document<BetaAppReviewDetailAttributes> =
self.request(Method::GET, &path, &[], None::<&()>).await?;
Ok(doc.data)
}
async fn update_beta_app_review_detail(
&self,
id: &str,
update: BetaAppReviewDetailUpdate,
) -> Result<BetaAppReviewDetail> {
let path = format!("/v1/betaAppReviewDetails/{id}");
let body = UpdateBody {
data: UpdateData {
resource_type: RESOURCE_TYPE,
id: id.to_string(),
attributes: update,
},
};
let doc: Document<BetaAppReviewDetailAttributes> =
self.request(Method::PATCH, &path, &[], Some(&body)).await?;
Ok(doc.data)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn deserializes_a_beta_app_review_detail() {
let body = serde_json::json!({
"data": {
"id": "DETAIL1",
"type": "betaAppReviewDetails",
"attributes": {
"contactEmail": "dev@example.com",
"contactFirstName": "Jane",
"contactLastName": "Developer",
"contactPhone": "+1-555-0100",
"demoAccountName": "demo@example.com",
"demoAccountPassword": "hunter2",
"demoAccountRequired": true,
"notes": "Tap the red button to reach the main feature."
}
}
});
let doc: Document<BetaAppReviewDetailAttributes> =
serde_json::from_value(body).expect("review detail must deserialize");
let attrs = &doc.data.attributes;
assert_eq!(doc.data.id, "DETAIL1");
assert_eq!(attrs.contact_email.as_deref(), Some("dev@example.com"));
assert_eq!(attrs.contact_first_name.as_deref(), Some("Jane"));
assert_eq!(attrs.demo_account_required, Some(true));
assert_eq!(
attrs.notes.as_deref(),
Some("Tap the red button to reach the main feature.")
);
}
#[test]
fn update_body_skips_none_fields() {
let update = BetaAppReviewDetailUpdate {
contact_email: Some("new@example.com".into()),
notes: Some("Updated notes.".into()),
..Default::default()
};
let body = UpdateBody {
data: UpdateData {
resource_type: RESOURCE_TYPE,
id: "DETAIL1".into(),
attributes: update,
},
};
let v = serde_json::to_value(&body).unwrap();
let attrs = &v["data"]["attributes"];
assert_eq!(attrs["contactEmail"], "new@example.com");
assert_eq!(attrs["notes"], "Updated notes.");
assert!(attrs.get("contactFirstName").is_none() || attrs["contactFirstName"].is_null());
assert!(attrs.get("demoAccountRequired").is_none());
}
}