// Copyright 2025 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

syntax = "proto3";

package google.shopping.merchant.promotions.v1beta;

import "google/api/field_behavior.proto";
import "google/protobuf/timestamp.proto";
import "google/shopping/type/types.proto";
import "google/type/interval.proto";

option go_package = "cloud.google.com/go/shopping/merchant/promotions/apiv1beta/promotionspb;promotionspb";
option java_multiple_files = true;
option java_outer_classname = "PromotionsCommonProto";
option java_package = "com.google.shopping.merchant.promotions.v1beta";

// Which product or list of products the promotion applies to.
enum ProductApplicability {
  // Which products the promotion applies to is unknown.
  PRODUCT_APPLICABILITY_UNSPECIFIED = 0;

  // Applicable to all products.
  ALL_PRODUCTS = 1;

  // Applicable to only a single product or list of products.
  SPECIFIC_PRODUCTS = 2;
}

// Store codes or list of store codes the promotion applies to. Only for
// Local inventory ads promotions.
enum StoreApplicability {
  // Which store codes the promotion applies to is unknown.
  STORE_APPLICABILITY_UNSPECIFIED = 0;

  // Promotion applies to all stores.
  ALL_STORES = 1;

  // Promotion applies to only the specified stores.
  SPECIFIC_STORES = 2;
}

// Offer type of a promotion.
enum OfferType {
  // Unknown offer type.
  OFFER_TYPE_UNSPECIFIED = 0;

  // Offer type without a code.
  NO_CODE = 1;

  // Offer type with a code. Generic redemption code for the promotion is
  // required when `offerType` = `GENERIC_CODE`.
  GENERIC_CODE = 2;
}

// Channel of a promotion.
enum RedemptionChannel {
  // Indicates that the channel is unspecified.
  REDEMPTION_CHANNEL_UNSPECIFIED = 0;

  // Indicates that the channel is in store.
  // This is same as `local` channel used for `products`.
  IN_STORE = 1;

  // Indicates that the channel is online.
  ONLINE = 2;
}

// [Coupon value
// type](https://support.google.com/merchants/answer/13861986?ref_topic=13773355&sjid=17642868584668136159-NC)
// of a promotion.
enum CouponValueType {
  // Indicates that the coupon value type is unspecified.
  COUPON_VALUE_TYPE_UNSPECIFIED = 0;

  // Money off coupon value type.
  MONEY_OFF = 1;

  // Percent off coupon value type.
  PERCENT_OFF = 2;

  // Buy M quantity, get N money off coupon value type.
  // `minimum_purchase_quantity` and `get_this_quantity_discounted` must be
  // present. `money_off_amount` must also be present.
  BUY_M_GET_N_MONEY_OFF = 3;

  // Buy M quantity, get N percent off coupon value type.
  // `minimum_purchase_quantity` and `get_this_quantity_discounted` must be
  // present. `percent_off_percentage` must also be present.
  BUY_M_GET_N_PERCENT_OFF = 4;

  // Buy M quantity, get money off. `minimum_purchase_quantity` and
  // `money_off_amount` must be present.
  BUY_M_GET_MONEY_OFF = 5;

  // Buy M quantity, get money off. `minimum_purchase_quantity` and
  // `percent_off_percentage` must be present.
  BUY_M_GET_PERCENT_OFF = 6;

  // Free gift with description only.
  FREE_GIFT = 7;

  // Free gift with monetary value.
  FREE_GIFT_WITH_VALUE = 8;

  // Free gift with item ID.
  FREE_GIFT_WITH_ITEM_ID = 9;

  // Standard free shipping coupon value type.
  FREE_SHIPPING_STANDARD = 10;

  // Overnight free shipping coupon value type.
  FREE_SHIPPING_OVERNIGHT = 11;

  // Two day free shipping coupon value type.
  FREE_SHIPPING_TWO_DAY = 12;
}

// Attributes.
message Attributes {
  // Required. Applicability of the promotion to either all products or
  // [only specific
  // products](https://support.google.com/merchants/answer/6396257?ref_topic=6396150&sjid=17642868584668136159-NC).
  ProductApplicability product_applicability = 1
      [(google.api.field_behavior) = REQUIRED];

  // Required.
  // [Type](https://support.google.com/merchants/answer/13837405?ref_topic=13773355&sjid=17642868584668136159-NC)
  // of the promotion. Use this attribute to indicate whether or not customers
  // need a coupon code to redeem your promotion.
  OfferType offer_type = 2 [(google.api.field_behavior) = REQUIRED];

  // Optional. Generic redemption code for the promotion. To be used with the
  // `offerType` field and must meet the [minimum
  // requirements](https://support.google.com/merchants/answer/13837405?ref_topic=13773355&sjid=17642868584668136159-NC).
  string generic_redemption_code = 3 [(google.api.field_behavior) = OPTIONAL];

  // Required. [Long
  // title](https://support.google.com/merchants/answer/13838102?ref_topic=13773355&sjid=17642868584668136159-NC)
  // for the promotion.
  string long_title = 4 [(google.api.field_behavior) = REQUIRED];

  // Required. The [coupon value type]
  // (https://support.google.com/merchants/answer/13861986?ref_topic=13773355&sjid=17642868584668136159-NC)
  // attribute to signal the type of promotion that you are running. Depending
  // on type of the selected coupon value [some attributes are
  // required](https://support.google.com/merchants/answer/6393006?ref_topic=7322920).
  CouponValueType coupon_value_type = 5
      [(google.api.field_behavior) = REQUIRED];

  // Required. The list of destinations where the promotion applies to. If you
  // don't specify a destination by including a supported value in your data
  // source, your promotion will display in Shopping ads and free listings by
  // default.
  //
  // You may have previously submitted the following values as destinations for
  // your products: Shopping Actions, Surfaces across Google, Local surfaces
  // across Google.  To represent these values use `FREE_LISTINGS`,
  // `FREE_LOCAL_LISTINGS`, `LOCAL_INVENTORY_ADS`. For more details see
  // [Promotion
  // destination](https://support.google.com/merchants/answer/13837465?sjid=5155774230887277618-NC)
  repeated google.shopping.type.Destination.DestinationEnum
      promotion_destinations = 6 [(google.api.field_behavior) = REQUIRED];

  // Optional. Product filter by [item
  // ID](https://support.google.com/merchants/answer/13861565?ref_topic=13773355&sjid=17642868584668136159-NC)
  // for the promotion. The product filter attributes only applies when the
  // products eligible for promotion product applicability
  // `product_applicability` attribute is set to
  // [specific_products](https://support.google.com/merchants/answer/13837299?ref_topic=13773355&sjid=17642868584668136159-NC).
  repeated string item_id_inclusion = 7
      [(google.api.field_behavior) = OPTIONAL];

  // Optional. Product filter by brand for the promotion. The product filter
  // attributes only applies when the products eligible for promotion product
  // applicability `product_applicability` attribute is set to
  // [specific_products](https://support.google.com/merchants/answer/13837299?ref_topic=13773355&sjid=17642868584668136159-NC).
  repeated string brand_inclusion = 8 [(google.api.field_behavior) = OPTIONAL];

  // Optional. Product filter by item group ID for the promotion. The product
  // filter attributes only applies when the products eligible for promotion
  // product applicability [product_applicability] attribute is set to
  // [specific_products](https://support.google.com/merchants/answer/13837299?ref_topic=13773355&sjid=17642868584668136159-NC).
  repeated string item_group_id_inclusion = 9
      [(google.api.field_behavior) = OPTIONAL];

  // Optional. Product filter by product type for the promotion. The product
  // filter attributes only applies when the products eligible for promotion
  // product applicability `product_applicability` attribute is set to
  // [specific_products](https://support.google.com/merchants/answer/13837299?ref_topic=13773355&sjid=17642868584668136159-NC).
  repeated string product_type_inclusion = 10
      [(google.api.field_behavior) = OPTIONAL];

  // Optional. Product filter by [item ID
  // exclusion](https://support.google.com/merchants/answer/13863524?ref_topic=13773355&sjid=17642868584668136159-NC)
  // for the promotion. The product filter attributes only applies when the
  // products eligible for promotion product applicability
  // `product_applicability` attribute is set to
  // [specific_products](https://support.google.com/merchants/answer/13837299?ref_topic=13773355&sjid=17642868584668136159-NC).
  repeated string item_id_exclusion = 11
      [(google.api.field_behavior) = OPTIONAL];

  // Optional. Product filter by [brand
  // exclusion](https://support.google.com/merchants/answer/13861679?ref_topic=13773355&sjid=17642868584668136159-NC)
  // for the promotion. The product filter attributes only applies when the
  // products eligible for promotion product applicability
  // `product_applicability` attribute is set to
  // [specific_products](https://support.google.com/merchants/answer/13837299?ref_topic=13773355&sjid=17642868584668136159-NC).
  repeated string brand_exclusion = 12 [(google.api.field_behavior) = OPTIONAL];

  // Optional. Product filter by [item group
  // ID](https://support.google.com/merchants/answer/13837298?ref_topic=13773355&sjid=17642868584668136159-NC).
  // The product filter attributes only applies when the products eligible for
  // promotion product applicability `product_applicability` attribute is set to
  // [specific_products](https://support.google.com/merchants/answer/13837299?ref_topic=13773355&sjid=17642868584668136159-NC).
  // exclusion for the promotion.
  repeated string item_group_id_exclusion = 13
      [(google.api.field_behavior) = OPTIONAL];

  // Optional. Product filter by [product type
  // exclusion](https://support.google.com/merchants/answer/13863746?ref_topic=13773355&sjid=17642868584668136159-NC)
  // for the promotion. The product filter attributes only applies when the
  // products eligible for promotion product applicability
  // `product_applicability` attribute is set to
  // [specific_products](https://support.google.com/merchants/answer/13837299?ref_topic=13773355&sjid=17642868584668136159-NC).
  repeated string product_type_exclusion = 14
      [(google.api.field_behavior) = OPTIONAL];

  // Optional. [Minimum purchase
  // amount](https://support.google.com/merchants/answer/13837705?ref_topic=13773355&sjid=17642868584668136159-NC)
  // for the promotion.
  google.shopping.type.Price minimum_purchase_amount = 15
      [(google.api.field_behavior) = OPTIONAL];

  // Optional. [Minimum purchase
  // quantity](https://support.google.com/merchants/answer/13838182?ref_topic=13773355&sjid=17642868584668136159-NC)
  // for the promotion.
  int64 minimum_purchase_quantity = 16 [(google.api.field_behavior) = OPTIONAL];

  // Optional. [Maximum purchase
  // quantity](https://support.google.com/merchants/answer/13861564?ref_topic=13773355&sjid=17642868584668136159-NC)
  // for the promotion.
  int64 limit_quantity = 17 [(google.api.field_behavior) = OPTIONAL];

  // Optional. [Maximum product
  // price](https://support.google.com/merchants/answer/2906014) for
  // promotion.
  google.shopping.type.Price limit_value = 18
      [(google.api.field_behavior) = OPTIONAL];

  // Optional. The [percentage
  // discount](https://support.google.com/merchants/answer/13837404?sjid=17642868584668136159-NC)
  // offered in the promotion.
  int64 percent_off = 19 [(google.api.field_behavior) = OPTIONAL];

  // Optional. The [money off
  // amount](https://support.google.com/merchants/answer/13838101?ref_topic=13773355&sjid=17642868584668136159-NC)
  // offered in the promotion.
  google.shopping.type.Price money_off_amount = 20
      [(google.api.field_behavior) = OPTIONAL];

  // Optional. The number of items discounted in the promotion. The attribute is
  // set when `couponValueType` is equal to `buy_m_get_n_money_off` or
  // `buy_m_get_n_percent_off`.
  int64 get_this_quantity_discounted = 21
      [(google.api.field_behavior) = OPTIONAL];

  // Optional. [Free gift
  // value](https://support.google.com/merchants/answer/13844477?ref_topic=13773355&sjid=17642868584668136159-NC)
  // for the promotion.
  google.shopping.type.Price free_gift_value = 22
      [(google.api.field_behavior) = OPTIONAL];

  // Optional. [Free gift
  // description](https://support.google.com/merchants/answer/13847245?ref_topic=13773355&sjid=17642868584668136159-NC)
  // for the promotion.
  string free_gift_description = 23 [(google.api.field_behavior) = OPTIONAL];

  // Optional. [Free gift item
  // ID](https://support.google.com/merchants/answer/13857152?ref_topic=13773355&sjid=17642868584668136159-NC)
  // for the promotion.
  string free_gift_item_id = 24 [(google.api.field_behavior) = OPTIONAL];

  // Required. `TimePeriod` representation of the promotion's effective dates.
  // This attribute specifies that the promotion can be tested on your online
  // store during this time period.
  google.type.Interval promotion_effective_time_period = 25
      [(google.api.field_behavior) = REQUIRED];

  // Optional. `TimePeriod` representation of the promotion's display dates.
  // This attribute specifies the date and time frame when the promotion will be
  // live on Google.com and Shopping ads. If the display time period for
  // promotion `promotion_display_time_period` attribute is not specified, the
  // promotion effective time period `promotion_effective_time_period`
  // determines the date and time frame when the promotion will be live on
  // Google.com and Shopping ads.
  google.type.Interval promotion_display_time_period = 26
      [(google.api.field_behavior) = OPTIONAL];

  // Optional. Whether the promotion applies to [all stores, or only specified
  // stores](https://support.google.com/merchants/answer/13857563?sjid=17642868584668136159-NC).
  // Local Inventory ads promotions throw an error if no store applicability is
  // included. An `INVALID_ARGUMENT` error is thrown if `store_applicability` is
  // set to `ALL_STORES` and `store_codes_inclusion` or `score_code_exclusion`
  // is set to a value.
  StoreApplicability store_applicability = 28
      [(google.api.field_behavior) = OPTIONAL];

  // Optional. [Store codes to
  // include](https://support.google.com/merchants/answer/13857470?ref_topic=13773355&sjid=17642868584668136159-NC)
  // for the promotion. The store filter attributes only applies when the
  // `store_applicability` attribute is set to
  // [specific_stores](https://support.google.com/merchants/answer/13857563?ref_topic=13773355&sjid=17642868584668136159-NC).
  //
  // Store code (the store ID from
  // your Business Profile) of the physical store the product is sold in. See
  // the [Local product inventory data
  // specification](https://support.google.com/merchants/answer/3061342) for
  // more information.
  repeated string store_codes_inclusion = 29
      [(google.api.field_behavior) = OPTIONAL];

  // Optional. [Store codes to
  // exclude](https://support.google.com/merchants/answer/13859586?ref_topic=13773355&sjid=17642868584668136159-NC)
  // for the promotion. The store filter attributes only applies when the
  // `store_applicability` attribute is set to
  // [specific_stores](https://support.google.com/merchants/answer/13857563?ref_topic=13773355&sjid=17642868584668136159-NC).
  repeated string store_codes_exclusion = 30
      [(google.api.field_behavior) = OPTIONAL];

  // Optional. URL to the page on the merchant's site where the promotion shows.
  // Local Inventory ads promotions throw an error if no `promotion_url` is
  // included. URL is used to confirm that the promotion is valid and can be
  // redeemed.
  string promotion_url = 31 [(google.api.field_behavior) = OPTIONAL];
}

// The status of the promotion.
message PromotionStatus {
  // The status for the specified destination.
  message DestinationStatus {
    // The current state of the promotion.
    enum State {
      // Unknown promotion state.
      STATE_UNSPECIFIED = 0;

      // The promotion is under review.
      IN_REVIEW = 1;

      // The promotion is disapproved.
      REJECTED = 2;

      // The promotion is approved and active.
      LIVE = 3;

      // The promotion is stopped by merchant.
      STOPPED = 4;

      // The promotion is no longer active.
      EXPIRED = 5;

      // The promotion is not stopped, and all reviews are approved, but the
      // active date is in the future.
      PENDING = 6;
    }

    // Output only. The name of the promotion destination.
    google.shopping.type.ReportingContext.ReportingContextEnum
        reporting_context = 1 [(google.api.field_behavior) = OUTPUT_ONLY];

    // Output only. The status for the specified destination.
    State status = 2 [(google.api.field_behavior) = OUTPUT_ONLY];
  }

  // The issue associated with the promotion.
  message ItemLevelIssue {
    // The severity of the issue.
    enum Severity {
      // Not specified.
      SEVERITY_UNSPECIFIED = 0;

      // This issue represents a warning and does not have a direct affect
      // on the promotion.
      NOT_IMPACTED = 1;

      // The promotion is demoted and most likely have limited performance
      // in search results
      DEMOTED = 2;

      // Issue disapproves the promotion.
      DISAPPROVED = 3;
    }

    // Output only. The error code of the issue.
    string code = 1 [(google.api.field_behavior) = OUTPUT_ONLY];

    // Output only. How this issue affects serving of the promotion.
    Severity severity = 2 [(google.api.field_behavior) = OUTPUT_ONLY];

    // Output only. Whether the issue can be resolved by the merchant.
    string resolution = 3 [(google.api.field_behavior) = OUTPUT_ONLY];

    // Output only. The attribute's name, if the issue is caused by a single
    // attribute.
    string attribute = 4 [(google.api.field_behavior) = OUTPUT_ONLY];

    // Output only. The destination the issue applies to.
    google.shopping.type.ReportingContext.ReportingContextEnum
        reporting_context = 5 [(google.api.field_behavior) = OUTPUT_ONLY];

    // Output only. A short issue description in English.
    string description = 6 [(google.api.field_behavior) = OUTPUT_ONLY];

    // Output only. A detailed issue description in English.
    string detail = 7 [(google.api.field_behavior) = OUTPUT_ONLY];

    // Output only. The URL of a web page to help with resolving this issue.
    string documentation = 8 [(google.api.field_behavior) = OUTPUT_ONLY];

    // Output only. List of country codes (ISO 3166-1 alpha-2) where issue
    // applies to the offer.
    repeated string applicable_countries = 9
        [(google.api.field_behavior) = OUTPUT_ONLY];
  }

  // Output only. The intended destinations for the promotion.
  repeated DestinationStatus destination_statuses = 1
      [(google.api.field_behavior) = OUTPUT_ONLY];

  // Output only. A list of issues associated with the promotion.
  repeated ItemLevelIssue item_level_issues = 2
      [(google.api.field_behavior) = OUTPUT_ONLY];

  // Output only. Date on which the promotion has been created
  // in [ISO 8601](http://en.wikipedia.org/wiki/ISO_8601) format: Date, time,
  // and offset, for example `2020-01-02T09:00:00+01:00` or
  // `2020-01-02T09:00:00Z`
  google.protobuf.Timestamp creation_date = 3
      [(google.api.field_behavior) = OUTPUT_ONLY];

  // Output only. Date on which the promotion status has been last updated
  // in [ISO 8601](http://en.wikipedia.org/wiki/ISO_8601) format: Date, time,
  // and offset, for example `2020-01-02T09:00:00+01:00` or
  // `2020-01-02T09:00:00Z`
  google.protobuf.Timestamp last_update_date = 4
      [(google.api.field_behavior) = OUTPUT_ONLY];
}
