Unified search algorithm across all lists; per-section record visibility (contacts, deals, activities, leads, finance, tickets, notes, projects)

This commit is contained in:
2026-10-06 15:04:46 +03:30
parent 43717392b2
commit e08f1452ef
38 changed files with 699 additions and 420 deletions
+14 -13
View File
@@ -25,6 +25,7 @@ import {
} from '../common/record-scope';
import { normalizeTags } from '../common/tags';
import { normalizePersonImportSource } from './person-source';
import { buildSearchWhere, ci } from '../common/search';
function parseDateOrNull(raw?: string | null): Date | null {
if (!raw?.trim()) return null;
@@ -77,22 +78,22 @@ export class CompaniesService {
page = 1,
limit = 20,
): Promise<PaginatedResponse<CompanyDto>> {
const search = buildSearchWhere<Prisma.CompanyWhereInput>(q, (t) => [
{ name: ci(t) },
{ email: ci(t) },
{ phone: { contains: t } },
{ otherPhones: { contains: t } },
{ nationalId: { contains: t } },
{ economicCode: { contains: t } },
{ code: ci(t) },
{ sourceRef: ci(t) },
{ city: ci(t) },
{ province: ci(t) },
]);
const where: Prisma.CompanyWhereInput = {
organizationId: actor.organizationId,
...ownerWhere(actor),
...(q?.trim()
? {
OR: [
{ name: { contains: q.trim(), mode: 'insensitive' } },
{ email: { contains: q.trim(), mode: 'insensitive' } },
{ phone: { contains: q.trim() } },
{ nationalId: { contains: q.trim() } },
{ code: { contains: q.trim() } },
{ sourceRef: { contains: q.trim() } },
{ city: { contains: q.trim(), mode: 'insensitive' } },
],
}
: {}),
...(search ? { AND: [search] } : {}),
};
const [rows, total] = await this.prisma.$transaction([
+14 -16
View File
@@ -32,6 +32,7 @@ import { AutomationsService } from '../automations/automations.service';
import { MessageAutomationsService } from '../message-automations/message-automations.service';
import { WebhooksService } from '../public-api/webhooks.service';
import { normalizeTags } from '../common/tags';
import { buildSearchWhere, ci } from '../common/search';
import {
normalizePersonImportSource,
personImportSourceLabel,
@@ -105,27 +106,24 @@ export class PeopleService {
const sourceFilter = opts?.importSource?.trim()
? normalizePersonImportSource(opts.importSource)
: undefined;
const search = buildSearchWhere<Prisma.PersonWhereInput>(q, (t) => [
{ firstName: ci(t) },
{ lastName: ci(t) },
{ previousFirstName: ci(t) },
{ previousLastName: ci(t) },
{ email: ci(t) },
{ mobile: { contains: t } },
{ phone: { contains: t } },
{ sourceRef: ci(t) },
{ previousSourceRef: ci(t) },
{ company: { name: ci(t) } },
]);
const where: Prisma.PersonWhereInput = {
organizationId: actor.organizationId,
...ownerWhere(actor),
...(opts?.mood ? { mood: opts.mood } : {}),
...(sourceFilter ? { importSource: sourceFilter } : {}),
...(q?.trim()
? {
OR: [
{ firstName: { contains: q.trim(), mode: 'insensitive' } },
{ lastName: { contains: q.trim(), mode: 'insensitive' } },
{ previousFirstName: { contains: q.trim(), mode: 'insensitive' } },
{ previousLastName: { contains: q.trim(), mode: 'insensitive' } },
{ email: { contains: q.trim(), mode: 'insensitive' } },
{ mobile: { contains: q.trim() } },
{ phone: { contains: q.trim() } },
{ sourceRef: { contains: q.trim() } },
{ previousSourceRef: { contains: q.trim() } },
{ company: { name: { contains: q.trim(), mode: 'insensitive' } } },
],
}
: {}),
...(search ? { AND: [search] } : {}),
};
const [rows, total] = await this.prisma.$transaction([