@prefix : <https://ontology.inferal.com/modules/advertising-budget/> .
@prefix adm: <https://ontology.inferal.com/modules/advertising-measurement/> .
@prefix ex: <https://example.com/advertising-budget/> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
@prefix rng: <https://ontology.inferal.com/modules/range/> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .

# Worked instances for the Advertising Budget module.
#
# Four scenarios:
#   A. The same daily allowance from two providers whose wire encodings differ,
#      comparable because period, pacing, and scope all agree.
#   B. A lifetime allowance that must not be compared with the daily ones.
#   C. A shared budget covering several ad groups, under which per-entity spend
#      cannot be attributed.
#   D. A spend cap, which is a ceiling rather than a target.


# --- Scenario A: comparable daily budgets ------------------------------------
#
# One provider sends a minor-unit string, the other a micros integer. Both lower
# to a decimal in major units, so the figures are directly comparable.

ex:meta-campaign-scope
    a :BudgetScope ;
    rdfs:label "scope of one Meta campaign" ;
    :coversEntity ex:meta-campaign-1 ;
    :sharedAcrossEntities false .

ex:meta-daily-budget
    a :Budget ;
    rdfs:label "Meta campaign daily budget" ;
    :budgetAmount ex:meta-daily-amount ;
    :budgetPeriod :dailyPeriod ;
    :budgetDeliveryMethod :standardDelivery ;
    :appliesToScope ex:meta-campaign-scope .

ex:meta-daily-amount
    a adm:MonetaryAmount ;
    rdfs:comment "Wire form was the string 50000 in minor units." ;
    adm:amountValue "500.00"^^xsd:decimal ;
    adm:currencyCode "USD" .

ex:googleads-campaign-scope
    a :BudgetScope ;
    rdfs:label "scope of one Google Ads campaign" ;
    :coversEntity ex:googleads-campaign-1 ;
    :sharedAcrossEntities false .

ex:googleads-daily-budget
    a :Budget ;
    rdfs:label "Google Ads campaign daily budget" ;
    :budgetAmount ex:googleads-daily-amount ;
    :budgetPeriod :dailyPeriod ;
    :budgetDeliveryMethod :standardDelivery ;
    :appliesToScope ex:googleads-campaign-scope .

ex:googleads-daily-amount
    a adm:MonetaryAmount ;
    rdfs:comment "Wire form was the integer 750000000 in micros." ;
    adm:amountValue "750.00"^^xsd:decimal ;
    adm:currencyCode "USD" .


# --- Scenario B: a lifetime allowance ----------------------------------------
#
# The same shape and currency as the daily budgets above, and not comparable
# with them. Nothing but the period distinguishes the two, which is why the
# period has to be stated rather than encoded in a field name.

ex:linkedin-campaigngroup-scope
    a :BudgetScope ;
    rdfs:label "scope of one LinkedIn campaign group" ;
    :coversEntity ex:linkedin-campaigngroup-1 ;
    :sharedAcrossEntities false .

ex:linkedin-lifetime-budget
    a :Budget ;
    rdfs:label "LinkedIn campaign group lifetime budget" ;
    :budgetAmount ex:linkedin-lifetime-amount ;
    :budgetPeriod :lifetimePeriod ;
    :budgetDeliveryMethod :standardDelivery ;
    :appliesToScope ex:linkedin-campaigngroup-scope ;
    :effectiveWindow ex:flight-window .

ex:linkedin-lifetime-amount
    a adm:MonetaryAmount ;
    rdfs:comment "Wire form was a decimal string inside a money object carrying its own currency code." ;
    adm:amountValue "12000.00"^^xsd:decimal ;
    adm:currencyCode "USD" .

ex:flight-window
    a rng:Range ;
    rdfs:label "the flight this lifetime allowance spans" ;
    rng:lowerInclusive true ;
    rng:upperInclusive false .


# --- Scenario C: a shared budget ---------------------------------------------
#
# One allowance pooled across three ad groups. Spend under it cannot be divided
# among them, so any per-ad-group cost or return figure derived from this budget
# is unattributable. Two providers expose this as a boolean and as a reference
# count respectively, and neither reaches the shared vocabulary today.

ex:pooled-scope
    a :BudgetScope ;
    rdfs:label "one allowance pooled across three ad groups" ;
    rdfs:comment "Shared. Per-entity attribution of spend under this budget is not possible." ;
    :coversEntity ex:meta-adgroup-a , ex:meta-adgroup-b , ex:meta-adgroup-c ;
    :sharedAcrossEntities true .

ex:shared-daily-budget
    a :Budget ;
    rdfs:label "Meta campaign budget shared across its ad groups" ;
    :budgetAmount ex:shared-daily-amount ;
    :budgetPeriod :dailyPeriod ;
    :budgetDeliveryMethod :acceleratedDelivery ;
    :appliesToScope ex:pooled-scope .

ex:shared-daily-amount
    a adm:MonetaryAmount ;
    adm:amountValue "2000.00"^^xsd:decimal ;
    adm:currencyCode "USD" .


# --- Scenario D: a spend cap -------------------------------------------------
#
# Identical on the wire to a lifetime budget: one amount, one period, one owner.
# It is not a budget. Pacing does not spend toward it, so an account sitting well
# under its cap is not underspending.

ex:account-scope
    a :BudgetScope ;
    rdfs:label "scope of one advertiser account" ;
    :coversEntity ex:meta-account-1 ;
    :sharedAcrossEntities false .

ex:account-spend-cap
    a :SpendCap ;
    rdfs:label "advertiser account lifetime spend cap" ;
    :capAmount ex:account-cap-amount ;
    :capPeriod :lifetimePeriod ;
    :constrainsScope ex:account-scope .

ex:account-cap-amount
    a adm:MonetaryAmount ;
    adm:amountValue "50000.00"^^xsd:decimal ;
    adm:currencyCode "USD" .
