feat(migrations): add national_code_verified flag to users and normalize bank_account representation

- Added a new column `national_code_verified` to the `users` table.
- Normalized the `bank_account` field in the `representations` table from a single object to an array of IBANs with a default `verified` status of false.

feat(ApiIrService): implement identity verification client for api.ir

- Created `ApiIrService` to handle identity verification via api.ir.
- Implemented methods for matching national code with mobile and IBAN with national code and birth date.
- Added error handling and logging for external API requests.
This commit is contained in:
hamed
2026-06-25 19:38:47 +03:30
parent 9b608aaeac
commit c2c6ae4d02
515 changed files with 194899 additions and 55 deletions
+68 -3
View File
@@ -250,14 +250,18 @@ Get yearly earnings dashboard for a representation.
"mobile_number": "09120671756",
"city_id": 132,
"commission_percent": "10.00",
"bank_account": null,
"bank_account": [
{ "id": "iban-uuid-1", "iban": "IR000000000000000000000000", "bank_name": "بانک ملت", "owner_name": "حامد حسینی", "verified": true, "created_at": 1718000000 }
],
"active": true,
"created_at": 1718000000
"created_at": 1718000000,
"national_code": "0012345678",
"national_code_verified": true
}
}
}
```
> double-nested: مقدار با `data.data` استخراج می‌شود.
> double-nested: مقدار با `data.data` استخراج می‌شود. `bank_account` آرایه‌ای از ۰ تا ۲ شبا است (`null` اگر هیچ شبایی ثبت نشده). `national_code`/`national_code_verified` از کاربرِ نماینده می‌آید.
#### Errors
| Code | HTTP | Description |
@@ -266,6 +270,67 @@ Get yearly earnings dashboard for a representation.
---
### POST `/api/v1/representation/verify-national-code`
تأیید کد ملی نماینده با استعلام **شاهکار** (`s.api.ir` → ShahkarLite): تطبیق کد ملی با موبایلِ کاربر جاری. در صورت موفقیت، `national_code` ذخیره و `national_code_verified=true` می‌شود.
#### Request Body
```json
{ "national_code": "0012345678" }
```
| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `national_code` | string | ✅ | کد ملی ۱۰ رقمی |
#### Response `200`
آبجکت پروفایل نماینده (مثل `me`، با `national_code_verified: true`).
#### Errors
| Code | HTTP | Description |
|------|------|-------------|
| `ERR_VALIDATION_001` | 422 | کد ملی ۱۰ رقم نیست (`field: national_code`) |
| `ERR_IDENTITY_001` | 422 | کد ملی متعلق به این موبایل نیست (`field: national_code`) |
| `ERR_EXTERNAL_001` | 502 | خطا در استعلام |
| `ERR_EXTERNAL_002` | 503 | سرویس استعلام پیکربندی نشده |
---
### POST `/api/v1/representation/iban`
افزودن یک شماره شبا. ابتدا با **IbanMatch** (`s.api.ir`) بررسی می‌شود شبا متعلق به کد ملیِ تأییدشده‌ی نماینده باشد. حداکثر ۲ شبا.
#### Request Body
```json
{ "iban": "IR000000000000000000000000" }
```
| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `iban` | string | ✅ | شماره شبا (با/بدون `IR` و فاصله؛ نرمال‌سازی می‌شود) |
#### Response `200`
آبجکت پروفایل نماینده با `bank_account` به‌روزشده.
#### Errors
| Code | HTTP | Description |
|------|------|-------------|
| `ERR_IDENTITY_004` | 409 | کد ملی هنوز تأیید نشده |
| `ERR_IDENTITY_003` | 409 | سقف ۲ شبا پر است |
| `ERR_VALIDATION_001` | 422 | شبا نامعتبر (`field: iban`) |
| `ERR_IDENTITY_002` | 422 | شبا متعلق به نماینده نیست (`field: iban`) |
| `ERR_EXTERNAL_001` | 502 | خطا در استعلام |
| `ERR_EXTERNAL_002` | 503 | سرویس استعلام پیکربندی نشده |
---
### DELETE `/api/v1/representation/iban/{id}`
حذف یک شماره شبا با `id` آن (از `bank_account[].id`).
#### Response `200`
آبجکت پروفایل نماینده با `bank_account` به‌روزشده.
---
### POST `/api/v1/representation/doctor`
افزودن پزشک توسط نماینده. `representation_id` پزشک به‌صورت خودکار روی نماینده‌ی کاربر جاری ست می‌شود. پس از ثبت موفق، یک پیامک خوش‌آمد (تگ `welcome`) به‌صورت async به موبایل پزشک ارسال می‌شود.