feat: unremitted per-user filtering, EOD unremitted reminders, remittance breakdown
- Filter unremitted payments by current user only (remove manager exception) - Add PaymentScheduler with 5PM daily cron for unremitted reminders - Add getUnremittedBreakdown service for per-collector dashboard totals - Register PaymentScheduler in SchedulerModule
This commit is contained in:
@@ -42,10 +42,8 @@ export class PaymentController {
|
||||
|
||||
@Get('unremitted')
|
||||
@Roles('technician', 'collector')
|
||||
async getUnremitted(@CurrentUser() user: CurrentUserPayload, @Query('all') all?: string) {
|
||||
const isManager = user.roles?.some((r: string) => ['manager', 'tenant_admin', 'super_admin'].includes(r));
|
||||
// Managers see all unremitted; collectors see only their own
|
||||
return this.paymentService.getUnremittedPayments(user.tenantId, isManager ? null : user.sub);
|
||||
async getUnremitted(@CurrentUser() user: CurrentUserPayload) {
|
||||
return this.paymentService.getUnremittedPayments(user.tenantId, user.sub);
|
||||
}
|
||||
|
||||
@Get('remittances')
|
||||
@@ -80,4 +78,10 @@ export class PaymentController {
|
||||
) {
|
||||
return this.paymentService.rejectRemittance(user.tenantId, id, user.sub);
|
||||
}
|
||||
|
||||
@Get('unremitted-breakdown')
|
||||
@Roles('manager')
|
||||
async getUnremittedBreakdown(@CurrentUser() user: CurrentUserPayload) {
|
||||
return this.paymentService.getUnremittedBreakdown(user.tenantId);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -301,4 +301,36 @@ export class PaymentService {
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
async getUnremittedBreakdown(tenantId: string) {
|
||||
const remittedIds = (await this.prisma.remittancePayment.findMany({
|
||||
where: { remittance: { tenantId } },
|
||||
select: { paymentId: true },
|
||||
})).map((r) => r.paymentId);
|
||||
|
||||
const grouped = await this.prisma.payment.groupBy({
|
||||
by: ['collectedById'],
|
||||
where: {
|
||||
tenantId,
|
||||
id: { notIn: remittedIds.length > 0 ? remittedIds : ['none'] },
|
||||
collectedById: { not: null },
|
||||
},
|
||||
_sum: { amount: true },
|
||||
_count: true,
|
||||
});
|
||||
|
||||
const collectorIds = grouped.map((g) => g.collectedById!).filter(Boolean);
|
||||
const collectors = await this.prisma.user.findMany({
|
||||
where: { id: { in: collectorIds } },
|
||||
select: { id: true, firstName: true, lastName: true },
|
||||
});
|
||||
const nameMap = new Map(collectors.map((c) => [c.id, `${c.firstName} ${c.lastName}`]));
|
||||
|
||||
return grouped.map((g) => ({
|
||||
collectorId: g.collectedById,
|
||||
collectorName: nameMap.get(g.collectedById!) ?? 'Unknown',
|
||||
totalAmount: Number(g._sum.amount ?? 0),
|
||||
count: g._count,
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user