# Contract Creation Quick Start

## Setup

```bash
# Install uv (if not already installed)
curl -LsSf https://astral.sh/uv/install.sh | sh

# Install dependencies
uv sync

cp config.shadow.json config.json

# Edit config.json with:
# - bearer_token
# - signing_entity_map (name to ID mapping, lowercase keys)
# - run_controller_map (name to ID mapping, lowercase keys)
# - identity_headers (optional)
```

## CSV Format

### Required Columns
- Account ID
- Contract Name
- Contract Type (Distribution, Legacy Distribution, or Neighbouring Rights)

### Optional Columns
- Signing Entity
- Run Controller
- Execution Date (MM/DD/YYYY, YYYY-MM-DD, or DD-Mon-YYYY)
- Is Excluded From Accounting Run (Yes/No/True/False)
- Is Primary Contract (Yes/No/True/False)
- Current Period Start Date (MM/DD/YYYY, YYYY-MM-DD, or DD-Mon-YYYY)
- Renewal Rules (Continuously Active, Renew After Certain Date, Renew Periodically)
- Termination Notice Period (Interval)
- Termination Notice Period (Type) (Days/Months/Years)
- Renew After (Interval)
- Renew After (Type)
- Current Period End Date (MM/DD/YYYY, YYYY-MM-DD, or DD-Mon-YYYY)
- Collection Period (Interval)
- Collection Period (Type)

Extra columns (e.g., Account Name) are silently ignored.

### Supported File Formats

| Extension | Format | Notes |
|-----------|--------|-------|
| `.csv` | CSV (default) | Standard comma-separated values |
| `.json` | JSON | Array of objects, keys as headers |
| `.xlsx` | Excel | Requires `openpyxl` (`uv add openpyxl`) |

The format is detected from the file extension. Files without an extension default to CSV.

## Usage

### Preview (Dry Run — default)
```bash
uv run python src/cli.py \
  --input input.csv \
  --config config.json \
  --limit 5
```

### QA Environment
```bash
uv run python src/cli.py \
  --input input.csv \
  --config config.json \
  --execute \
  --output results.csv
```

### Production

Set `graphql_url` in config.json to the production endpoint, then:

```bash
uv run python src/cli.py \
  --input input.csv \
  --config config.json \
  --execute \
  --output results.csv
```

**Output:**
- `results.csv` - Successful contracts with Contract IDs
- `results_failures.csv` - Failed/skipped rows with error details

### Auto-Resume

The script automatically saves progress every 10 rows. If interrupted:
1. Update bearer token in config.json (if expired)
2. Rerun the same command

The script will skip already processed contracts and continue.

### Retry Failures

```bash
uv run python src/cli.py \
  --input results_failures.csv \
  --config config.json \
  --execute \
  --output results.csv
```

## Options

| Flag | Description | Default |
|------|-------------|---------|
| `--input` | Input file (CSV, JSON, or XLSX) | required |
| `--config` | Config JSON file | required |
| `--execute` | Make real API calls | dry-run |
| `--limit N` | Process only N rows | all |
| `--throttle-capacity` | Token bucket burst size | from config, then 1 |
| `--throttle-rate` | Requests per second | from config, then 2.0 |
| `--skip-if-missing` | Skip rows with missing required fields | false |
| `--output` | Output CSV with Contract IDs | none |
| `--resume` | Previous output CSV to resume from | none |

All flags except `--input` and `--config` can also be set in config.json. CLI flags override config values.

## Config File

Entity maps can be provided inline or loaded from the database.

### Inline maps (no database required)

```json
{
  "bearer_token": "YOUR_BEARER_TOKEN_HERE",
  "signing_entity_map": {
    "signing_entity_name": 1
  },
  "run_controller_map": {
    "run_controller_name": 1
  },
  "env": "qa",
  "api_url": null,
  "throttle_capacity": 1,
  "throttle_rate": 2.0,
  "skip_if_missing": false
}
```

Entity map keys must be **lowercase** — the CSV values are lowercased before lookup.

### Database-backed maps

When `mysql` is set, entity maps are loaded from `reference_signing_entity` and `run_controller` tables automatically. Inline maps are ignored.

```json
{
  "bearer_token": "YOUR_BEARER_TOKEN_HERE",
  "mysql": {
    "host": "qa-royalty-accounting.cluster-xyz.us-east-1.rds.amazonaws.com",
    "user": "readonly_user",
    "password": "...",
    "database": "royalty_accounting"
  },
  "env": "qa"
}
```

## Development

```bash
make env_dev              # Install dev dependencies
make test                 # Run unit tests (156)
make test_integration     # Run integration tests (6, mock HTTP)
make lint                 # Check linting
make format               # Check formatting
make docker_test          # Unit + lint in Docker
make docker_test_integration  # Integration tests with real MySQL
```

### Docker with MySQL

```bash
# First time — pull liquibase image from ECR
make docker_login

# Start MySQL + run schema migrations
make start_db

# Run integration tests against the DB
make docker_test_integration

# Or run locally against Docker MySQL
MYSQL_DB_HOST=localhost MYSQL_DB_PORT=6050 make test_integration

# Tear down
make docker_down
```

## Common Issues

**"Signing entity not found in map"**
Add signing entity to `signing_entity_map` in config.json with its database ID. Use lowercase keys.

**"Run controller not found in map"**
Add run controller to `run_controller_map` in config.json with its database ID. Use lowercase keys.

**"Unauthorized" / AUTH ERROR**
Verify bearer token is valid and has correct permissions.

**"Missing required CSV columns"**
Ensure your CSV has at minimum: Account ID, Contract Name, Contract Type.

**Dates not parsed**
Supported formats: `MM/DD/YYYY`, `YYYY-MM-DD`, `DD-Mon-YYYY` (e.g., `18-Apr-2026`).
