Xem Chi Tiết Hợp Đồng Tùy Chỉnh
Mô Tả Tổng Quan
Tính năng Xem Chi Tiết Hợp Đồng Tùy Chỉnh cho phép quản trị viên lấy thông tin đầy đủ về một hợp đồng tùy chỉnh cụ thể, bao gồm tất cả dữ liệu và lịch sử liên quan.
Điều Kiện Tiên Quyết
- Người dùng phải được xác thực với vai trò quản trị viên (SuperAdmin hoặc AdminStaff)
- Hợp đồng tùy chỉnh phải tồn tại
Phụ Thuộc
- Không có (thao tác chỉ đọc)
Liên Kết Swagger
API: Xem Chi Tiết Hợp Đồng Tùy Chỉnh
Tài Liệu Trường Hợp
Trường Hợp 1: Lấy Chi Tiết Hợp Đồng Thành Công
Mô Tả
Quản trị viên lấy thành công thông tin chi tiết về một hợp đồng tùy chỉnh cụ thể, bao gồm tất cả các mối quan hệ và siêu dữ liệu.
Sequence Diagram
sequenceDiagram
participant Admin
participant Controller as CustomContractController
participant Repository as CustomContractRepository
participant Database
Note over Admin,Database: GET /api/v1/admin/custom-contracts/{id}
rect rgb(200, 255, 200)
Note right of Admin: Happy Case Flow
Admin->>Controller: GET request with contract ID
rect rgb(200, 255, 255)
Note right of Controller: Data Retrieval
Controller->>Repository: findById(contractId)
Repository->>Database: SELECT * FROM custom_contracts WHERE id = ?
Database-->>Repository: Return contract record
Repository->>Repository: Load relationships (eager loading)
Repository->>Database: SELECT related records
Database-->>Repository: Return related data
Repository-->>Controller: Return contract with all relations
end
Controller-->>Admin: 200 OK (contract_data)
end
rect rgb(255, 200, 200)
Note right of Admin: Error Scenarios
rect rgb(255, 230, 230)
alt Contract Not Found
Repository-->>Controller: Null returned
Controller-->>Admin: 404 Not Found
else Database Error
Database-->>Repository: Database error
Repository-->>Controller: Error result
Controller-->>Admin: 400 Bad Request
end
end
end
Các Bước
Bước 1: Lấy Hợp Đồng
- Mô Tả: Lấy bản ghi hợp đồng với tất cả các mối quan hệ
- Yêu Cầu:
GET /api/v1/admin/custom-contracts/{id} - Ủy Quyền: Người dùng phải có vai trò SuperAdmin hoặc AdminStaff
- Tham Số Đường Dẫn:
id: ID hợp đồng tùy chỉnh (bắt buộc, số nguyên)
Bước 2: Tải Các Mối Quan Hệ
- Mô Tả: Tải tích cực tất cả dữ liệu liên quan
- Các Mối Quan Hệ Được Tải:
group: Thông tin nhóm với các thành viêngroup.groupMembers: Tất cả thành viên nhómpackagePlan: Chi tiết gói cơ bảnsubscription: Dữ liệu đăng ký liên quan
- Thao Tác Cơ Sở Dữ Liệu:
- SELECT từ custom_contracts
- LEFT JOIN với groups, package_plans, subscriptions
- Truy vấn bổ sung cho thành viên nhóm
Bước 3: Trả Về Phản Hồi
- Mô Tả: Trả về dữ liệu hợp đồng đầy đủ
- Dữ Liệu Phản Hồi:
- Tất cả các trường hợp đồng
- Chi tiết nhóm (name, status, created_by)
- Danh sách thành viên nhóm
- Chi tiết gói (nếu có)
- Chi tiết đăng ký (slug, status, email)
- Siêu dữ liệu Stripe (session_id, price_id, subscription_item_id)
- Giới hạn sử dụng (tất cả các trường max_*)
- Thông tin ngày (starts_at, ends_at, created_at, updated_at)
- Thông Báo Thành Công: "カスタムプランの詳細取得に成功しました" (Đã lấy thành công chi tiết hợp đồng)
Database Related Tables & Fields
erDiagram
custom_contracts {
bigint id PK
bigint subscription_id FK
bigint package_plan_id FK
bigint group_id FK
bigint user_id FK
string code
string billing_interval
string currency
integer amount
string status
string provider_checkout_session_id
string provider_price_id
string provider_subscription_item_id
timestamp starts_at
timestamp ends_at
integer max_member
integer max_product_group
integer max_product
integer max_category
integer max_search_query
integer max_viewpoint
string data_visible
tinyint api_available
timestamp created_at
timestamp updated_at
}
groups {
bigint id PK
string name
bigint created_by FK
integer status
timestamp created_at
timestamp updated_at
}
group_members {
bigint id PK
bigint group_id FK
bigint user_id FK
string role
timestamp created_at
}
subscriptions {
bigint id PK
string slug
bigint package_plan_id FK
bigint group_id FK
string status
string email
string payment_provider_customer_id
timestamp created_at
timestamp updated_at
}
package_plans {
bigint id PK
bigint package_id FK
string name
string billing_interval
integer amount
timestamp created_at
timestamp updated_at
}
users {
bigint id PK
string name
string email
timestamp created_at
}
custom_contracts ||--|| groups : belongs_to
custom_contracts ||--o| package_plans : based_on
custom_contracts ||--o| subscriptions : has
custom_contracts ||--o| users : managed_by
groups ||--o{ group_members : has
group_members ||--|| users : belongs_to
Error Handling
- Log: Errors are logged via
logThrow()method - Error Detail:
| Status Code | Error Message | Description |
|---|---|---|
| 404 | "カスタムプランが見つかりませんでした" | When contract with specified ID doesn't exist |
| 400 | Generic error with exception message | For unexpected database errors |
Additional Notes
Response Structure
The response includes comprehensive contract information:
- Contract Details: code, status, amounts, intervals, dates
- Stripe Integration: session_id, price_id, subscription_item_id
- Usage Limits: All max_* fields (null means unlimited)
- Related Group: Full group details with member list
- Related Subscription: Complete subscription information
- Related Package Plan: Base plan used as template
Group Members Information
- Includes all members of the contract's group
- Shows member roles and permissions
- Useful for admin to understand who has access
Usage Limits Display
nullvalues indicate unlimited usage for that resource0values indicate feature is disabled- Positive integers show the specific limit
Status Information
Contract status indicates lifecycle stage:
- draft: Created but not yet offered
- offered: Payment link sent, awaiting payment
- active: Payment successful, contract in effect
- expired: Contract end date has passed
- cancelled: Contract terminated before expiration
Stripe Metadata
- provider_checkout_session_id: Used to track payment session
- provider_price_id: Stripe price ID for subscription
- provider_subscription_item_id: Stripe subscription item for management
Performance Considerations
- Single query with eager loading prevents N+1 problem
- Indexed lookup on contract ID (primary key)
- Fast response time (typically < 100ms)
- Consider caching for frequently accessed contracts
Response Format Example
{
"status": true,
"message": "カスタムプランの詳細取得に成功しました",
"data": {
"id": 1,
"subscription_id": 10,
"package_plan_id": 3,
"group_id": 5,
"user_id": 15,
"code": "CUSTOM-2026-001",
"billing_interval": "month",
"currency": "jpy",
"amount": 150000,
"status": "active",
"provider_checkout_session_id": "cs_test_abc123",
"provider_price_id": "price_abc123",
"provider_subscription_item_id": "si_abc123",
"starts_at": "2026-02-01T00:00:00Z",
"ends_at": "2027-02-01T00:00:00Z",
"max_member": 10,
"max_product_group": 5,
"max_product": 100,
"max_category": 20,
"max_search_query": 50,
"max_viewpoint": 30,
"data_visible": "private",
"api_available": 1,
"created_at": "2026-01-28T10:30:00Z",
"updated_at": "2026-01-28T15:45:00Z",
"group": {
"id": 5,
"name": "Test Corporation",
"status": 1,
"created_by": 12,
"group_members": [
{
"id": 1,
"user_id": 15,
"role": "owner",
"user": {
"id": 15,
"name": "John Doe",
"email": "john@example.com"
}
}
]
},
"subscription": {
"id": 10,
"slug": "sub_abc123",
"status": "active",
"email": "billing@example.com",
"payment_provider_customer_id": "cus_abc123"
},
"package_plan": {
"id": 3,
"name": "Enterprise Plan",
"billing_interval": "month",
"amount": 100000
}
}
}