# Payment Methods API

> **Prefix:** `/api/v1/my/payment-methods`

Per-**environment** payment methods managed from the settings screen (`/admin/my-financial`,
tab "مدیریت پرداخت"). Two resources: **bank accounts** and **POS (card reader) devices**.

> **دسترسی منشی:** روش‌های پرداخت زیرمجموعهٔ منبع `payments` هستند. برای `ROLE_SECRETARY` (`SecretaryAccessChecker`): GET→`payments.view`, POST→`payments.create`, PUT/PATCH→`payments.update`؛ نبودِ مجوز یا رابطهٔ فعال → `403`. جزئیات: [secretary.md](secretary.md).
Records are stored so a patient invoice can later reference which account/device a
service payment was made to.

All endpoints are scoped to the **active environment** (`EntityContextResolver`), not to
the acting user. A doctor who also owns a clinic sees a different set of cards in each
environment; switching context switches the list. `user_id` is still stored, but only
records who registered the card.

> **کارت‌های بدون محیط.** ردیف‌هایی که پیش از این نشانه‌گذاری ثبت شده‌اند و مالکشان
> بیش از یک محیط دارد، `entity_type: null` می‌گیرند: هیچ ستونی نمی‌گفت کارت مال کدام
> محیط است و حدس زدنش یعنی پول به حساب اشتباه.
>
> چنین ردیفی در **هیچ** محیطی «متعلق» نیست (`TenantFilter` شرط تساوی می‌گذارد و NULL
> با هیچ مقداری برابر نیست) و تا تعیین محیط **قابل ویرایش نیست** — ولی در فهرست
> خودِ مالک می‌آید تا با `PATCH .../{uuid}/environment` به محیط فعال منتسبش کند.
> این کوئری عمداً بیرون فیلتر و محدود به `user_id` اجرا می‌شود.
> جزئیات: [architecture/tenancy.md](../architecture/tenancy.md).

**اگر محیط فعالی حل نشود** (مثلاً نقش کلینیک بدون کلینیکِ واقعی، یا منشیِ بدون
`UserActiveContext`) همهٔ این endpointها `403 ERR_FORBIDDEN_001` می‌دهند.

**Permission:** authenticated user with one of `ROLE_CLINIC`, `ROLE_DOCTOR`,
`ROLE_SECRETARY`, `ROLE_ADMIN` (otherwise `403 ERR_FORBIDDEN_001`).

---

## Bank accounts

### GET `/api/v1/my/payment-methods/bank-accounts`

List the bank accounts of the active environment (newest first), followed by any of the
caller's own cards that still have no environment.

#### Response `200`
```json
{
  "success": true,
  "data": [
    {
      "uuid": "b73d0c8e-3833-4314-83ba-937b6d4dbc60",
      "bank_name": "ملی",
      "card_number": "6037991234567890",
      "account_number": "0101234567890",
      "shaba_number": "IR820540102680020817909002",
      "is_active": true,
      "created_at": 1785238315,
      "entity_type": "clinic"
    },
    {
      "uuid": "21225430-0108-4adf-99f1-978e0a864c71",
      "bank_name": "ملت",
      "card_number": null,
      "account_number": "0209876543210",
      "shaba_number": null,
      "is_active": true,
      "created_at": 1785238315,
      "entity_type": null
    }
  ]
}
```

| Field | Type | Description |
|-------|------|-------------|
| `entity_type` | `"doctor"` \| `"clinic"` \| `null` | محیطِ مالک؛ `null` یعنی هنوز تعیین نشده و کارت قابل استفاده نیست |

Empty list returns `"data": []`.

---

### POST `/api/v1/my/payment-methods/bank-accounts`

Create a bank account.

#### Body
| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `bank_name` | string | ✅ | Bank name |
| `account_number` | string | ✅ | Account number |
| `card_number` | string | ❌ | Card number |
| `shaba_number` | string | ❌ | IBAN / SHABA |

#### Response `201`
Single created record (same shape as list item). `entity_type` is the active environment.

#### Errors
- `422 ERR_VALIDATION_001` — `bank_name` or `account_number` missing (`field` set).

---

### PUT `/api/v1/my/payment-methods/bank-accounts/{uuid}`

Update a bank account. Any subset of the create fields may be sent; only provided
keys change. Empty `bank_name`/`account_number` → `422`.

#### Response `200`
Updated record.

#### Errors
- `404 ERR_NOT_FOUND_001` — uuid unknown, owned by another environment, or still unassigned.
- `422 ERR_VALIDATION_001` — provided `bank_name`/`account_number` empty.

---

### PATCH `/api/v1/my/payment-methods/bank-accounts/{uuid}/status`

Toggle `is_active` (active ⇄ inactive). No body.

#### Response `200`
Record with flipped `is_active`.

#### Errors
- `404 ERR_NOT_FOUND_001` — uuid unknown, owned by another environment, or still unassigned.

---

### PATCH `/api/v1/my/payment-methods/bank-accounts/{uuid}/environment`

کارتِ **بی‌محیطِ خودِ کاربر** را به محیط فعال می‌چسباند. بدون بدنه.

شرط‌های مالکیت و بی‌محیط بودن داخل خودِ `UPDATE` هستند، پس دو درخواست هم‌زمان
نمی‌توانند یک کارت را به دو محیط بچسبانند و کارتِ محیط‌دار هم ربوده نمی‌شود.

#### Response `200`
```json
{
  "success": true,
  "data": {
    "uuid": "21225430-0108-4adf-99f1-978e0a864c71",
    "bank_name": "ملت",
    "card_number": null,
    "account_number": "0209876543210",
    "shaba_number": null,
    "is_active": true,
    "created_at": 1785238315,
    "entity_type": "clinic"
  }
}
```

#### Errors
`404 ERR_NOT_FOUND_001` — uuid ناشناس، مالِ کاربر دیگر، یا از قبل محیط دارد (انتساب دوباره بی‌اثر است):
```json
{
  "success": false,
  "data": null,
  "errors": [{ "code": "ERR_NOT_FOUND_001", "message": "حساب بانکیِ بدون محیط یافت نشد" }]
}
```

---

## POS devices

### GET `/api/v1/my/payment-methods/pos`

List the card reader devices of the active environment (newest first), followed by any of
the caller's own devices that still have no environment.

#### Response `200`
```json
{
  "success": true,
  "data": [
    {
      "uuid": "382eb554-5931-4f07-b1cc-53ade2597438",
      "bank_name": "ملت",
      "serial_number": "SN-98765",
      "terminal_number": "123456",
      "account_number": null,
      "is_active": true,
      "created_at": 1785238315,
      "entity_type": "clinic"
    }
  ]
}
```

---

### POST `/api/v1/my/payment-methods/pos`

Create a POS device.

#### Body
| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `bank_name` | string | ✅ | Bank name |
| `terminal_number` | string | ✅ | Terminal number |
| `serial_number` | string | ❌ | Device serial number |
| `account_number` | string | ❌ | Linked account number |

#### Response `201`
Single created record.

#### Errors
- `422 ERR_VALIDATION_001` — `bank_name` or `terminal_number` missing (`field` set).

---

### PUT `/api/v1/my/payment-methods/pos/{uuid}`

Update a POS device. Partial update; empty `bank_name`/`terminal_number` → `422`.

#### Response `200`
Updated record.

#### Errors
- `404 ERR_NOT_FOUND_001` — uuid unknown or not owned.
- `422 ERR_VALIDATION_001` — provided `bank_name`/`terminal_number` empty.

---

### PATCH `/api/v1/my/payment-methods/pos/{uuid}/status`

Toggle `is_active`. No body.

#### Response `200`
Record with flipped `is_active`.

#### Errors
- `404 ERR_NOT_FOUND_001` — uuid unknown or not owned.

---

### PATCH `/api/v1/my/payment-methods/pos/{uuid}/environment`

قرینهٔ endpoint انتساب حساب بانکی: کارتخوانِ بی‌محیطِ خودِ کاربر را به محیط فعال
می‌چسباند. بدون بدنه.

#### Response `200`
رکورد با `entity_type` پرشده.

#### Errors
- `404 ERR_NOT_FOUND_001` — uuid ناشناس، مالِ کاربر دیگر، یا از قبل محیط دارد (پیام: «کارت خوانِ بدون محیط یافت نشد»).
