feat: add multi-city representation support and domain context resolution
- Created migration to add representation_cities table and domain, is_global fields to representations. - Implemented SiteContextController to resolve domain to site context (city | representation | unknown). - Developed DomainContext and DomainContextResolver services for domain mapping. - Added tests for DomainContextResolver and commission logic based on domain ownership.
This commit is contained in:
@@ -32,10 +32,14 @@ Create a new representation.
|
||||
|-------|------|----------|-------------|
|
||||
| `full_name` | string | ✅ | Agent full name |
|
||||
| `mobile_number` | string | ✅ | Login mobile (creates a User account) |
|
||||
| `city_id` | integer | ❌ | City ID (FK to categories where bundle=city) |
|
||||
| `city_ids` | integer[] | ❌ | شهرهای تحت پوشش (چند-شهری). `city_id` تکی هم برای BC پذیرفته میشود |
|
||||
| `domain` | string | ❌ | دامنه اختصاصی نماینده (نرمال میشود: بدون scheme/www). یکتا؛ نباید با دامنه شهرها تداخل کند. **admin-only** |
|
||||
| `is_global` | boolean | ❌ | نماینده سراسری — سایتِ دامنهاش فقط پزشکان/کلینیکهای خودش را نشان میدهد. **admin-only** |
|
||||
| `commission_percent` | float | ❌ | Commission rate (0–100) |
|
||||
| `bank_account` | object | ❌ | Bank details for settlements |
|
||||
|
||||
**پاسخها اکنون شامل:** `city_ids: int[]`، `cities: [{id, name}]`، `domain`، `is_global` (علاوه بر `city_id` قدیمی = اولین شهر).
|
||||
|
||||
### Response `201`
|
||||
```json
|
||||
{
|
||||
@@ -119,9 +123,9 @@ Update representation.
|
||||
}
|
||||
```
|
||||
|
||||
All fields optional.
|
||||
All fields optional. `city_ids: int[]` جایگزین `city_id` است (تکی هم پذیرفته میشود).
|
||||
|
||||
**Privileged fields:** `commission_percent` and `active` are **admin-only** — a representation editing its own record may change `full_name`, `city_id`, `bank_account` but **not** these two. `commission_percent` must be within `0–100`.
|
||||
**Privileged fields:** `commission_percent`، `active`، `domain` و `is_global` **admin-only** هستند — نماینده روی رکورد خودش فقط `full_name`، `city_ids`، `bank_account` را میتواند تغییر دهد. `commission_percent` باید در بازه `0–100` باشد. خطاهای `domain`: نامعتبر → 422، تکراری یا برخورد با دامنه شهر → 409.
|
||||
|
||||
### Response `200`
|
||||
Updated representation object.
|
||||
@@ -233,6 +237,40 @@ Get yearly earnings dashboard for a representation.
|
||||
|
||||
---
|
||||
|
||||
## GET `/api/v1/site-context`
|
||||
|
||||
**عمومی (بدون auth).** نگاشت یک دامنه به زمینهی سایت — مصرفکننده: سایت عمومی nobat724 برای دامنههای خارج از `data/city.json` (دامنه اختصاصی نمایندگان سراسری).
|
||||
|
||||
### Query Parameters
|
||||
| Param | Type | Required | Description |
|
||||
|-------|------|----------|-------------|
|
||||
| `domain` | string | ✅ | host یا URL کامل؛ نرمال میشود (scheme/www/پورت حذف) |
|
||||
|
||||
### Response `200`
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"data": {
|
||||
"type": "representation",
|
||||
"city": null,
|
||||
"representation": { "uuid": "...", "full_name": "نماینده الف", "is_global": true }
|
||||
}
|
||||
}
|
||||
```
|
||||
`type`: `city` (دامنه یکی از شهرها) | `representation` (دامنه اختصاصی نماینده فعال) | `unknown`. برای `city`، آبجکت `city: {id, name}` پر میشود.
|
||||
|
||||
---
|
||||
|
||||
## قانون کمیسیون دامنهمحور
|
||||
|
||||
کمیسیون (نوبت **و** اشتراک) فقط وقتی ثبت میشود که **هر دو** شرط برقرار باشد:
|
||||
1. دامنهی مبدأ خرید (`payment.frontend_address`) متعلق به یک نمایندهی فعال باشد (`representations.domain`).
|
||||
2. پزشک/کلینیکِ موضوع خرید، `representation_id` همان نماینده را داشته باشد.
|
||||
|
||||
در غیر این صورت هیچ کمیسیونی برای هیچ نمایندهای ثبت نمیشود (پرداخت بدون `frontend_address` هم کمیسیون ندارد). درصد: نوبت = `commission_percent` نماینده؛ اشتراک = تنظیم سراسری `upgrade_commission_percent`. نگاشت دامنه فقط از طریق `DomainContextResolver` انجام میشود.
|
||||
|
||||
---
|
||||
|
||||
## پنل نماینده (ROLE_REPRESENTATION)
|
||||
|
||||
این endpointها برای کاربرِ دارای نقش `ROLE_REPRESENTATION` در پنل ادمین (`/admin`) هستند. مالکیت همیشه از کاربر جاری (`#[CurrentUser]` + `findByUser`) تعیین میشود؛ هیچ uuid/id ورودی برای تعیین مالکیت پذیرفته نمیشود.
|
||||
|
||||
Reference in New Issue
Block a user