Files
2025-11-11 03:08:36 -03:00

244 lines
5.7 KiB
TypeScript

/**
* Queries de transactions (transações do sistema de escrow)
* Operações para a tabela transactions
*/
import { query } from "../index";
export interface Transaction {
transaction_id: number;
listing_id: number | null;
buyer_id: number;
seller_id: number;
item_name: string;
quantity: number;
server_name: string;
amount: number;
payment_method: "pix" | "tibia_coins" | "gold_coins" | null;
escrow_fee: number | null;
transaction_status:
| "pending"
| "deposited"
| "item_delivered"
| "completed"
| "disputed"
| "cancelled"
| "refunded";
created_at: Date;
deposited_at: Date | null;
delivered_at: Date | null;
completed_at: Date | null;
buyer_confirmed: boolean;
seller_confirmed: boolean;
buyer_notes: string | null;
seller_notes: string | null;
}
export interface CreateTransactionData {
listing_id?: number;
buyer_id: number;
seller_id: number;
item_name: string;
quantity: number;
server_name: string;
amount: number;
payment_method: "pix" | "tibia_coins" | "gold_coins";
escrow_fee?: number;
}
export interface UpdateTransactionStatusData {
transaction_status: Transaction["transaction_status"];
deposited_at?: Date;
delivered_at?: Date;
completed_at?: Date;
buyer_confirmed?: boolean;
seller_confirmed?: boolean;
buyer_notes?: string;
seller_notes?: string;
}
/**
* Cria uma nova transação
*/
export async function createTransaction(
data: CreateTransactionData,
): Promise<Transaction> {
// Calcular escrow_fee se não fornecido (2% do valor)
const escrowFee = data.escrow_fee ?? Number((data.amount * 0.02).toFixed(2));
const result = await query<Transaction>(
`
INSERT INTO transactions (
listing_id, buyer_id, seller_id, item_name, quantity,
server_name, amount, payment_method, escrow_fee
)
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)
RETURNING *
`,
[
data.listing_id || null,
data.buyer_id,
data.seller_id,
data.item_name,
data.quantity,
data.server_name,
data.amount,
data.payment_method,
escrowFee,
],
);
return result.rows[0];
}
/**
* Busca transação por ID
*/
export async function getTransactionById(
transactionId: number,
): Promise<Transaction | null> {
const result = await query<Transaction>(
`
SELECT * FROM transactions WHERE transaction_id = $1
`,
[transactionId],
);
return result.rows[0] || null;
}
/**
* Atualiza status da transação
*/
export async function updateTransactionStatus(
transactionId: number,
data: UpdateTransactionStatusData,
): Promise<Transaction | null> {
const updates: string[] = [];
const params: any[] = [];
let paramIndex = 1;
updates.push(`transaction_status = $${paramIndex}`);
params.push(data.transaction_status);
paramIndex++;
if (data.deposited_at !== undefined) {
updates.push(`deposited_at = $${paramIndex}`);
params.push(data.deposited_at);
paramIndex++;
}
if (data.delivered_at !== undefined) {
updates.push(`delivered_at = $${paramIndex}`);
params.push(data.delivered_at);
paramIndex++;
}
if (data.completed_at !== undefined) {
updates.push(`completed_at = $${paramIndex}`);
params.push(data.completed_at);
paramIndex++;
}
if (data.buyer_confirmed !== undefined) {
updates.push(`buyer_confirmed = $${paramIndex}`);
params.push(data.buyer_confirmed);
paramIndex++;
}
if (data.seller_confirmed !== undefined) {
updates.push(`seller_confirmed = $${paramIndex}`);
params.push(data.seller_confirmed);
paramIndex++;
}
if (data.buyer_notes !== undefined) {
updates.push(`buyer_notes = $${paramIndex}`);
params.push(data.buyer_notes);
paramIndex++;
}
if (data.seller_notes !== undefined) {
updates.push(`seller_notes = $${paramIndex}`);
params.push(data.seller_notes);
paramIndex++;
}
params.push(transactionId);
const result = await query<Transaction>(
`
UPDATE transactions
SET ${updates.join(", ")}
WHERE transaction_id = $${paramIndex}
RETURNING *
`,
params,
);
return result.rows[0] || null;
}
/**
* Busca transações de um usuário (comprador ou vendedor)
*/
export async function getTransactionsByUser(
userId: number,
filters: {
role?: "buyer" | "seller" | "both";
status?: Transaction["transaction_status"];
page?: number;
pageSize?: number;
} = {},
): Promise<{ transactions: Transaction[]; total: number }> {
const { role = "both", status, page = 1, pageSize = 20 } = filters;
const conditions: string[] = [];
const params: any[] = [];
let paramIndex = 1;
if (role === "buyer") {
conditions.push(`buyer_id = $${paramIndex}`);
} else if (role === "seller") {
conditions.push(`seller_id = $${paramIndex}`);
} else {
conditions.push(
`(buyer_id = $${paramIndex} OR seller_id = $${paramIndex})`,
);
}
params.push(userId);
paramIndex++;
if (status) {
conditions.push(`transaction_status = $${paramIndex}`);
params.push(status);
paramIndex++;
}
const whereClause =
conditions.length > 0 ? `WHERE ${conditions.join(" AND ")}` : "";
// Contar total
const countResult = await query<{ count: string }>(
`SELECT COUNT(*) as count FROM transactions ${whereClause}`,
params,
);
const total = parseInt(countResult.rows[0].count, 10);
// Buscar transações
const offset = (page - 1) * pageSize;
const result = await query<Transaction>(
`
SELECT * FROM transactions
${whereClause}
ORDER BY created_at DESC
LIMIT $${paramIndex} OFFSET $${paramIndex + 1}
`,
[...params, pageSize, offset],
);
return {
transactions: result.rows,
total,
};
}