Browse Source
feat(transaction): implement receipt management for transactions
feat(transaction): implement receipt management for transactions
- Added `TransactionReceipt` model to store payment receipts uploaded by users. - Introduced endpoints for uploading receipts and listing receipts associated with transactions. - Updated `TransactionParticipant` model to include a new status 'waiting_approval'. - Enhanced serializers to handle receipt uploads and retrievals, including validation for file uploads. - Updated admin interface to manage transaction receipts effectively. - Added comprehensive API documentation for transaction receipt operations.master
9 changed files with 968 additions and 26 deletions
-
21apps/library/migrations/0009_alter_book_language.py
-
61apps/transaction/admin.py
-
529apps/transaction/doc.py
-
35apps/transaction/migrations/0003_alter_transactionparticipant_status_and_more.py
-
44apps/transaction/models.py
-
57apps/transaction/serializers.py
-
3apps/transaction/urls.py
-
165apps/transaction/views.py
-
79templates/docs.html
@ -0,0 +1,21 @@ |
|||||
|
# Generated by Django 5.1.8 on 2025-12-03 23:32 |
||||
|
|
||||
|
import dj_language.field |
||||
|
import django.db.models.deletion |
||||
|
from django.db import migrations |
||||
|
|
||||
|
|
||||
|
class Migration(migrations.Migration): |
||||
|
|
||||
|
dependencies = [ |
||||
|
('dj_language', '0002_auto_20220120_1344'), |
||||
|
('library', '0008_auto_20251203_1533'), |
||||
|
] |
||||
|
|
||||
|
operations = [ |
||||
|
migrations.AlterField( |
||||
|
model_name='book', |
||||
|
name='language', |
||||
|
field=dj_language.field.LanguageField(blank=True, default=69, limit_choices_to={'status': True}, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='+', to='dj_language.language', verbose_name='Language'), |
||||
|
), |
||||
|
] |
||||
@ -0,0 +1,529 @@ |
|||||
|
def doc_upload_transaction_receipts(): |
||||
|
return """ |
||||
|
# 🐈 Scenario |
||||
|
🛠️ آپلود رسید پرداخت برای تراکنش |
||||
|
|
||||
|
این API برای آپلود یک یا چند رسید پرداخت برای یک تراکنش استفاده میشود. |
||||
|
پس از آپلود موفقیتآمیز، وضعیت تراکنش به 'waiting_approval' (در انتظار تایید) تغییر میکند. |
||||
|
|
||||
|
--- |
||||
|
|
||||
|
## 🚀 روند آپلود (دو مرحلهای) |
||||
|
|
||||
|
### مرحله 1️⃣: آپلود فایل به سرور موقت |
||||
|
ابتدا باید فایلهای خود را به endpoint زیر آپلود کنید: |
||||
|
|
||||
|
``` |
||||
|
POST /upload-tmp-media/ |
||||
|
Content-Type: multipart/form-data |
||||
|
|
||||
|
Body: |
||||
|
- file: [فایل رسید] |
||||
|
``` |
||||
|
|
||||
|
**پاسخ:** |
||||
|
```json |
||||
|
{ |
||||
|
"url": "/static/tmp/xyz123-receipt.jpg", |
||||
|
"name": "receipt.jpg", |
||||
|
"size": "1024000", |
||||
|
"mime_type": "image/jpeg" |
||||
|
} |
||||
|
``` |
||||
|
|
||||
|
### مرحله 2️⃣: ثبت URL فایلها در تراکنش |
||||
|
سپس URL های دریافتی را به این endpoint ارسال کنید: |
||||
|
|
||||
|
``` |
||||
|
POST /api/transactions/<transaction_id>/receipts/upload/ |
||||
|
Content-Type: application/json |
||||
|
``` |
||||
|
|
||||
|
--- |
||||
|
|
||||
|
## 🚀 درخواست API (مرحله 2) |
||||
|
|
||||
|
### URL: |
||||
|
``` |
||||
|
POST /api/transactions/<transaction_id>/receipts/upload/ |
||||
|
``` |
||||
|
|
||||
|
### پارامترهای URL: |
||||
|
| کلید | نوع داده | توضیحات | |
||||
|
|------------------|-----------|----------------------------------------------------------| |
||||
|
| `transaction_id` | Integer | شناسه تراکنش که میخواهید رسید برای آن ثبت کنید | |
||||
|
|
||||
|
### پارامترهای درخواست (JSON Body): |
||||
|
| کلید | نوع داده | الزامی | توضیحات | |
||||
|
|---------------|-----------|--------|----------------------------------------------------------| |
||||
|
| `files` | String[] | بله | لیست URL های فایلهای آپلود شده از مرحله 1 (حداکثر 10 فایل) | |
||||
|
| `description` | String | خیر | توضیحات اختیاری درباره رسیدها | |
||||
|
|
||||
|
--- |
||||
|
|
||||
|
## 💡 نکات مهم: |
||||
|
1. **روند دو مرحلهای**: |
||||
|
- **مرحله 1**: ابتدا فایلها را به `/upload-tmp-media/` آپلود کنید |
||||
|
- **مرحله 2**: سپس URL های دریافتی را به این API ارسال کنید |
||||
|
|
||||
|
2. **محدودیت فایلها**: |
||||
|
- حداکثر 10 فایل میتوانید در هر درخواست ثبت کنید |
||||
|
|
||||
|
3. **وضعیت تراکنش**: |
||||
|
- فقط میتوانید برای تراکنشهایی با وضعیت 'pending' یا 'waiting_approval' رسید آپلود کنید |
||||
|
- پس از ثبت موفقیتآمیز، وضعیت تراکنش به 'waiting_approval' تغییر میکند |
||||
|
|
||||
|
4. **احراز هویت**: |
||||
|
- باید توکن احراز هویت را در هدر درخواست ارسال کنید |
||||
|
- فقط میتوانید برای تراکنشهای خودتان رسید آپلود کنید |
||||
|
|
||||
|
--- |
||||
|
|
||||
|
## 📊 پاسخها |
||||
|
|
||||
|
| کد وضعیت | توضیحات | |
||||
|
|---------------|-----------------------------------------------------------| |
||||
|
| `201` | موفقیتآمیز - رسیدها با موفقیت ثبت شدند | |
||||
|
| `400` | دادههای نامعتبر یا تراکنش قادر به دریافت رسید نیست | |
||||
|
| `403` | عدم دسترسی - شما صاحب این تراکنش نیستید | |
||||
|
| `404` | تراکنش یافت نشد | |
||||
|
|
||||
|
--- |
||||
|
|
||||
|
## 📄 نمونه درخواست کامل (JSON): |
||||
|
|
||||
|
```json |
||||
|
{ |
||||
|
"files": [ |
||||
|
"/static/tmp/xyz123-receipt1.jpg", |
||||
|
"/static/tmp/abc456-receipt2.jpg" |
||||
|
], |
||||
|
"description": "Payment receipt for Python course" |
||||
|
} |
||||
|
``` |
||||
|
|
||||
|
--- |
||||
|
|
||||
|
## 📄 نمونه پاسخ موفقیتآمیز |
||||
|
|
||||
|
```json |
||||
|
{ |
||||
|
"success": true, |
||||
|
"message": "Receipts uploaded successfully", |
||||
|
"transaction_status": "waiting_approval", |
||||
|
"receipts": [ |
||||
|
{ |
||||
|
"id": 1, |
||||
|
"file": "http://example.com/media/receipts/1/receipt1.jpg", |
||||
|
"description": "Payment receipt for course enrollment", |
||||
|
"uploaded_at": "2025-12-03T10:30:00Z" |
||||
|
}, |
||||
|
{ |
||||
|
"id": 2, |
||||
|
"file": "http://example.com/media/receipts/1/receipt2.jpg", |
||||
|
"description": "Payment receipt for course enrollment", |
||||
|
"uploaded_at": "2025-12-03T10:30:05Z" |
||||
|
} |
||||
|
] |
||||
|
} |
||||
|
``` |
||||
|
|
||||
|
--- |
||||
|
|
||||
|
## 📄 نمونه درخواست کامل (cURL): |
||||
|
|
||||
|
### مرحله 1 - آپلود فایل: |
||||
|
```bash |
||||
|
curl -X POST \\ |
||||
|
'http://your-api.com/upload-tmp-media/' \\ |
||||
|
-H 'Authorization: Bearer YOUR_ACCESS_TOKEN' \\ |
||||
|
-F 'file=@/path/to/receipt1.jpg' |
||||
|
``` |
||||
|
|
||||
|
### مرحله 2 - ثبت رسید: |
||||
|
```bash |
||||
|
curl -X POST \\ |
||||
|
'http://your-api.com/api/transactions/123/receipts/upload/' \\ |
||||
|
-H 'Authorization: Bearer YOUR_ACCESS_TOKEN' \\ |
||||
|
-H 'Content-Type: application/json' \\ |
||||
|
-d '{ |
||||
|
"files": ["/static/tmp/xyz123-receipt1.jpg"], |
||||
|
"description": "Payment receipt for Python course" |
||||
|
}' |
||||
|
``` |
||||
|
|
||||
|
--- |
||||
|
|
||||
|
## 📄 نمونه پاسخ خطا (403 - عدم دسترسی): |
||||
|
|
||||
|
```json |
||||
|
{ |
||||
|
"message": "You don't have permission to upload receipts for this transaction" |
||||
|
} |
||||
|
``` |
||||
|
|
||||
|
--- |
||||
|
|
||||
|
## 📄 نمونه پاسخ خطا (400 - وضعیت نامعتبر): |
||||
|
|
||||
|
```json |
||||
|
{ |
||||
|
"message": "Cannot upload receipts for transaction with status 'success'" |
||||
|
} |
||||
|
``` |
||||
|
""" |
||||
|
|
||||
|
|
||||
|
def doc_list_transaction_receipts(): |
||||
|
return """ |
||||
|
# 🐈 Scenario |
||||
|
🛠️ لیست رسیدهای پرداخت یک تراکنش |
||||
|
|
||||
|
این API برای دریافت لیست تمام رسیدهای آپلود شده برای یک تراکنش خاص استفاده میشود. |
||||
|
|
||||
|
--- |
||||
|
|
||||
|
## 🚀 درخواست API |
||||
|
|
||||
|
### URL: |
||||
|
``` |
||||
|
GET /api/transactions/<transaction_id>/receipts/ |
||||
|
``` |
||||
|
|
||||
|
### پارامترهای URL: |
||||
|
| کلید | نوع داده | توضیحات | |
||||
|
|------------------|-----------|----------------------------------------------------------| |
||||
|
| `transaction_id` | Integer | شناسه تراکنش که میخواهید رسیدهای آن را مشاهده کنید | |
||||
|
|
||||
|
--- |
||||
|
|
||||
|
## 💡 نکات مهم: |
||||
|
1. **احراز هویت**: |
||||
|
- باید توکن احراز هویت را در هدر درخواست ارسال کنید |
||||
|
- فقط میتوانید رسیدهای تراکنشهای خودتان را مشاهده کنید |
||||
|
|
||||
|
2. **مرتبسازی**: |
||||
|
- رسیدها بر اساس تاریخ آپلود (جدیدترین اول) مرتب میشوند |
||||
|
|
||||
|
--- |
||||
|
|
||||
|
## 📊 پاسخها |
||||
|
|
||||
|
| کد وضعیت | توضیحات | |
||||
|
|---------------|-----------------------------------------------------------| |
||||
|
| `200` | موفقیتآمیز - لیست رسیدها بازگردانده شد | |
||||
|
| `403` | عدم دسترسی - شما صاحب این تراکنش نیستید | |
||||
|
| `404` | تراکنش یافت نشد | |
||||
|
|
||||
|
--- |
||||
|
|
||||
|
## 📄 نمونه پاسخ موفقیتآمیز |
||||
|
|
||||
|
```json |
||||
|
[ |
||||
|
{ |
||||
|
"id": 1, |
||||
|
"file": "http://example.com/media/receipts/1/receipt1.jpg", |
||||
|
"description": "Payment receipt for course enrollment", |
||||
|
"uploaded_at": "2025-12-03T10:30:00Z" |
||||
|
}, |
||||
|
{ |
||||
|
"id": 2, |
||||
|
"file": "http://example.com/media/receipts/1/receipt2.jpg", |
||||
|
"description": "Second payment receipt", |
||||
|
"uploaded_at": "2025-12-03T10:25:00Z" |
||||
|
} |
||||
|
] |
||||
|
``` |
||||
|
|
||||
|
--- |
||||
|
|
||||
|
## 📄 توضیحات مقادیر پاسخ |
||||
|
|
||||
|
| کلید | نوع داده | توضیحات | |
||||
|
|---------------|------------|----------------------------------------------------------| |
||||
|
| `id` | Integer | شناسه یکتای رسید | |
||||
|
| `file` | String | URL کامل فایل رسید آپلود شده | |
||||
|
| `description` | String | توضیحات اختیاری درباره رسید (ممکن است خالی باشد) | |
||||
|
| `uploaded_at` | DateTime | تاریخ و زمان آپلود رسید | |
||||
|
|
||||
|
--- |
||||
|
|
||||
|
## 📄 نمونه درخواست (cURL): |
||||
|
|
||||
|
```bash |
||||
|
curl -X GET \\ |
||||
|
'http://your-api.com/api/transactions/123/receipts/' \\ |
||||
|
-H 'Authorization: Bearer YOUR_ACCESS_TOKEN' |
||||
|
``` |
||||
|
|
||||
|
--- |
||||
|
|
||||
|
## 📄 نمونه پاسخ خطا (403 - عدم دسترسی): |
||||
|
|
||||
|
```json |
||||
|
{ |
||||
|
"message": "You don't have permission to view receipts for this transaction" |
||||
|
} |
||||
|
``` |
||||
|
|
||||
|
--- |
||||
|
|
||||
|
## 📄 نمونه پاسخ خطا (404 - تراکنش یافت نشد): |
||||
|
|
||||
|
```json |
||||
|
{ |
||||
|
"message": "Transaction not found" |
||||
|
} |
||||
|
``` |
||||
|
""" |
||||
|
|
||||
|
|
||||
|
def doc_transaction_list(): |
||||
|
return """ |
||||
|
# 🐈 Scenario |
||||
|
🛠️ لیست تراکنشهای کاربر |
||||
|
|
||||
|
این API برای دریافت لیست تمام تراکنشهای کاربر احراز هویت شده استفاده میشود. |
||||
|
|
||||
|
--- |
||||
|
|
||||
|
## 🚀 درخواست API |
||||
|
|
||||
|
### URL: |
||||
|
``` |
||||
|
GET /api/transactions/list/ |
||||
|
``` |
||||
|
|
||||
|
--- |
||||
|
|
||||
|
## 💡 نکات مهم: |
||||
|
1. **احراز هویت**: |
||||
|
- باید توکن احراز هویت را در هدر درخواست ارسال کنید |
||||
|
- فقط تراکنشهای خودتان را مشاهده میکنید |
||||
|
|
||||
|
2. **فیلترینگ خودکار**: |
||||
|
- تراکنشهای حذف شده (soft deleted) نمایش داده نمیشوند |
||||
|
|
||||
|
3. **وضعیتهای تراکنش**: |
||||
|
- `pending`: در انتظار پرداخت |
||||
|
- `waiting_approval`: در انتظار تایید (رسید آپلود شده) |
||||
|
- `success`: پرداخت موفق و تایید شده |
||||
|
- `failed`: پرداخت ناموفق |
||||
|
|
||||
|
--- |
||||
|
|
||||
|
## 📊 پاسخها |
||||
|
|
||||
|
| کد وضعیت | توضیحات | |
||||
|
|---------------|-----------------------------------------------------------| |
||||
|
| `200` | موفقیتآمیز - لیست تراکنشها بازگردانده شد | |
||||
|
| `401` | عدم احراز هویت | |
||||
|
|
||||
|
--- |
||||
|
|
||||
|
## 📄 توضیحات مقادیر پاسخ |
||||
|
|
||||
|
| کلید | نوع داده | توضیحات | |
||||
|
|---------------|------------|----------------------------------------------------------| |
||||
|
| `id` | Integer | شناسه یکتای تراکنش | |
||||
|
| `course` | Object | اطلاعات دوره مرتبط با تراکنش | |
||||
|
| `status` | String | وضعیت تراکنش (pending, waiting_approval, success, failed) | |
||||
|
| `price` | Decimal | مبلغ تراکنش | |
||||
|
| `created_at` | DateTime | تاریخ و زمان ایجاد تراکنش | |
||||
|
| `updated_at` | DateTime | تاریخ و زمان آخرین بهروزرسانی تراکنش | |
||||
|
|
||||
|
--- |
||||
|
|
||||
|
## 📄 نمونه پاسخ موفقیتآمیز |
||||
|
|
||||
|
```json |
||||
|
[ |
||||
|
{ |
||||
|
"id": 1, |
||||
|
"course": { |
||||
|
"id": 5, |
||||
|
"title": "Python Programming Basics", |
||||
|
"slug": "python-programming-basics", |
||||
|
"thumbnail": "http://example.com/media/courses/thumbnails/python.jpg", |
||||
|
"price": "99.00", |
||||
|
"final_price": "79.00" |
||||
|
}, |
||||
|
"status": "waiting_approval", |
||||
|
"price": "79.00", |
||||
|
"created_at": "2025-12-01T10:00:00Z", |
||||
|
"updated_at": "2025-12-03T10:30:00Z" |
||||
|
}, |
||||
|
{ |
||||
|
"id": 2, |
||||
|
"course": { |
||||
|
"id": 8, |
||||
|
"title": "Django Web Development", |
||||
|
"slug": "django-web-development", |
||||
|
"thumbnail": "http://example.com/media/courses/thumbnails/django.jpg", |
||||
|
"price": "149.00", |
||||
|
"final_price": "149.00" |
||||
|
}, |
||||
|
"status": "success", |
||||
|
"price": "149.00", |
||||
|
"created_at": "2025-11-28T14:20:00Z", |
||||
|
"updated_at": "2025-11-29T09:15:00Z" |
||||
|
} |
||||
|
] |
||||
|
``` |
||||
|
|
||||
|
--- |
||||
|
|
||||
|
## 📄 نمونه درخواست (cURL): |
||||
|
|
||||
|
```bash |
||||
|
curl -X GET \\ |
||||
|
'http://your-api.com/api/transactions/list/' \\ |
||||
|
-H 'Authorization: Bearer YOUR_ACCESS_TOKEN' |
||||
|
``` |
||||
|
""" |
||||
|
|
||||
|
|
||||
|
def doc_create_transaction(): |
||||
|
return """ |
||||
|
# 🐈 Scenario |
||||
|
🛠️ ثبتنام در دوره و ایجاد تراکنش |
||||
|
|
||||
|
این API برای ثبتنام کاربر در یک دوره و ایجاد تراکنش استفاده میشود. |
||||
|
|
||||
|
--- |
||||
|
|
||||
|
## 🚀 درخواست API |
||||
|
|
||||
|
### URL: |
||||
|
``` |
||||
|
POST /api/transactions/<slug>/join/ |
||||
|
``` |
||||
|
|
||||
|
### پارامترهای URL: |
||||
|
| کلید | نوع داده | توضیحات | |
||||
|
|---------|-----------|----------------------------------------------------------| |
||||
|
| `slug` | String | اسلاگ دورهای که میخواهید در آن ثبتنام کنید | |
||||
|
|
||||
|
### پارامترهای درخواست (JSON Body): |
||||
|
| کلید | نوع داده | الزامی | توضیحات | |
||||
|
|---------------------|-----------|--------|----------------------------------------------------------| |
||||
|
| `participant_infos` | Array | بله | لیست اطلاعات شرکتکنندگان | |
||||
|
|
||||
|
### ساختار `participant_infos`: |
||||
|
| کلید | نوع داده | الزامی | توضیحات | |
||||
|
|---------------|-----------|--------|----------------------------------------------------------| |
||||
|
| `fullname` | String | بله | نام کامل شرکتکننده | |
||||
|
| `email` | String | بله | ایمیل شرکتکننده (برای دوره رایگان باید با ایمیل کاربر احراز هویت شده یکسان باشد) | |
||||
|
| `phone_number`| String | خیر | شماره تلفن شرکتکننده | |
||||
|
| `gender` | String | خیر | جنسیت شرکتکننده (male, female) | |
||||
|
| `birthdate` | Date | خیر | تاریخ تولد شرکتکننده (فرمت: YYYY-MM-DD) | |
||||
|
|
||||
|
--- |
||||
|
|
||||
|
## 💡 نکات مهم: |
||||
|
1. **دوره رایگان**: |
||||
|
- اگر دوره رایگان باشد و فقط یک شرکتکننده در لیست باشد و ایمیل او با کاربر احراز هویت شده یکسان باشد، تراکنش به صورت خودکار تایید میشود (status = 'success') |
||||
|
- کاربر به صورت خودکار به عنوان دانشجو در دوره ثبت میشود |
||||
|
|
||||
|
2. **دوره پولی**: |
||||
|
- تراکنش با وضعیت 'pending' ایجاد میشود |
||||
|
- کاربر باید رسید پرداخت خود را آپلود کند |
||||
|
- پس از آپلود رسید، وضعیت به 'waiting_approval' تغییر میکند |
||||
|
- پس از تایید توسط ادمین، وضعیت به 'success' تغییر میکند |
||||
|
|
||||
|
3. **احراز هویت**: |
||||
|
- باید توکن احراز هویت را در هدر درخواست ارسال کنید |
||||
|
|
||||
|
--- |
||||
|
|
||||
|
## 📊 پاسخها |
||||
|
|
||||
|
| کد وضعیت | توضیحات | |
||||
|
|---------------|-----------------------------------------------------------| |
||||
|
| `201` | موفقیتآمیز - تراکنش ایجاد شد | |
||||
|
| `400` | دادههای نامعتبر | |
||||
|
| `404` | دوره یافت نشد | |
||||
|
|
||||
|
--- |
||||
|
|
||||
|
## 📄 نمونه درخواست (JSON Body): |
||||
|
|
||||
|
```json |
||||
|
{ |
||||
|
"participant_infos": [ |
||||
|
{ |
||||
|
"fullname": "علی رضایی", |
||||
|
"email": "ali@example.com", |
||||
|
"phone_number": "+989123456789", |
||||
|
"gender": "male", |
||||
|
"birthdate": "1995-05-15" |
||||
|
} |
||||
|
] |
||||
|
} |
||||
|
``` |
||||
|
|
||||
|
--- |
||||
|
|
||||
|
## 📄 نمونه پاسخ موفقیتآمیز (دوره رایگان): |
||||
|
|
||||
|
```json |
||||
|
{ |
||||
|
"message": "Transaction Participant created successfully.", |
||||
|
"transaction_id": 123, |
||||
|
"participant_infos": [ |
||||
|
{ |
||||
|
"fullname": "علی رضایی", |
||||
|
"email": "ali@example.com", |
||||
|
"phone_number": "+989123456789", |
||||
|
"gender": "male", |
||||
|
"birthdate": "1995-05-15" |
||||
|
} |
||||
|
] |
||||
|
} |
||||
|
``` |
||||
|
|
||||
|
--- |
||||
|
|
||||
|
## 📄 نمونه پاسخ موفقیتآمیز (دوره پولی): |
||||
|
|
||||
|
```json |
||||
|
{ |
||||
|
"message": "Transaction Participant created successfully.", |
||||
|
"transaction_id": 124, |
||||
|
"participant_infos": [ |
||||
|
{ |
||||
|
"fullname": "سارا احمدی", |
||||
|
"email": "sara@example.com", |
||||
|
"phone_number": "+989123456789", |
||||
|
"gender": "female", |
||||
|
"birthdate": "1998-03-20" |
||||
|
} |
||||
|
] |
||||
|
} |
||||
|
``` |
||||
|
|
||||
|
توجه: برای دوره پولی، شما باید با استفاده از `transaction_id` بازگشتی، رسید پرداخت خود را از طریق API آپلود رسید آپلود کنید. |
||||
|
|
||||
|
--- |
||||
|
|
||||
|
## 📄 نمونه درخواست (cURL): |
||||
|
|
||||
|
```bash |
||||
|
curl -X POST \\ |
||||
|
'http://your-api.com/api/transactions/python-programming-basics/join/' \\ |
||||
|
-H 'Authorization: Bearer YOUR_ACCESS_TOKEN' \\ |
||||
|
-H 'Content-Type: application/json' \\ |
||||
|
-d '{ |
||||
|
"participant_infos": [ |
||||
|
{ |
||||
|
"fullname": "علی رضایی", |
||||
|
"email": "ali@example.com", |
||||
|
"phone_number": "+989123456789", |
||||
|
"gender": "male", |
||||
|
"birthdate": "1995-05-15" |
||||
|
} |
||||
|
] |
||||
|
}' |
||||
|
``` |
||||
|
""" |
||||
@ -0,0 +1,35 @@ |
|||||
|
# Generated by Django 5.1.8 on 2025-12-03 23:32 |
||||
|
|
||||
|
import apps.transaction.models |
||||
|
import django.db.models.deletion |
||||
|
from django.db import migrations, models |
||||
|
|
||||
|
|
||||
|
class Migration(migrations.Migration): |
||||
|
|
||||
|
dependencies = [ |
||||
|
('transaction', '0002_remove_transactionparticipant_is_paid_and_more'), |
||||
|
] |
||||
|
|
||||
|
operations = [ |
||||
|
migrations.AlterField( |
||||
|
model_name='transactionparticipant', |
||||
|
name='status', |
||||
|
field=models.CharField(choices=[('pending', 'Pending'), ('waiting_approval', 'Waiting for Approval'), ('success', 'Success'), ('failed', 'Failed')], default='pending', max_length=20, verbose_name='Transaction Status'), |
||||
|
), |
||||
|
migrations.CreateModel( |
||||
|
name='TransactionReceipt', |
||||
|
fields=[ |
||||
|
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), |
||||
|
('file', models.FileField(help_text='Upload payment receipt image or document', upload_to=apps.transaction.models.receipt_file_upload_to, verbose_name='Receipt File')), |
||||
|
('uploaded_at', models.DateTimeField(auto_now_add=True, verbose_name='Uploaded At')), |
||||
|
('description', models.TextField(blank=True, help_text='Optional description or notes about the receipt', null=True, verbose_name='Description')), |
||||
|
('transaction', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='receipts', to='transaction.transactionparticipant', verbose_name='Transaction')), |
||||
|
], |
||||
|
options={ |
||||
|
'verbose_name': 'Transaction Receipt', |
||||
|
'verbose_name_plural': 'Transaction Receipts', |
||||
|
'ordering': ['-uploaded_at'], |
||||
|
}, |
||||
|
), |
||||
|
] |
||||
Write
Preview
Loading…
Cancel
Save
Reference in new issue