# ows-carveouts
OWS Carveout Microservice

## Local Setup

* Install [docker](https://docs.docker.com/get-docker/)
* Clone this repository

### Set Credentials

1. Create `.env` file from template
```
$ cp .env.shadow .env
```

#### Packages from GitHub

To install some private packages, you need to be able to autheticate with Github.

* Create Github access token [here](https://github.com/settings/tokens) with all **repo** scope only.
* Set auth token in `.env` replacing `<key-goes-here>` in `COMPOSER_AUTH`

#### Databases

Set your personal database credentials for **QA** in `.env` where empty.

#### AWS

* Install and configure [awsume](https://www.notion.so/AWS-Access-f841b9dd815d4443a80e96a86c92cd2f#ad5d3a529a7d41b299daa604c517ebf2) to easily set and change AWS credentials on your current shell which will be used by the application container automatically.
* Install [ecr-credentials-helper](https://www.notion.so/AWS-Access-f841b9dd815d4443a80e96a86c92cd2f#ad5d3a529a7d41b299daa604c517ebf2) to automatically use your current AWS credentials when pulling down ECR images.


## Running Application

```bash
$ docker compose up --build web-deploy
```
:bulb: Current AWS credentials in your host machine's shell will be used to fetch from ECR and by the application.

```bash
$ curl --request GET \
  --url http://localhost:8081/hello
```

## Running Unit Tests

```bash
$ docker compose run --rm --build unit-lint
```

:bulb: set `TEST_FILTER` env var with `-e` to only run a subset of tests


## Running Integration Tests

Integration tests live in [`tests/Integration`](tests/Integration) and are written
in Python/pytest. They exercise the **deployed** HTTP API end-to-end (they do not
run the app locally), defaulting to QA (`BASE_URL=https://qa-ows-carveouts.theorchard.io`).

```bash
# Everything EXCEPT data-mutating write tests — safe against shared envs (QA).
$ make test_integration_safe

# The full suite, including write lifecycle tests (see warning below).
$ make test_integration

# In CI, via docker:
$ make ci_test_integration
```

:warning: The **write lifecycle tests create and delete carveouts**, so they are
skipped unless you provide throwaway IDs that are safe to mutate on the target
environment. `make test_integration_safe` excludes them entirely (`-m "not write"`).

See [`tests/Integration/README.md`](tests/Integration/README.md) for the full guide:
test layout, markers, environment variables, and how to enable the write tests.


## Endpoints

### Release
> Retrieves all carveouts that are explicitly set for the provided release

Carveout Type | Endpoint
----- | -----
Store | `http://orchard-url/carveout/release/{upc}/dms`
Territory | `http://orchard-url/carveout/release/{upc}/territory`
Substore | `http://orchard-url/carveout/release/{upc}/territory/{dms_id}`
All | `http://orchard-url/carveout/release/{upc}`

### Vendor
> Retrieves all carveouts that are explicitly set for the provided vendor

Carveout Type | Endpoint
----- | -----
Store | `http://orchard-url/carveout/vendor/{vendor_id}/dms`
Territory | `http://orchard-url/carveout/vendor/{vendor_id}/territory`
Substore | `http://orchard-url/carveout/vendor/{vendor_id}/territory/{dms_id}`
All | `http://orchard-url/carveout/vendor/{vendor_id}`

### Subaccount
> Retrieves all carveouts that are explicitly set for the provided subaccount

Carveout Type | Endpoint
----- | -----
Store | `http://orchard-url/carveout/subaccount/{subaccount_id}/dms`
Territory | `http://orchard-url/carveout/subaccount/{subaccount_id}/territory`
Substore | `http://orchard-url/carveout/subaccount/{subaccount_id}/territory/{dms_id}`
All | `http://orchard-url/carveout/subaccount/{subaccount_id}`

### Combined
> Retrieves the effective set of carveouts for the provided release, combining release, vendor, and subaccount level carveouts

Carveout Type | Endpoint
----- | -----
Store | `http://orchard-url/carveout/{upc}/dms`
Territory | `http://orchard-url/carveout/{upc}/territory`
Substore | `http://orchard-url/carveout/{upc}/territory/{dms_id}`
All | `http://orchard-url/carveout/{upc}`

### Store List
> Retrieves all stores

`http://orchard-url/stores/`


## Data Structure

### Store
> List of store carveouts

> Distribution type ids for which the carvout applies, indexed by store id.

````json
{
    "11" : {
        "distros": [1,2,3],
        "dms_name": "24\/7"
    },
    "187" : {
        "distros": [2],
        "dms_name": "Amazon Digital Services Inc."
    },
    "496" : {
        "distros": [1,3],
        "dms_name": "Google Music"
    }
}
````

### Territory
> List of territory carveouts

> ISO-3166 2 character country code, indexed by country id.

````json
{
    "1" : "US",
    "2" : "CA",
    "3" : "GB"
}
````

### Substore
> List of substore carveouts

> ISO-3166 2 character country code, indexed by country id.

````json
{
    "1" : "US",
    "2" : "CA",
    "3" : "GB"
}
````

### All
> Lists store, territory and substore carveouts

>#### store

>- contains list of store carveouts
>- distribution type ids for which the carvout applies, indexed by store id.

>#### territory

>- contains list of territory carveouts
>- ISO-3166 2 character country code, indexed by country id

>#### substore

>- contains list of substore carveouts
>- ISO-3166 2 character country code, indexed by country id
>- each group of carveouts indexed by store id
>- **Note:** substore list only includes territories not included in territory index

````json
{
    "store" : {
        "11" : {
            "distros": [1,2,3],
            "dms_name": "24\/7"
        },
        "187" : {
            "distros": [2],
            "dms_name": "Amazon Digital Services Inc."
        },
        "496" : {
            "distros": [1,3],
            "dms_name": "Google Music"
        }
    },
    "territory" : {
        "1" : "US",
        "2" : "CA",
        "3" : "GB"
    },
    "substore" : {
        "244" : {
            "4" : "DE"
        },
        "502" : {
            "6" : "FR"
        }
    }
}
````

### Projection

Calculates allowed territories for a specific **release + store** combination after carveouts have been applied along with release and account level validations. This takes into account the fact that stores only support subsets of distribution types and territories.

`carveout/projection/{upc}/dms/{dms_id}`

```json
{
    "empty_reason": null,
    "territories": [
        "US",
        "CA"
    ]
}
```

`"empty_reason"` returns a code to explain to the client why the territories list is empty, this is expected to be useful during order validation

* ACCOUNT_DELETED
* ACCOUNT_NOT_SIGNED
* ACCOUNT_HAS_NO_ACTIVE_CONTRACT
* RELEASE_IS_DELETED
* RELEASE_NOT_IN_CONTENT
* RELEASE_NOT_TYPE_MUSIC
* RELEASE_DISTRIBUTION_TYPE_NOT_ALLOWED_STORE
* RELEASE_DISTRIBUTION_TYPE_NOT_ALLOWED_CARVEOUT
* ALL_TERRITORIES_CARVED_OUT

### Store List
> List of stores

````json
{
    "1" : "iTunes",
    "2" : "Napster",
    "3" : "MediaNet"
}
````
