# Reserves Take

## Overview

This lambda creates entries in `ledger_reserve_taken` using the results of an approved `accounting_run`.
1. The `target_id` of the received `abacus_event` is the ID of the `accounting_run` from which reserves are being taken.
2. A Snowflake query is run against `ACCOUNTING_RUN_RESULTS_DISTRO` to get the total of "physical sales" and "physical returns" for each contract in the accounting run. (Reserves will only be taken if sales are greater than returns).
3. A request against ows-royalties is made to get a distinct list of `contract_ids` in the accounting run.
4. The list of `contract_ids` are used to get a list of `contract_reserve` items from ows-royalties.
5. For each item in the Snowflake results, the amount of reserves to take is determined by using the respective contract's `contract_reserve.reserve_rate`. (If the contract does not have a `contract_reserve` record, no reserves are taken).
6. The total amount of reserves taken for each contract is rounded and bulk inserted into `ledger_reserve_taken` using ows-ledger.
7. Any remaining amounts after rounding are bulk inserted into `ledger_deposit` using ows-ledger.

More on the Reserve Calculation can be found here: https://www.notion.so/Physical-Reserves-89307b6eb5c241729948f3ba78518a0a

## Getting Started

### Requirements

- Python 3.11
- Docker

### OWS Dependencies

- [ows-royalties](https://github.com/theorchard/ows-royalties)
- [ows-ledger](https://github.com/theorchard/ows-ledger)
- [ows-royalties](https://github.com/theorchard/ows-royalties)

### Installation

Create a `.env` file based on the `.env.shadow` and fill in the values:

```bash
$ cp .env.shadow .env
```

Create a virtual env and install the requirements:

```bash
$ make dev_env
```

#### Snowflake Creds
You will need to have a Snowflake SSH key pair to run this lambda -- using a username and password is no longer valid.

If you do not have a Snowflake SSH key pair set up, follow these instructions:
1. create a snowflake subdirectory: `mkdir ~/.ssh/snowflake`
2. navigate to the new subdirectory: `cd ~/.ssh/snowflake`
3. run the following command to create a public and private key:
```shell
openssl genrsa 2048 | openssl pkcs8 -topk8 -inform PEM -out rsa_key.p8
openssl rsa -in rsa_key.p8 -pubout -out rsa_key.pub
```
4. you will be prompted to create a **passphrase** -- **use something you will remember and/or jot it down, you will need this to decrypt your private key**
5. copy your `rsa_key.pub` (without the header/footer) and add it to [terraform](https://github.com/theorchard/terraform-infra/blob/master/prod/snowflake/orchard/users/users.auto.tfvars) ([example PR](https://github.com/theorchard/terraform-infra/pull/15503))


Make sure to fill in all the necessary snowflake environment variables in your `.env`:
* `SNOWFLAKE_USER` is your email (i.e. `dczinsky@sonymusic-pde.com`)
* `SNOWFLAKE_KEY_PASSPHRASE` is the key passphrase you used when creating your key-pair
* `SNOWFLAKE_PRIVATE_KEY_PATH` is the path to your private key on your machine -- if you followed the instructions above it should be `~/.ssh/snowflake/rsa_key.p8`


You may need to export these variables:
```shell
export SNOWFLAKE_USER=dczinsky@sonymusic-pde.com
export SNOWFLAKE_PRIVATE_KEY_PATH=~/.ssh/snowflake/rsa_key.p8
export SNOWFLAKE_KEY_PASSPHRASE=<secret>
```

or source all your environment variables from your `.env`:
```shell
source .env
```

### Running

You can run the function locally with: `make run`

Or you can run the function inside Docker with: `make docker_local_up` and trigger an event with `make local_event`

### Testing

You can run the linter and the unit tests locally with: `make lint` and `make test`

Or you can run the linter and the unit tests inside Docker with: `make docker_test`

The integration tests can only be run inside Docker with: `make docker_test_integration`

**Note:**
You might need to login to Docker with the shared AWS account in order to run the integration tests:

```bash
$ awsume <shared_profile>
$ make docker_login
```

### Adding new packages

- For dev packages, add them normally to `requirements-dev.txt`
- For regular packages, add the new top level package name
  and optionally version constraints to `requirements-to-freeze.txt`
- Run `make pip_lock_versions`

### Upgrading packages

Regularly running `make pip_lock_versions` will update and freeze all non-dev dependencies in `requirements.txt`
