# Content Purchase and Entitlement System

# !!! THIS IS A WORK IN PROGRESS !!!

This document defines how Bigscreen customers can purchase and consume content (e.g. movies!) offered by Bigscreen.



# !!! THIS IS A WORK IN PROGRESS !!!

## Content ID

An individual contiguous item of encrypted content.

Data structure:
{
    id: "bigscreen_3d",
    title: "Bigscreen (Brightcove)",
    cdn: {
        name: CDN_BRIGHTCOVE,
        contentId: "6065934235001"
    },
    geo:
    isAdaptive: false,
    stereoPacking: "LeftRight"
    duration
}

Contains DRM information about the content, and how it should be rendered.


## Content Program

Multiple content ids bundled together.

Data structure:

- programId
- Starting Content ID
- ContentIDs: list
- geo 
- approx duration

Restrictions:
- Content programs must be made up of contentIds that all have the same geolocation (aside from global content).
- We may have content programs with basically identical content, per geo location.  This seems very inefficient from computer scientist's point of view, but for other stakeholders, replication like this is very necessary.

Used for:
1. Individual titles (e.g. even if there is a single content id, it MUST be stored within a content program)
2. pre-roll content (e.g. Ad -> Ad -> Main Movie)
3. Extended content.
4. TV Series or "Boxed sets"


## Product

Represents a particular content program to purchase.

- Each product contains:
    - Stripe product id
    - Stripe SKU
    - Content Program id
    - geo
    - Entitlement class.
    - ticketed? - if true, purchase results in a ticket that can be redeemed for an entitlement. If false, purchase instantly creates an entitlement.
    - Content data
        - Title
        - Description
        - etc


## Stripe Product and SKU

Mapping from stripe to our own product database.

Restrictions:
- Stripe SKUs *must* contain the price of each item and be a single source of truth for pricing for everyone (this is ensure no mistakes where a price is changed in OUR database and NOT on the stripe database!)
- This is how we show an end price to the customer.

Legacy system looks like this:

```
[ { id: 'prod_Cfj4B6XQRg9PJ0',
    description:
     'Arnold Schwarzenegger returns as the Terminator in this explosive action-adventure spectacle. Now he\'s one of the good guys, sent back in time to protect John Connor, the boy destined to lead the freedom fighters of the future. Linda Hamilton reprises her role as Sarah Connor, John\'s mother, a quintessential survivor who has been institutionalized for her warning of the nuclear holocaust she knows is inevitable. Together, the threesome must find a way to stop the ultimate enemy-the T-1000, the most lethal Terminator ever created. Co-written, produced and directed by James Cameron (The Terminator, Aliens, Titanic), this visual tour de force is also a touching human story of survival.',
    name: 'Terminator 2 3D',
    skus:
     { object: 'list',
       data: [Array],
       has_more: false,
       total_count: 5,
       url: '/v1/skus?product=prod_Cfj4B6XQRg9PJ0&active=true' } },
  { id: 'topgun3d',
    description: 'Top Gun 3D',
    name: 'Top Gun 3D',
    skus:
     { object: 'list',
       data: [Array],
       has_more: false,
       total_count: 3,
       url: '/v1/skus?product=topgun3d&active=true' } },
  { id: 'prod_CGEEidQWXE7N0W',
    description: null,
    name: 'Top Gun 3D',
    skus:
     { object: 'list',
       data: [Array],
       has_more: false,
       total_count: 2,
       url: '/v1/skus?product=prod_CGEEidQWXE7N0W&active=true' } } ]
```

# Receipt

When a product is purchased, store the receipt (mostly stripe data).



# Ticket

If a product is "Ticketed" then the customer gets a ticket when they purchase the item.  Ticket simply represents a future entitlement.  Used for movie nights.

Ticket data structure:
- productId
- useByDate
- isConsumed
- From the product id, get:
    - geo
    - content id
    - entitlement class

Restrictions:
- When the customer redeems the ticket, the ticket is marked as "consumed", and the server adds an entitlement to the customer's account.
- The ticket itself also has a "use-by" date. The ticket can be consumed up until the use-by.

Note:
- Any reason why we can't put this information on the entitlement?  Mainly can't do this because it would greatly complicate the entitlement.


## Entitlement classes:

When a product is purchased OR a ticket is redeemed, an entitlement class is used to "instantiate" an individual entitlement.  The entitlement class defines what the customer can do with the content once the 
ticket is redeemed.

Entitlement class information:

startDateTime: when the entitlement can be accessed.
endDateTime: when the entitlement expires.
usages: how many times the entitlement can be used
sharedTimestampIntervals: used to generate synchronization timestamps for movie nights.
invites: how many other accounts the customer can invite to watch the content with them.


### "MovieNight" Class:

1. Entitlement startDateTime: starts on the exact date time on which the ticket was redeemed.
2. Entitlement endDateTime: exactly 48 hours after the startDateTime
3. Entitlement usages: can be used 100 times.
4. SharedTimestampIntervals: Used for public movie nights - the hourly frequency around which the content is synchronized.

- SharedTimestampInterval synchronization occurs by passing a preferred starting timestamp on consumption of an entitlement. ("I want to go to
the content showing that starts at 3:45pm").  All public customers with the same choice are grouped together in the same room.


### "Rental" class:

Included to show contrast to movie night class.

1. Entitlement startDateTime: starts on the exact date time on which the ticket was redeemed.
2. Entitlement endDateTime: exactly 48 hours after the startDateTime
3. Entitlement usages: can be used 100 times.
4. Entitlement invites: the entitlement can be shared with 4 other accounts.

### For "owned" content:

Included to show how an entitlement works for "permanently owned" content.

1. Entitlement startDateTime: starts on the exact date time on which the content was purchased.
2. Entitlement endDateTime: null
3. Entitlement usages: can be used 2500? times.
4. Entitlement invites: the entitlement can be shared with 4 other accounts.



## Entitlements

Entitlements are permanently defined instances of an entitlement class.  The entitlement determines what a customer can do
with a specific piece of content.

- (Ref) Owner Account id
- (Ref) entitlement class
- (Ref) ticket id
- (Ref) product id
- programId
- geo
- startDateTime: date on which the entitlement became active
- endDateTime: date and time on which the entitlement will become inactive (or null for indefinite use).
- maxUsages: the number of times an entitlement can be used (or -1 for indefinite use).
- usages: the number of times the entitlement has been used so far.
- status: ACTIVE, EXPIRED, REVOKED
- bookmark: programIndex, timestamp since start.

To determine whether an entitlement is available to the requester:
    - Owner account id matches request account id
    - status must be ACTIVE
    - server date time must be greater than or equal to startDateTime
    - if endDateTime not null, server date time must be less than endDateTime
    - if maxUsages is not equal to -1, usages must be less than maxUsages
    - if geo is not null, 

Entitlements never get deleted (for now). 

Expired entitlements have status changed to EXPIRED using a cron job.


## Entitlement usage:

- (REF) Entitlement ID
- (Ref) Account ID
- createdAt


## Content Slate

- Program Ids that are available to be purchased or redeem tickets for.
- 

## Consuming content

