Exclude client targets for soft-deleted clients
findAll and findById filter on client.deletedAt = null so targets belonging to a soft-deleted client are invisible. The create guard also rejects soft-deleted clients. The raw SQL balance query now excludes soft-deleted time entries and projects from tracked totals.
This commit is contained in:
@@ -68,7 +68,7 @@ export interface ClientTargetWithBalance {
|
|||||||
export class ClientTargetService {
|
export class ClientTargetService {
|
||||||
async findAll(userId: string): Promise<ClientTargetWithBalance[]> {
|
async findAll(userId: string): Promise<ClientTargetWithBalance[]> {
|
||||||
const targets = await prisma.clientTarget.findMany({
|
const targets = await prisma.clientTarget.findMany({
|
||||||
where: { userId },
|
where: { userId, client: { deletedAt: null } },
|
||||||
include: {
|
include: {
|
||||||
client: { select: { id: true, name: true } },
|
client: { select: { id: true, name: true } },
|
||||||
corrections: { orderBy: { date: 'asc' } },
|
corrections: { orderBy: { date: 'asc' } },
|
||||||
@@ -81,7 +81,7 @@ export class ClientTargetService {
|
|||||||
|
|
||||||
async findById(id: string, userId: string) {
|
async findById(id: string, userId: string) {
|
||||||
return prisma.clientTarget.findFirst({
|
return prisma.clientTarget.findFirst({
|
||||||
where: { id, userId },
|
where: { id, userId, client: { deletedAt: null } },
|
||||||
include: {
|
include: {
|
||||||
client: { select: { id: true, name: true } },
|
client: { select: { id: true, name: true } },
|
||||||
corrections: { orderBy: { date: 'asc' } },
|
corrections: { orderBy: { date: 'asc' } },
|
||||||
@@ -97,8 +97,8 @@ export class ClientTargetService {
|
|||||||
throw new BadRequestError('startDate must be a Monday');
|
throw new BadRequestError('startDate must be a Monday');
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ensure the client belongs to this user
|
// Ensure the client belongs to this user and is not soft-deleted
|
||||||
const client = await prisma.client.findFirst({ where: { id: data.clientId, userId } });
|
const client = await prisma.client.findFirst({ where: { id: data.clientId, userId, deletedAt: null } });
|
||||||
if (!client) {
|
if (!client) {
|
||||||
throw new NotFoundError('Client not found');
|
throw new NotFoundError('Client not found');
|
||||||
}
|
}
|
||||||
@@ -229,6 +229,8 @@ export class ClientTargetService {
|
|||||||
AND p.client_id = ${target.clientId}
|
AND p.client_id = ${target.clientId}
|
||||||
AND te.start_time >= ${periodStart}
|
AND te.start_time >= ${periodStart}
|
||||||
AND te.start_time <= ${periodEnd}
|
AND te.start_time <= ${periodEnd}
|
||||||
|
AND te.deleted_at IS NULL
|
||||||
|
AND p.deleted_at IS NULL
|
||||||
GROUP BY DATE_TRUNC('week', te.start_time AT TIME ZONE 'UTC')
|
GROUP BY DATE_TRUNC('week', te.start_time AT TIME ZONE 'UTC')
|
||||||
`);
|
`);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user