late 0.0.1291

API reference for Zernio. Authenticate with a Bearer API key. Base URL: https://zernio.com/api Versioning and deprecation: all endpoints are versioned in the URL path (current version: /v1). Breaking changes only ship in a new path version; existing versions keep working. Deprecated operations are marked 'deprecated: true' in this spec and announced in the changelog (https://zernio.com/changelog) before removal. Errors: every 4xx/5xx response is application/json with a machine-readable 'code' and a human-readable 'error' message (see the ErrorResponse schema). Request ids: responses carry an X-Request-Id header with the id we log the request under. Quote it when reporting a problem. A valid x-request-id you send is reused as that id.
Documentation
/*
 * Zernio API
 *
 * API reference for Zernio. Authenticate with a Bearer API key. Base URL: https://zernio.com/api  Versioning and deprecation: all endpoints are versioned in the URL path (current version: /v1). Breaking changes only ship in a new path version; existing versions keep working. Deprecated operations are marked 'deprecated: true' in this spec and announced in the changelog (https://zernio.com/changelog) before removal.  Errors: every 4xx/5xx response is application/json with a machine-readable 'code' and a human-readable 'error' message (see the ErrorResponse schema).  Request ids: responses carry an X-Request-Id header with the id we log the request under. Quote it when reporting a problem. A valid x-request-id you send is reused as that id.
 *
 * The version of the OpenAPI document: 1.416.0
 * Contact: support@zernio.com
 * Generated by: https://openapi-generator.tech
 */

use crate::models;
use serde::{Deserialize, Serialize};

/// AdTreeCampaign : Campaign with nested ad sets and rolled-up metrics
#[derive(Clone, Default, Debug, PartialEq, Serialize, Deserialize)]
pub struct AdTreeCampaign {
    #[serde(rename = "platformCampaignId", skip_serializing_if = "Option::is_none")]
    pub platform_campaign_id: Option<String>,
    #[serde(rename = "platform", skip_serializing_if = "Option::is_none")]
    pub platform: Option<Platform>,
    #[serde(rename = "campaignName", skip_serializing_if = "Option::is_none")]
    pub campaign_name: Option<String>,
    /// Earliest `platformCreatedAt` across every ad in the campaign (platform ad creation time; falls back to `createdAt`, Zernio's sync time, for ads synced before that field existed).  Not the platform campaign's own creation time (Meta's `Campaign.created_time` etc. is not synced). A campaign created empty and populated later shows its first ad's time, not the campaign's.  Usable for sorting \"most recently created\" without the numeric-campaign-id heuristic. Same source as `AdTreeAdSet.createdTime` and `Ad.platformCreatedAt`; mirrors `AdCampaign.earliestAd`.
    #[serde(
        rename = "createdTime",
        default,
        with = "::serde_with::rust::double_option",
        skip_serializing_if = "Option::is_none"
    )]
    pub created_time: Option<Option<String>>,
    /// Delivery status derived from child ad statuses. Distinct from `reviewStatus`, which reflects the platform-side review state.
    #[serde(rename = "status", skip_serializing_if = "Option::is_none")]
    pub status: Option<models::AdStatus>,
    #[serde(
        rename = "reviewStatus",
        default,
        with = "::serde_with::rust::double_option",
        skip_serializing_if = "Option::is_none"
    )]
    pub review_status: Option<Option<models::AdReviewStatus>>,
    /// Raw platform-level campaign status (Meta `effective_status`: ACTIVE, PAUSED, DELETED, ARCHIVED, IN_PROCESS, WITH_ISSUES; ChatGPT (OpenAI): the campaign's own switch, active / paused / archived, independent of the delivery `status`; TikTok: the campaign's own switch `operation_status`, ENABLE / DISABLE; Reddit: the campaign's `configured_status`, ACTIVE / PAUSED / ARCHIVED). Distinct from per-ad `platformStatus`.
    #[serde(
        rename = "platformCampaignStatus",
        default,
        with = "::serde_with::rust::double_option",
        skip_serializing_if = "Option::is_none"
    )]
    pub platform_campaign_status: Option<Option<String>>,
    /// Platform-reported campaign issues (Meta `issues_info[]`). Populated only when the platform has delivery issues to report; contains the specific error codes and messages.
    #[serde(
        rename = "campaignIssuesInfo",
        default,
        with = "::serde_with::rust::double_option",
        skip_serializing_if = "Option::is_none"
    )]
    pub campaign_issues_info: Option<Option<Vec<serde_json::Value>>>,
    /// Total ads across all ad sets
    #[serde(rename = "adCount", skip_serializing_if = "Option::is_none")]
    pub ad_count: Option<i32>,
    #[serde(rename = "adSetCount", skip_serializing_if = "Option::is_none")]
    pub ad_set_count: Option<i32>,
    #[serde(rename = "budget", skip_serializing_if = "Option::is_none")]
    pub budget: Option<Box<models::AdTreeCampaignBudget>>,
    #[serde(rename = "campaignBudget", skip_serializing_if = "Option::is_none")]
    pub campaign_budget: Option<Box<models::AdTreeCampaignCampaignBudget>>,
    /// Canonical CBO/ABO indicator. `campaign` = CBO (Advantage Campaign Budget, budget lives on the campaign). `adset` = ABO (budget lives on each ad set). Route budget updates to the matching Meta entity.
    #[serde(
        rename = "budgetLevel",
        default,
        with = "::serde_with::rust::double_option",
        skip_serializing_if = "Option::is_none"
    )]
    pub budget_level: Option<Option<BudgetLevel>>,
    /// Meta-only. Mirrors Campaign.is_budget_schedule_enabled: true when the campaign uses budget scheduling (time-based budget changes). Independent of CBO/ABO.
    #[serde(
        rename = "isBudgetScheduleEnabled",
        skip_serializing_if = "Option::is_none"
    )]
    pub is_budget_schedule_enabled: Option<bool>,
    /// ISO 4217 currency code (e.g. USD, EUR, CLP, JPY) for all budget amounts in this campaign node. Budgets are NOT normalized to USD.
    #[serde(
        rename = "currency",
        default,
        with = "::serde_with::rust::double_option",
        skip_serializing_if = "Option::is_none"
    )]
    pub currency: Option<Option<String>>,
    #[serde(rename = "metrics", skip_serializing_if = "Option::is_none")]
    pub metrics: Option<Box<models::AdMetrics>>,
    /// Only with `compare=previous`. The same metrics over `previousRange`.
    #[serde(rename = "previousMetrics", skip_serializing_if = "Option::is_none")]
    pub previous_metrics: Option<Box<models::AdMetrics>>,
    #[serde(
        rename = "platformAdAccountId",
        skip_serializing_if = "Option::is_none"
    )]
    pub platform_ad_account_id: Option<String>,
    /// Human-readable advertiser/account name from the platform. Refreshed on every sync.
    #[serde(
        rename = "platformAdAccountName",
        default,
        with = "::serde_with::rust::double_option",
        skip_serializing_if = "Option::is_none"
    )]
    pub platform_ad_account_name: Option<Option<String>>,
    #[serde(rename = "accountId", skip_serializing_if = "Option::is_none")]
    pub account_id: Option<String>,
    /// Profile the row belongs to: the profile of its owning connection (`accountId`); when that connection no longer exists, the requested profile (`profileId` filter) that reaches the row ad account, else the profile of the oldest connection of the row owner that reaches it.
    #[serde(rename = "profileId", skip_serializing_if = "Option::is_none")]
    pub profile_id: Option<String>,
    /// TikTok only. true when the campaign is an Upgraded Smart+ campaign (TikTok lists it on /smart_plus/campaign/get/), false when it is not.  Set by ads sync, so the key is absent on other platforms and on TikTok campaigns not synced since this field shipped.  On Smart+ objects Zernio can pause, resume, rename, delete and change the budget of the campaign and ad set, and pause or resume an ad. Other edits answer 422 and belong in TikTok Ads Manager.
    #[serde(rename = "isSmartPlus", skip_serializing_if = "Option::is_none")]
    pub is_smart_plus: Option<bool>,
    /// Google-only. Raw campaign.advertising_channel_type (SEARCH, PERFORMANCE_MAX, LOCAL_SERVICES, VIDEO, DEMAND_GEN, DISPLAY, SHOPPING, ...). Serving surface, distinct from platformObjective (advertiser intent). Null/absent for non-Google platforms.
    #[serde(
        rename = "advertisingChannelType",
        default,
        with = "::serde_with::rust::double_option",
        skip_serializing_if = "Option::is_none"
    )]
    pub advertising_channel_type: Option<Option<String>>,
    /// Raw Meta campaign objective (e.g. OUTCOME_SALES, OUTCOME_LEADS, OUTCOME_TRAFFIC)
    #[serde(
        rename = "platformObjective",
        default,
        with = "::serde_with::rust::double_option",
        skip_serializing_if = "Option::is_none"
    )]
    pub platform_objective: Option<Option<String>>,
    #[serde(rename = "optimizationGoal", skip_serializing_if = "Option::is_none")]
    pub optimization_goal: Option<Box<models::AdTreeCampaignOptimizationGoal>>,
    #[serde(
        rename = "bidStrategy",
        default,
        with = "::serde_with::rust::double_option",
        skip_serializing_if = "Option::is_none"
    )]
    pub bid_strategy: Option<Option<models::BidStrategy>>,
    /// Representative bid for the campaign, bubbled up from the top-spending ad set (whole currency units). Meta: populated when the ad-set bidStrategy is LOWEST_COST_WITH_BID_CAP or COST_CAP. LinkedIn: the campaign unitCost, which has no bidStrategy gate and where 0 is a real, delivery-stopping value rather than unset.
    #[serde(
        rename = "bidAmount",
        default,
        with = "::serde_with::rust::double_option",
        skip_serializing_if = "Option::is_none"
    )]
    pub bid_amount: Option<Option<f64>>,
    /// Representative ROAS floor for the campaign, bubbled up from the top-spending ad set. Decimal multiplier (2.0 = 2.0x).
    #[serde(
        rename = "roasAverageFloor",
        default,
        with = "::serde_with::rust::double_option",
        skip_serializing_if = "Option::is_none"
    )]
    pub roas_average_floor: Option<Option<f64>>,
    #[serde(rename = "promotedObject", skip_serializing_if = "Option::is_none")]
    pub promoted_object: Option<Box<models::AdTreeCampaignPromotedObject>>,
    #[serde(rename = "adSets", skip_serializing_if = "Option::is_none")]
    pub ad_sets: Option<Vec<models::AdTreeAdSet>>,
    /// Per-day metric series for this campaign. Present only when `GET /v1/ads/tree` is called with `timeIncrement=1` (any `dailyLevel`). This is the per-campaign daily trend. Summing its additive fields reproduces the campaign `metrics` total, except `reach`: on Meta the range total is de-duplicated, so daily reach does not sum to it.
    #[serde(rename = "daily", skip_serializing_if = "Option::is_none")]
    pub daily: Option<Vec<models::AdDailyMetrics>>,
}

impl AdTreeCampaign {
    /// Campaign with nested ad sets and rolled-up metrics
    pub fn new() -> AdTreeCampaign {
        AdTreeCampaign {
            platform_campaign_id: None,
            platform: None,
            campaign_name: None,
            created_time: None,
            status: None,
            review_status: None,
            platform_campaign_status: None,
            campaign_issues_info: None,
            ad_count: None,
            ad_set_count: None,
            budget: None,
            campaign_budget: None,
            budget_level: None,
            is_budget_schedule_enabled: None,
            currency: None,
            metrics: None,
            previous_metrics: None,
            platform_ad_account_id: None,
            platform_ad_account_name: None,
            account_id: None,
            profile_id: None,
            is_smart_plus: None,
            advertising_channel_type: None,
            platform_objective: None,
            optimization_goal: None,
            bid_strategy: None,
            bid_amount: None,
            roas_average_floor: None,
            promoted_object: None,
            ad_sets: None,
            daily: None,
        }
    }
}
///
#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize, Deserialize)]
pub enum Platform {
    #[serde(rename = "facebook")]
    Facebook,
    #[serde(rename = "instagram")]
    Instagram,
    #[serde(rename = "tiktok")]
    Tiktok,
    #[serde(rename = "linkedin")]
    Linkedin,
    #[serde(rename = "pinterest")]
    Pinterest,
    #[serde(rename = "google")]
    Google,
    #[serde(rename = "twitter")]
    Twitter,
    #[serde(rename = "openai")]
    Openai,
    #[serde(rename = "reddit")]
    Reddit,
}

impl Default for Platform {
    fn default() -> Platform {
        Self::Facebook
    }
}
/// Canonical CBO/ABO indicator. `campaign` = CBO (Advantage Campaign Budget, budget lives on the campaign). `adset` = ABO (budget lives on each ad set). Route budget updates to the matching Meta entity.
#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize, Deserialize)]
pub enum BudgetLevel {
    #[serde(rename = "campaign")]
    Campaign,
    #[serde(rename = "adset")]
    Adset,
}

impl Default for BudgetLevel {
    fn default() -> BudgetLevel {
        Self::Campaign
    }
}