Backend (Go): - FCM Push Notifications (fcm.go, push_handler.go) - Credit Lines (credit_line.go, credit_handler.go) - Payment Config (admin_handler.go, seller_payment_handler.go) - Team Management (team_handler.go) Backoffice (NestJS): - Dashboard module (KPIs, revenue charts) - Audit module (tracking changes) - Disputes module (CRUD, resolution) - Reports module (CSV export) - Performance module (seller scores) - Fraud module (detection, alerts) Frontend (Marketplace): - ThemeContext for Dark Mode - HelpCenter page with FAQ - OrderDetails with timeline - Team management page - Persistent cart (Zustand)
107 lines
3.3 KiB
TypeScript
107 lines
3.3 KiB
TypeScript
import { Injectable } from '@nestjs/common';
|
|
import { PrismaService } from '../prisma/prisma.service';
|
|
|
|
interface DisputeFilter {
|
|
page: number;
|
|
limit: number;
|
|
status?: string;
|
|
}
|
|
|
|
@Injectable()
|
|
export class DisputesService {
|
|
constructor(private prisma: PrismaService) { }
|
|
|
|
async list(filter: DisputeFilter) {
|
|
const offset = (filter.page - 1) * filter.limit;
|
|
let whereClause = '';
|
|
if (filter.status) {
|
|
whereClause = `WHERE status = '${filter.status}'`;
|
|
}
|
|
|
|
const disputes = await this.prisma.$queryRawUnsafe<any[]>(`
|
|
SELECT d.*,
|
|
o.id as order_id,
|
|
o.total_cents,
|
|
buyer.name as buyer_name,
|
|
seller.corporate_name as seller_name
|
|
FROM disputes d
|
|
LEFT JOIN orders o ON d.order_id = o.id
|
|
LEFT JOIN users buyer ON d.buyer_id = buyer.id
|
|
LEFT JOIN companies seller ON d.seller_id = seller.id
|
|
${whereClause}
|
|
ORDER BY d.created_at DESC
|
|
LIMIT ${filter.limit} OFFSET ${offset}
|
|
`);
|
|
|
|
const countResult = await this.prisma.$queryRawUnsafe<[{ count: bigint }]>(`
|
|
SELECT COUNT(*) as count FROM disputes ${whereClause}
|
|
`);
|
|
|
|
return {
|
|
disputes,
|
|
total: Number(countResult[0]?.count || 0),
|
|
page: filter.page,
|
|
limit: filter.limit,
|
|
};
|
|
}
|
|
|
|
async getById(id: string) {
|
|
const disputes = await this.prisma.$queryRaw<any[]>`
|
|
SELECT d.*,
|
|
o.id as order_id,
|
|
o.total_cents,
|
|
o.status as order_status,
|
|
buyer.name as buyer_name,
|
|
buyer.email as buyer_email,
|
|
seller.corporate_name as seller_name
|
|
FROM disputes d
|
|
LEFT JOIN orders o ON d.order_id = o.id
|
|
LEFT JOIN users buyer ON d.buyer_id = buyer.id
|
|
LEFT JOIN companies seller ON d.seller_id = seller.id
|
|
WHERE d.id = ${id}::uuid
|
|
`;
|
|
return disputes[0] || null;
|
|
}
|
|
|
|
async create(data: {
|
|
orderId: string;
|
|
buyerId: string;
|
|
sellerId: string;
|
|
reason: string;
|
|
description: string;
|
|
}) {
|
|
await this.prisma.$executeRaw`
|
|
INSERT INTO disputes (id, order_id, buyer_id, seller_id, reason, description, status, created_at, updated_at)
|
|
VALUES (
|
|
gen_random_uuid(),
|
|
${data.orderId}::uuid,
|
|
${data.buyerId}::uuid,
|
|
${data.sellerId}::uuid,
|
|
${data.reason},
|
|
${data.description},
|
|
'open',
|
|
NOW(),
|
|
NOW()
|
|
)
|
|
`;
|
|
return { status: 'created' };
|
|
}
|
|
|
|
async resolve(id: string, data: {
|
|
resolution: string;
|
|
refundAmountCents?: number;
|
|
notes: string;
|
|
}) {
|
|
await this.prisma.$executeRaw`
|
|
UPDATE disputes
|
|
SET status = 'resolved',
|
|
resolution = ${data.resolution},
|
|
refund_amount_cents = ${data.refundAmountCents || 0},
|
|
admin_notes = ${data.notes},
|
|
resolved_at = NOW(),
|
|
updated_at = NOW()
|
|
WHERE id = ${id}::uuid
|
|
`;
|
|
return { status: 'resolved' };
|
|
}
|
|
}
|