{
  "$schema": "http://json-schema.org/draft-06/schema#",
  "title": "Program Transaction Schema",
  "description": "Establishes the transaction interface that programs use apply mutations/generate analytics.",
  "type": "object",
  "properties": {
    "programId": {
      "type": "string",
      "title": "Program Identifier"
    },
    "mutations": {
      "type": "array",
      "title": "Mutations",
      "description": "These are actions we would like to be performed by the program engine (i.e. creating a reward or sending an email)",
      "items": {
        "$ref": "#/definitions/mutation"
      }
    },
    "analytics": {
      "type": "array",
      "title": "Analytics",
      "description": "A list of analytics representing activities performed by the program",
      "items": {
        "$ref": "#/definitions/analytics"
      }
    }
  },
  "additionalProperties": false,
  "required": [
    "programId"
  ],
  "definitions": {
    "user": {
      "type": "object",
      "title": "Mutation User",
      "description": "The mutation will be applied to this user",
      "properties": {
        "id": {
          "type": "string",
          "title": "User ID"
        },
        "accountId": {
          "type": "string",
          "title": "User Account ID"
        }
      },
      "additionalProperties": false,
      "required": [
        "id",
        "accountId"
      ]
    },
    "mutation": {
      "type": "object",
      "title": "Program Mutation",
      "properties": {
        "type": {
          "type": "string",
          "title": "Mutation Type",
          "description": "The type of mutation to be performed",
          "enum": [
            "CREATE_REWARD",
            "SEND_EMAIL",
            "MODERATE_GRAPH_NODES",
            "EXCHANGE_REWARD",
            "RETRACT_REFERRAL_CONVERSION"
          ]
        }
      },
      "dependencies": {
        "type": {
          "oneOf": [
            {
              "$ref": "#/definitions/rewardCreation"
            },
            {
              "$ref": "#/definitions/moderateGraphNodes"
            },
            {
              "$ref": "#/definitions/sendEmail"
            },
            {
              "$ref": "#/definitions/exchangeReward"
            },
            {
              "$ref": "#/definitions/retractReferralConversion"
            }
          ]
        }
      }
    },
    "rewardCreation": {
      "type": "object",
      "properties": {
        "type": {
          "enum": [
            "CREATE_REWARD"
          ]
        },
        "data": {
          "type": "object",
          "title": "Reward Data",
          "properties": {
            "key": {
              "type": "string",
              "title": "Reward Key",
              "description": "The program template key used to establish the relationship between this reward and the program"
            },
            "rewardId": {
              "type": [
                "string",
                "null"
              ],
              "title": "Reward ID",
              "description": "A unique BSON ObjectID used to identify the reward, if not set this will be auto-generated. Use this to link with emails."
            },
            "referralId": {
              "type": [
                "string",
                "null"
              ],
              "title": "Referral ID",
              "description": "The referral ID for the event to be marked as a source of this reward"
            },
            "status": {
              "$ref": "#/definitions/initialRewardStatus"
            },
            "rewardSource": {
              "type": "string",
              "title": "Reward Source",
              "enum": [
                "FRIEND_SIGNUP",
                "REFERRED",
                "ACTIVATION",
                "ACQUISITION",
                "RETENTION",
                "REACTIVATION",
                "AUTOMATED"
              ]
            },
            "user": {
              "$ref": "#/definitions/user"
            },
            "userEvent": {
              "type": [
                "object",
                "null"
              ],
              "properties": {
                "key": {
                  "type": "string",
                  "title": "Event Key",
                  "description": "The key of the event to be marked as a source of this reward"
                },
                "id": {
                  "type": "string",
                  "title": "Event ID",
                  "description": "The unique identifier of the event to be marked as a source of this reward"
                }
              },
              "additionalProperties": false,
              "required": [
                "key",
                "id"
              ]
            },
            "dynamicProperties": {
              "type": "object",
              "title": "If the reward is marked as dynamic by the program template these properties will be used to dynamically generate the reward. TODO describe user definition precedence?",
              "$ref": "#/definitions/exchangeReward/properties/data/properties/rewardInput"
            },
            "overrideProperties": {
              "type": "object",
              "title": "Reward Override",
              "description": "Properties included here will override or be added to properties setup via program reward configuration",
              "properties": {
                "dateScheduledFor": {
                  "type": [
                    "integer",
                    "null"
                  ],
                  "title": "Scheduled Reward Given Date",
                  "description": "If the reward is created in a PENDING state this is the date we will attempt to 'give' it"
                },
                "dateExpires": {
                  "type": [
                    "integer",
                    "null"
                  ],
                  "title": "Reward Expiry Date",
                  "description": "The date this reward is scheduled to expire if the reward is expirable"
                }
              },
              "additionalProperties": false
            }
          },
          "not": {
            "required": [
              "dynamicProperties",
              "overrideProperties"
            ]
          },
          "additionalProperties": false,
          "required": [
            "user",
            "key"
          ]
        }
      },
      "additionalProperties": false,
      "required": [
        "type",
        "data"
      ]
    },
    "moderateGraphNodes": {
      "type": "object",
      "properties": {
        "type": {
          "enum": [
            "MODERATE_GRAPH_NODES"
          ]
        },
        "data": {
          "type": "object",
          "title": "Reward Data",
          "properties": {
            "graphNodeType": {
              "type": "string",
              "title": "Graph Node Type",
              "description": "The type of the graph node(s) to be moderated",
              "enum": [
                "REWARD",
                "PROGRAM_EMAIL",
                "REFERRAL",
                "USER_EVENT",
                "PAYMENT_ACCOUNT"
              ]
            },
            "filter": {
              "type": "object",
              "title": "Moderation Filter",
              "description": "A GraphQL filter that defines the node(s) to be moderated. See RewardFilterInput, ProgramEmailTransactionFilterInput, ProgramReferralFilterInput, and UserEventDataFilterInput"
            },
            "moderationInput": {
              "type": "object",
              "properties": {
                "action": {
                  "type": "string",
                  "title": "Moderation Action",
                  "description": "The moderation action to apply to the filtered graph node(s)",
                  "enum": [
                    "APPROVE",
                    "DENY",
                    "NOTHING"
                  ]
                },
                "maxDepth": {
                  "type": "integer",
                  "title": "Max Depth",
                  "description": "The maximum depth of child nodes to be moderated"
                }
              },
              "additionalProperties": false,
              "required": [
                "action",
                "maxDepth"
              ]
            }
          },
          "additionalProperties": false,
          "required": [
            "graphNodeType",
            "filter",
            "moderationInput"
          ]
        }
      },
      "additionalProperties": false,
      "required": [
        "type",
        "data"
      ]
    },
    "sendEmail": {
      "type": "object",
      "properties": {
        "type": {
          "enum": [
            "SEND_EMAIL"
          ]
        },
        "data": {
          "type": "object",
          "title": "Email Data",
          "properties": {
            "key": {
              "type": "string",
              "title": "Email Key",
              "description": "The program template key of the email to send"
            },
            "status": {
              "type": "string",
              "title": "Email Status",
              "description": "The initial email status, if not set this will default to QUEUED",
              "enum": [
                "PENDING",
                "QUEUED"
              ]
            },
            "rewardId": {
              "type": [
                "string",
                "null"
              ],
              "title": "Email Reward ID",
              "description": "If included, this defines the reward that will be linked to this email"
            },
            "referralId": {
              "type": [
                "string",
                "null"
              ],
              "title": "Email Referral ID",
              "description": "If included, this defines the referral that will be linked to this email"
            },
            "user": {
              "$ref": "#/definitions/user"
            },
            "query": {
              "type": "string",
              "title": "Email Query",
              "description": "The GraphQL query used to build the context for this email"
            },
            "queryVariables": {
              "type": "object",
              "title": "Email Query Variables",
              "description": "This variables object parameterizes the GraphQL Email query"
            }
          },
          "additionalProperties": false,
          "required": [
            "key",
            "user",
            "query",
            "queryVariables"
          ]
        }
      },
      "additionalProperties": false,
      "required": [
        "type",
        "data"
      ]
    },
    "analytics": {
      "type": "object",
      "title": "Program Analytic",
      "properties": {
        "eventType": {
          "type": "string",
          "title": "Event Type",
          "description": "The type of event to record as an analytic",
          "enum": [
            "PROGRAM_EVALUATED",
            "PROGRAM_GOAL"
          ]
        },
        "data": {
          "type": "object",
          "title": "Event Data",
          "description": "Event data - currently just program which only requires the user",
          "properties": {
            "user": {
              "$ref": "#/definitions/user"
            },
            "programType": {
              "type": "string",
              "description": "The type of program (i.e. acquisition, loyalty, retention)",
              "enum": [
                "ACQUISITION",
                "RETENTION",
                "LOYALTY"
              ]
            },
            "analyticsKey": {
              "type": "string",
              "description": "The type of analytic recorded (i.e. in program goals this could describe the goal achieved such as 'friendPaid'). It maps directly to the goalId.",
              "pattern": "^[a-zA-Z0-9_\\-/]*$",
              "maxLength": 64
            },
            "analyticsDedupeId": {
              "type": [
                "string",
                "null"
              ],
              "description": "An ID unique in the recording of this analytic that will be used to deduplicate (i.e. with goals this could be the number of times the referrer was rewarded)",
              "pattern": "^[a-zA-Z0-9_\\-]*$",
              "maxLength": 64
            },
            "isConversion": {
              "type": "boolean",
              "description": "Whether this analytic will trigger a referral conversion. When analyticsDedupeId exists, the default value is true. When analyticsDedupeId does not exist, the default value is false."
            },
            "timestamp": {
              "type": "integer",
              "exclusiveMinimum": 0,
              "description": "The date this analytic will be marked as recorded (defaults to current tenant time if not set)"
            }
          },
          "additionalProperties": false,
          "dependencies": {
            "analyticsDedupeId": {
              "required": [
                "analyticsKey"
              ]
            }
          },
          "required": [
            "user"
          ]
        }
      },
      "additionalProperties": false,
      "required": [
        "eventType",
        "data"
      ]
    },
    "initialRewardStatus": {
      "type": "string",
      "title": "Initial Reward Status",
      "description": "This status defines the state the reward will be in when immediately after it is created",
      "enum": [
        "AVAILABLE",
        "PENDING",
        "CANCELLED"
      ]
    },
    "exchangeReward": {
      "type": "object",
      "properties": {
        "type": {
          "enum": [
            "EXCHANGE_REWARD"
          ]
        },
        "data": {
          "type": "object",
          "title": "Reward Exchange Data",
          "properties": {
            "user": {
              "$ref": "#/definitions/user"
            },
            "redeemCreditInput": {
              "type": "object",
              "description": "Defines the amount of credit to redeem for this reward exchange",
              "additionalProperties": false,
              "required": [
                "amount",
                "unit"
              ],
              "properties": {
                "amount": {
                  "type": "integer"
                },
                "unit": {
                  "type": "string"
                }
              }
            },
            "rewardInput": {
              "$schema": "http://json-schema.org/draft-06/schema#",
              "title": "Reward API Input",
              "description": "Defines the reward API data input structure.",
              "type": "object",
              "properties": {
                "type": {
                  "type": "string",
                  "title": "Reward Type",
                  "enum": [
                    "PCT_DISCOUNT",
                    "FUELTANK",
                    "CREDIT",
                    "INTEGRATION"
                  ]
                }
              },
              "dependencies": {
                "type": {
                  "oneOf": [
                    {
                      "properties": {
                        "type": {
                          "enum": [
                            "PCT_DISCOUNT"
                          ]
                        },
                        "discountPercent": {
                          "type": "integer",
                          "title": "Discount Percent",
                          "exclusiveMinimum": 0,
                          "maximum": 100,
                          "description": "The discount associated with this reward"
                        },
                        "name": {
                          "$ref": "#/definitions/exchangeReward/properties/data/properties/rewardInput/definitions/rewardName"
                        },
                        "dateExpires": {
                          "$ref": "#/definitions/exchangeReward/properties/data/properties/rewardInput/definitions/rewardDateExpires"
                        },
                        "cancellable": {
                          "$ref": "#/definitions/exchangeReward/properties/data/properties/rewardInput/definitions/rewardCancellable"
                        },
                        "dateScheduledFor": {
                          "$ref": "#/definitions/exchangeReward/properties/data/properties/rewardInput/definitions/rewardDateScheduledFor"
                        }
                      },
                      "additionalProperties": false,
                      "required": [
                        "type",
                        "discountPercent"
                      ]
                    },
                    {
                      "properties": {
                        "type": {
                          "enum": [
                            "FUELTANK"
                          ]
                        },
                        "fuelTankCode": {
                          "type": "string",
                          "title": "Fuel Tank Code",
                          "description": "The associated coupon code uploaded via the fuel tank API or portal code manager"
                        },
                        "unit": {
                          "$ref": "#/definitions/exchangeReward/properties/data/properties/rewardInput/definitions/rewardUnit"
                        },
                        "amount": {
                          "type": "string",
                          "title": "Amount",
                          "description": "The amount of credit or discount to be given"
                        },
                        "dateExpires": {
                          "$ref": "#/definitions/exchangeReward/properties/data/properties/rewardInput/definitions/rewardDateExpires"
                        },
                        "fuelTankType": {
                          "type": "string",
                          "title": "Fuel Tank Type",
                          "description": "The type of fuel tank reward being given",
                          "enum": [
                            "PCT_DISCOUNT",
                            "CREDIT"
                          ]
                        },
                        "cancellable": {
                          "$ref": "#/definitions/exchangeReward/properties/data/properties/rewardInput/definitions/rewardCancellable"
                        }
                      },
                      "additionalProperties": false,
                      "required": [
                        "type",
                        "fuelTankCode",
                        "fuelTankType",
                        "amount"
                      ]
                    },
                    {
                      "properties": {
                        "type": {
                          "enum": [
                            "CREDIT"
                          ]
                        },
                        "unit": {
                          "$ref": "#/definitions/exchangeReward/properties/data/properties/rewardInput/definitions/rewardUnit"
                        },
                        "name": {
                          "$ref": "#/definitions/exchangeReward/properties/data/properties/rewardInput/definitions/rewardName"
                        },
                        "assignedCredit": {
                          "type": "integer",
                          "title": "Assigned Credit",
                          "exclusiveMinimum": 0,
                          "description": "The initial redeemable credit assigned to be assigned to reward"
                        },
                        "dateExpires": {
                          "$ref": "#/definitions/exchangeReward/properties/data/properties/rewardInput/definitions/rewardDateExpires"
                        },
                        "cancellable": {
                          "$ref": "#/definitions/exchangeReward/properties/data/properties/rewardInput/definitions/rewardCancellable"
                        },
                        "dateScheduledFor": {
                          "$ref": "#/definitions/exchangeReward/properties/data/properties/rewardInput/definitions/rewardDateScheduledFor"
                        }
                      },
                      "additionalProperties": false,
                      "required": [
                        "type",
                        "unit",
                        "assignedCredit"
                      ]
                    },
                    {
                      "properties": {
                        "type": {
                          "enum": [
                            "INTEGRATION"
                          ]
                        },
                        "unit": {
                          "$ref": "#/definitions/exchangeReward/properties/data/properties/rewardInput/definitions/rewardUnit"
                        },
                        "name": {
                          "$ref": "#/definitions/exchangeReward/properties/data/properties/rewardInput/definitions/rewardName"
                        },
                        "description": {
                          "type": "string",
                          "title": "Reward Description",
                          "description": "This text describes the integration reward given in more detail"
                        },
                        "valueInCents": {
                          "type": "string",
                          "title": "Reward Amount",
                          "description": "The value in base currency unit (i.e. cents) to be assigned to this reward"
                        },
                        "integrationSettings": {
                          "$ref": "#/definitions/exchangeReward/properties/data/properties/rewardInput/definitions/integrationSettings"
                        }
                      },
                      "additionalProperties": false,
                      "required": [
                        "type",
                        "unit",
                        "valueInCents",
                        "integrationSettings"
                      ]
                    }
                  ]
                }
              },
              "definitions": {
                "rewardUnit": {
                  "type": "string",
                  "title": "Unit",
                  "description": "The unit of credit associated with this reward (i.e. months or usd)"
                },
                "rewardName": {
                  "type": [
                    "string",
                    "null"
                  ],
                  "title": "Reward Name"
                },
                "rewardDateExpires": {
                  "type": [
                    "integer",
                    "null"
                  ],
                  "title": "Reward Expiry Date",
                  "description": "The date this reward will expire"
                },
                "rewardCancellable": {
                  "type": [
                    "boolean",
                    "null"
                  ],
                  "title": "Cancellable",
                  "description": "Whether this reward can be cancelled"
                },
                "rewardDateScheduledFor": {
                  "type": [
                    "integer",
                    "null"
                  ],
                  "title": "Scheduled Reward Given Date",
                  "description": "If the reward is created in a PENDING state this is the date we will attempt to 'give' it"
                },
                "integrationSettings": {
                  "type": "object",
                  "title": "Integration Settings",
                  "properties": {
                    "templateId": {
                      "type": "string",
                      "title": "Email Template ID"
                    },
                    "giftId": {
                      "type": "string"
                    },
                    "utid": {
                      "type": "string"
                    }
                  }
                }
              }
            },
            "globalRewardKey": {
              "type": "string",
              "description": "The global reward key for the reward to be given"
            },
            "status": {
              "$ref": "#/definitions/initialRewardStatus"
            },
            "repeat": {
              "type": "boolean",
              "description": "Whether this reward exchange should be performed repeatedly until the user does not have enough redeemable credit. If not set, this will default to false.",
              "default": false
            }
          },
          "additionalProperties": false,
          "required": [
            "user",
            "redeemCreditInput"
          ]
        }
      }
    },
    "retractReferralConversion": {
      "type": "object",
      "properties": {
        "type": {
          "enum": [
            "RETRACT_REFERRAL_CONVERSION"
          ]
        },
        "data": {
          "type": "object",
          "title": "Retract Referral Conversion Data",
          "properties": {
            "referralId": {
              "type": "string",
              "title": "Referral ID"
            }
          },
          "additionalProperties": false,
          "required": [
            "referralId"
          ]
        }
      }
    }
  }
}