Unified search algorithm across all lists; per-section record visibility (contacts, deals, activities, leads, finance, tickets, notes, projects)
This commit is contained in:
@@ -10,7 +10,8 @@ import type {
|
||||
} from '@mento/shared';
|
||||
import { Prisma } from '@prisma/client';
|
||||
import { PrismaService } from '../prisma/prisma.service';
|
||||
import { type Actor, elevated, ownerWhere } from '../common/record-scope';
|
||||
import { type ScopedActor, ownerWhere, scopedOwnerIds } from '../common/record-scope';
|
||||
import { buildSearchWhere, ci } from '../common/search';
|
||||
|
||||
const CHEQUE_STATUSES = ['pending', 'cleared', 'bounced'] as const;
|
||||
|
||||
@@ -20,7 +21,7 @@ export class ChequesService {
|
||||
|
||||
async list(
|
||||
organizationId: string,
|
||||
actor: Pick<Actor, 'userId' | 'role'>,
|
||||
actor: ScopedActor,
|
||||
opts?: { status?: string; q?: string; direction?: string },
|
||||
): Promise<ChequeDto[]> {
|
||||
const rows = await this.prisma.cheque.findMany({
|
||||
@@ -31,37 +32,7 @@ export class ChequesService {
|
||||
...(opts?.direction === 'in' || opts?.direction === 'out'
|
||||
? { direction: opts.direction }
|
||||
: {}),
|
||||
...(opts?.q?.trim()
|
||||
? {
|
||||
OR: [
|
||||
{ number: { contains: opts.q.trim(), mode: 'insensitive' } },
|
||||
{ bank: { contains: opts.q.trim(), mode: 'insensitive' } },
|
||||
{
|
||||
invoice: {
|
||||
number: { contains: opts.q.trim(), mode: 'insensitive' },
|
||||
},
|
||||
},
|
||||
{
|
||||
person: {
|
||||
OR: [
|
||||
{
|
||||
firstName: {
|
||||
contains: opts.q.trim(),
|
||||
mode: 'insensitive',
|
||||
},
|
||||
},
|
||||
{
|
||||
lastName: {
|
||||
contains: opts.q.trim(),
|
||||
mode: 'insensitive',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
}
|
||||
: {}),
|
||||
...this.searchWhere(opts?.q),
|
||||
},
|
||||
include: this.include,
|
||||
orderBy: [{ dueDate: 'asc' }, { createdAt: 'desc' }],
|
||||
@@ -70,9 +41,27 @@ export class ChequesService {
|
||||
return rows.map((row) => this.toDto(row));
|
||||
}
|
||||
|
||||
private searchWhere(q?: string): Prisma.ChequeWhereInput {
|
||||
const search = buildSearchWhere<Prisma.ChequeWhereInput>(q, (t) => [
|
||||
{ number: ci(t) },
|
||||
{ bank: ci(t) },
|
||||
{ invoice: { number: ci(t) } },
|
||||
{
|
||||
person: {
|
||||
OR: [
|
||||
{ firstName: ci(t) },
|
||||
{ lastName: ci(t) },
|
||||
{ mobile: { contains: t } },
|
||||
],
|
||||
},
|
||||
},
|
||||
]);
|
||||
return search ? { AND: [search] } : {};
|
||||
}
|
||||
|
||||
async create(
|
||||
organizationId: string,
|
||||
actor: Pick<Actor, 'userId' | 'role'>,
|
||||
actor: ScopedActor,
|
||||
dto: CreateChequeRequest,
|
||||
): Promise<ChequeDto> {
|
||||
const person = await this.prisma.person.findFirst({
|
||||
@@ -112,7 +101,7 @@ export class ChequesService {
|
||||
async update(
|
||||
organizationId: string,
|
||||
id: string,
|
||||
actor: Pick<Actor, 'userId' | 'role'>,
|
||||
actor: ScopedActor,
|
||||
dto: UpdateChequeRequest,
|
||||
): Promise<ChequeDto> {
|
||||
const existing = await this.prisma.cheque.findFirst({
|
||||
@@ -144,11 +133,12 @@ export class ChequesService {
|
||||
}
|
||||
|
||||
private accessWhere(
|
||||
actor: Pick<Actor, 'userId' | 'role'>,
|
||||
actor: ScopedActor,
|
||||
): Prisma.ChequeWhereInput {
|
||||
if (elevated(actor.role)) return {};
|
||||
const ids = scopedOwnerIds(actor, 'finance');
|
||||
if (ids === null) return {};
|
||||
return {
|
||||
OR: [{ ownerId: actor.userId }, { invoice: { ownerId: actor.userId } }],
|
||||
OR: [{ ownerId: { in: ids } }, { invoice: { ownerId: { in: ids } } }],
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user