P3: payments + payouts (multi-country adapter pattern, wallet-integrated)

- payments: cash instant + gateway intent/redirect + webhook confirm; topup credits wallet
- payouts: driver request (holds wallet.debit) + admin complete/fail (fail refunds)
- tables tripz_pay_payments / tripz_pay_payouts (logical payment schema, extractable later)
- providers: cash/cliq/zaincash/syriatel/mtn/shamcash/paymob/fawry (structure ready, creds later)
- migration InitPayments; wired into app.module

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-07-16 19:05:49 +03:00
co-authored by Claude Opus 4.8
parent e0ccd2efb7
commit bb6a7bc7ec
9 changed files with 447 additions and 0 deletions
@@ -0,0 +1,64 @@
import {
Column,
CreateDateColumn,
Entity,
Index,
PrimaryGeneratedColumn,
UpdateDateColumn,
} from 'typeorm';
export type PaymentStatus = 'pending' | 'success' | 'failed' | 'refunded';
export type PaymentPurpose = 'topup' | 'trip';
/**
* معاملة دفع. الجدول: tripz_pay_payments («schema الدفع» منطقياً — قابل للفصل).
*/
@Entity('pay_payments')
@Index(['tenant_id', 'user_id'])
@Index(['tenant_id', 'status'])
export class Payment {
@PrimaryGeneratedColumn('uuid')
id: string;
@Column({ type: 'uuid' })
tenant_id: string;
@Column({ type: 'uuid' })
user_id: string;
@Column({ type: 'uuid', nullable: true })
trip_id: string | null;
@Column({ default: 'topup' })
purpose: PaymentPurpose;
@Column()
provider: string; // cash | cliq | zaincash | syriatel | mtn | shamcash | paymob | fawry
@Column({ type: 'varchar', nullable: true })
method: string | null;
@Column({ type: 'numeric', precision: 12, scale: 3 })
amount: number;
@Column({ default: 'JOD' })
currency: string;
@Column({ type: 'varchar', default: 'pending' })
status: PaymentStatus;
@Column({ type: 'varchar', nullable: true })
tx_ref: string | null;
@Column({ type: 'varchar', nullable: true })
redirect_url: string | null;
@Column({ type: 'jsonb', default: {} })
meta: Record<string, any>;
@CreateDateColumn()
created_at: Date;
@UpdateDateColumn()
updated_at: Date;
}