fix: mobile app bugs - payment screen, remittance isolation, invoice sorting, ticket creation

- Fix record payment screen fetching invoice directly instead of relying on collection provider
- Fix getUnremittedPayments tenant isolation (remittance tenantId filter)
- Add invoice status filter and dueDate sort support in controller/service
- Allow technicians to create tickets (role decorator fix)
- Enhance seed data with 10 more pending-installation clients and installation tickets
This commit is contained in:
kevin-asprec
2026-05-06 03:13:32 +08:00
parent 58d77fc67f
commit 58c01d4580
5 changed files with 38 additions and 7 deletions

View File

@@ -25,8 +25,9 @@ export class InvoiceController {
@CurrentUser() user: CurrentUserPayload,
@Query('clientId') clientId?: string,
@Query('status') status?: string,
@Query('sort') sort?: string,
) {
return this.invoiceService.findAll(user.tenantId, { clientId, status });
return this.invoiceService.findAll(user.tenantId, { clientId, status, sort });
}
@Get(':id')

View File

@@ -10,13 +10,23 @@ import { paginationArgs, paginatedResult } from '../common/dto/pagination.dto';
export class InvoiceService {
constructor(private readonly prisma: PrismaService) {}
async findAll(tenantId: string, filters?: { clientId?: string; status?: string; page?: number; limit?: number }) {
async findAll(tenantId: string, filters?: { clientId?: string; status?: string; sort?: string; page?: number; limit?: number }) {
const { skip, take, page, limit } = paginationArgs({ page: filters?.page, limit: filters?.limit });
const db = this.prisma.forTenant(tenantId);
const statusFilter = filters?.status
? (filters.status.includes(',') ? { in: filters.status.split(',') } : filters.status)
: undefined;
const where = {
...(filters?.clientId && { clientId: filters.clientId }),
...(filters?.status && { status: filters.status }),
...(statusFilter && { status: statusFilter }),
};
const orderBy = filters?.sort === 'dueDate:asc'
? { dueDate: 'asc' as const }
: { createdAt: 'desc' as const };
const [items, total] = await Promise.all([
db.invoice.findMany({
where,
@@ -26,7 +36,7 @@ export class InvoiceService {
client: { select: { id: true, firstName: true, lastName: true, accountNumber: true, phone: true, latitude: true, longitude: true } },
_count: { select: { payments: true } },
},
orderBy: { createdAt: 'desc' },
orderBy,
}),
db.invoice.count({ where }),
]);

View File

@@ -159,7 +159,10 @@ export class PaymentService {
}
async getUnremittedPayments(tenantId: string, collectorId: string) {
const remittedIds = (await this.prisma.remittancePayment.findMany({ select: { paymentId: true } }))
const remittedIds = (await this.prisma.remittancePayment.findMany({
where: { remittance: { tenantId } },
select: { paymentId: true },
}))
.map((r) => r.paymentId);
return this.prisma.payment.findMany({

View File

@@ -43,7 +43,7 @@ export class TicketController {
}
@Post()
@Roles('manager')
@Roles('technician')
async create(
@CurrentUser() user: CurrentUserPayload,
@Body() dto: CreateTicketDto,