feat: باشگاه امتیازات کارکنان (موتور امتیاز، جدول رتبه، فروشگاه پاداش، نشان‌ها، پنل مدیریت و گزارش ROI)

- موتور رویدادمحور با شرط، محدودیت، تأیید مدیر و idempotency
- اتصال به لید، مشتری، معامله، فعالیت، روتین، پیش‌فاکتور، فاکتور و تیکت
- صفحه /club و /club/admin، اعلان زنده امتیاز، آیتم منو
- انتقال فرم‌ساز سرنخ به ابزارها

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-10-10 21:28:49 +03:30
co-authored by Cursor
parent b87ebb22e0
commit 60d797f184
51 changed files with 11298 additions and 806 deletions
+23 -1
View File
@@ -21,6 +21,7 @@ import { AutomationsService } from '../automations/automations.service';
import { MessageAutomationsService } from '../message-automations/message-automations.service';
import { InventoryService } from '../inventory/inventory.service';
import { CommissionsService } from '../finance/commissions.service';
import { GamificationService } from '../gamification/gamification.service';
type InvoiceActor = Pick<Actor, 'userId' | 'role'>;
@@ -52,6 +53,7 @@ export class InvoicesService {
private readonly messageAutomations: MessageAutomationsService,
private readonly inventory: InventoryService,
private readonly commissions: CommissionsService,
private readonly game: GamificationService,
) {}
async list(
@@ -477,7 +479,7 @@ export class InvoicesService {
}
}
await this.prisma.$transaction(async (tx) => {
const paymentId = await this.prisma.$transaction(async (tx) => {
const payment = await tx.payment.create({
data: {
invoiceId,
@@ -525,6 +527,7 @@ export class InvoicesService {
data: { status: 'issued', issuedAt: new Date() },
});
}
return payment.id;
});
await this.recomputeStatus(invoiceId);
@@ -546,6 +549,16 @@ export class InvoicesService {
};
await this.automations.runTrigger('invoice_paid', paidCtx);
await this.messageAutomations.onEvent('invoice_paid', paidCtx);
this.game.emit({
organizationId,
userId: actor.userId,
event: 'PAYMENT_REGISTERED',
entityType: 'invoice',
entityId: row.id,
entityTitle: paidCtx.title,
eventKey: paymentId,
facts: { amount: dto.amount },
});
return row;
}
@@ -666,6 +679,15 @@ export class InvoicesService {
};
await this.automations.runTrigger('invoice_issued', ctx);
await this.messageAutomations.onEvent('invoice_issued', ctx);
this.game.emit({
organizationId,
userId: row.owner?.id,
event: 'INVOICE_ISSUED',
entityType: 'invoice',
entityId: row.id,
entityTitle: ctx.title,
facts: { amount: row.payableAmount },
});
}
private async ensureExists(