import { Entity, PrimaryGeneratedColumn, Column, CreateDateColumn, ManyToOne, Index, } from 'typeorm'; import { Wallet } from './Wallet'; import { Agent } from './Agent'; import { User } from './User'; export enum TransactionType { PURCHASE = 'purchase', // Buying points CHARGE = 'charge', // Charged for agent task REFUND = 'refund', // Refunded points FREE = 'free', // Free task ADMIN_TEST = 'admin_test', // Admin testing unapproved agents (no charge) } export enum TransactionStatus { PENDING = 'pending', COMPLETED = 'completed', FAILED = 'failed', } @Entity('transactions') @Index(['walletId', 'createdAt']) @Index(['userId', 'agentId']) export class Transaction { @PrimaryGeneratedColumn('uuid') id: string; @ManyToOne(() => Wallet, (wallet) => wallet.transactions) wallet: Wallet; @Column() walletId: string; @ManyToOne(() => User, { nullable: true }) user: User; @Column({ nullable: true }) userId?: string; @ManyToOne(() => Agent, { nullable: true }) agent: Agent; @Column({ nullable: true }) agentId?: string; @Column({ type: 'enum', enum: TransactionType, }) type: TransactionType; @Column({ type: 'enum', enum: TransactionStatus, default: TransactionStatus.PENDING, }) status: TransactionStatus; @Column('decimal', { precision: 15, scale: 2 }) amount: number; // Points amount (positive for purchases, negative for charges) @Column('decimal', { precision: 15, scale: 2, nullable: true }) balanceAfter: number; // Wallet balance after transaction @Column({ nullable: true }) description?: string; @Column({ nullable: true, unique: true }) paymentReference?: string; // Paystack reference for purchases (unique for idempotency) @Column('jsonb', { nullable: true }) metadata?: Record; @CreateDateColumn() createdAt: Date; }