# پایگاه داده — تسک ۱۵: ماژول پرداخت ## جدول: payments _(entity_type=payment, bundle=appointment — از DB backup تأیید شده)_ | ستون | نوع | نام Drupal | توضیح | |------|-----|-----------|-------| | id | INT UNSIGNED AUTO_INCREMENT PK | id | | | uuid | CHAR(36) UNIQUE NOT NULL | uuid | | | user_id | INT FK → users.id NOT NULL | uid | پرداخت‌کننده | | appointment_id | INT FK → appointments.id UNIQUE NULL | field_reference_id | entity ref → appointment | | representation_id | INT FK → representations.id NULL | field_representation | entity ref → clinic_pro | | amount | INT NOT NULL | field_amount | مبلغ به **ریال** (نه تومان) — تایپ INT | | status | VARCHAR(20) DEFAULT 'pending' | field_status | وضعیت | | payment_method | VARCHAR(20) NULL | field_payment_method | روش پرداخت | | ref_id | VARCHAR(100) NULL | field_ref_id | SaleReferenceId بانک | | frontend_address | VARCHAR(150) NULL | field_frontend_address | URL فرانت برای redirect | | payment_time | INT NULL | field_payment_time | زمان پرداخت (Unix timestamp) | | card_info | LONGTEXT NULL | field_card_info | اطلاعات کارت (JSON/text) | | created_at | INT NOT NULL | created | Unix timestamp | | updated_at | INT NOT NULL | changed | Unix timestamp | ## وضعیت‌های پرداخت (field_status) — از config ``` pending → ایجاد شده، منتظر پرداخت received → پرداخت موفق تأیید شده ⚠️ نه 'paid'! refund → مبلغ برگشت خورده canceled → لغو شده (نه 'failed') ``` ## روش‌های پرداخت (field_payment_method) — از config ``` mellat → بانک ملت (SOAP) sep → بانک سامان (SEP) ``` ## نمونه داده واقعی از DB backup ``` id=2, uid=33, amount=100000 (ریال), status=pending, method=mellat frontend_address='http://yasuj-nobat.localhost:3000/' ``` ## ایندکس‌ها ```sql CREATE UNIQUE INDEX idx_payments_appointment ON payments(appointment_id); CREATE INDEX idx_payments_user ON payments(user_id); CREATE INDEX idx_payments_status ON payments(status); CREATE INDEX idx_payments_representation ON payments(representation_id); CREATE INDEX idx_payments_ref_id ON payments(ref_id); ``` ## وابستگی وضعیت appointment ``` appointments.status = 'waiting_for_payment' → پیش‌نیاز ایجاد payment بعد از پرداخت موفق: payments.status = 'received' appointments.status = 'reserved' payment_time = Unix timestamp الان ``` ## نکات مهم - `amount` نوع **INT** است (نه DECIMAL) — از DB backup تأیید شد (مثال: 100000) - مبلغ در **ریال** ذخیره می‌شود - `field_reference_id` → entity reference به appointment (نه foreign key مستقیم در جدول payment) - `frontend_address` برای redirect بعد از پرداخت به سایت نماینده است - `card_info` برای ذخیره اطلاعات کارت بانکی (مثلاً شماره کارت ماسک‌شده) --- ## جدول: subscription_payments (پرداخت اشتراک) _(از بخش ۲.۱۰.۲ مستند — نوع پرداخت مجزا از پرداخت نوبت)_ | ستون | نوع | توضیح | |------|-----|-------| | id | INT UNSIGNED AUTO_INCREMENT PK | | | uuid | CHAR(36) UNIQUE NOT NULL | | | user_id | INT FK → users.id NOT NULL | کاربر سابسکرایب‌کننده | | reference_type | VARCHAR(10) NOT NULL | `doctor` یا `clinic` | | reference_id | INT NOT NULL | FK به doctors.id یا clinics.id | | representation_id | INT FK → representations.id NULL | نماینده (در صورت وجود) | | amount | INT NOT NULL | مبلغ اشتراک (ریال) | | payment_method | VARCHAR(20) NULL | روش پرداخت (mellat, sep, ...) | | payment_time | INT NULL | زمان پرداخت (Unix timestamp) | | start_date | INT NOT NULL | تاریخ شروع اشتراک (Unix timestamp) | | expiration_date | INT NOT NULL | تاریخ انقضای اشتراک (Unix timestamp) | | ref_id | VARCHAR(100) NULL | شماره مرجع درگاه بانکی | | card_info | LONGTEXT NULL | اطلاعات کارت بانکی (JSON) | | frontend_address | VARCHAR(150) NULL | آدرس بازگشت پس از پرداخت | | status | VARCHAR(20) DEFAULT 'pending' | pending \| received \| refund \| canceled | | created_at | INT NOT NULL | Unix timestamp | | updated_at | INT NOT NULL | Unix timestamp | ## ایندکس‌های subscription_payments ```sql CREATE INDEX idx_sub_payments_user ON subscription_payments(user_id); CREATE INDEX idx_sub_payments_ref ON subscription_payments(reference_type, reference_id); CREATE INDEX idx_sub_payments_status ON subscription_payments(status); CREATE INDEX idx_sub_payments_expiry ON subscription_payments(expiration_date); ``` ## تفاوت payments و subscription_payments | ویژگی | payments | subscription_payments | |-------|----------|----------------------| | مرجع | `appointment_id` | `reference_id` → doctor/clinic | | فیلدهای اضافه | — | `start_date`, `expiration_date` | | هدف | پرداخت نوبت | خرید اشتراک پلن |