@hed-hog/contact 0.0.299 → 0.0.301
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/contact.module.d.ts.map +1 -1
- package/dist/contact.module.js +2 -0
- package/dist/contact.module.js.map +1 -1
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -1
- package/dist/person/person.service.js +350 -350
- package/dist/proposal/dto/proposal.dto.d.ts +152 -0
- package/dist/proposal/dto/proposal.dto.d.ts.map +1 -0
- package/dist/proposal/dto/proposal.dto.js +396 -0
- package/dist/proposal/dto/proposal.dto.js.map +1 -0
- package/dist/proposal/proposal-contract.subscriber.d.ts +11 -0
- package/dist/proposal/proposal-contract.subscriber.d.ts.map +1 -0
- package/dist/proposal/proposal-contract.subscriber.js +51 -0
- package/dist/proposal/proposal-contract.subscriber.js.map +1 -0
- package/dist/proposal/proposal-event.types.d.ts +122 -0
- package/dist/proposal/proposal-event.types.d.ts.map +1 -0
- package/dist/proposal/proposal-event.types.js +13 -0
- package/dist/proposal/proposal-event.types.js.map +1 -0
- package/dist/proposal/proposal.controller.d.ts +56 -0
- package/dist/proposal/proposal.controller.d.ts.map +1 -0
- package/dist/proposal/proposal.controller.js +191 -0
- package/dist/proposal/proposal.controller.js.map +1 -0
- package/dist/proposal/proposal.module.d.ts +3 -0
- package/dist/proposal/proposal.module.d.ts.map +1 -0
- package/dist/proposal/proposal.module.js +32 -0
- package/dist/proposal/proposal.module.js.map +1 -0
- package/dist/proposal/proposal.service.d.ts +95 -0
- package/dist/proposal/proposal.service.d.ts.map +1 -0
- package/dist/proposal/proposal.service.js +1914 -0
- package/dist/proposal/proposal.service.js.map +1 -0
- package/dist/proposal/proposal.service.spec.d.ts +2 -0
- package/dist/proposal/proposal.service.spec.d.ts.map +1 -0
- package/dist/proposal/proposal.service.spec.js +187 -0
- package/dist/proposal/proposal.service.spec.js.map +1 -0
- package/hedhog/data/dashboard.yaml +6 -0
- package/hedhog/data/dashboard_component.yaml +87 -0
- package/hedhog/data/dashboard_component_role.yaml +55 -0
- package/hedhog/data/dashboard_item.yaml +95 -0
- package/hedhog/data/dashboard_role.yaml +6 -0
- package/hedhog/data/route.yaml +112 -68
- package/hedhog/frontend/app/dashboard/_components/dashboard-widgets.tsx.ejs +508 -0
- package/hedhog/frontend/app/dashboard/_components/use-crm-dashboard-data.ts.ejs +104 -0
- package/hedhog/frontend/app/dashboard/page.tsx.ejs +37 -431
- package/hedhog/frontend/app/pipeline/_components/lead-detail-sheet.tsx.ejs +252 -209
- package/hedhog/frontend/app/pipeline/_components/lead-proposals-tab.tsx.ejs +1584 -0
- package/hedhog/frontend/messages/en.json +136 -42
- package/hedhog/frontend/messages/pt.json +135 -41
- package/hedhog/frontend/widgets/next-actions.tsx.ejs +40 -0
- package/hedhog/frontend/widgets/overview-kpis.tsx.ejs +47 -0
- package/hedhog/frontend/widgets/owner-performance.tsx.ejs +42 -0
- package/hedhog/frontend/widgets/quick-access.tsx.ejs +29 -0
- package/hedhog/frontend/widgets/source-breakdown.tsx.ejs +40 -0
- package/hedhog/frontend/widgets/stage-distribution.tsx.ejs +40 -0
- package/hedhog/frontend/widgets/top-owners.tsx.ejs +42 -0
- package/hedhog/frontend/widgets/unattended.tsx.ejs +40 -0
- package/hedhog/table/crm_activity.yaml +68 -68
- package/hedhog/table/crm_stage_history.yaml +34 -34
- package/hedhog/table/person_company.yaml +27 -27
- package/hedhog/table/proposal.yaml +112 -0
- package/hedhog/table/proposal_approval.yaml +63 -0
- package/hedhog/table/proposal_document.yaml +77 -0
- package/hedhog/table/proposal_item.yaml +64 -0
- package/hedhog/table/proposal_revision.yaml +78 -0
- package/package.json +6 -5
- package/src/contact.module.ts +2 -0
- package/src/index.ts +3 -0
- package/src/person/dto/account.dto.ts +100 -100
- package/src/person/dto/activity.dto.ts +54 -54
- package/src/person/dto/dashboard-query.dto.ts +25 -25
- package/src/person/dto/followup-query.dto.ts +25 -25
- package/src/person/dto/reports-query.dto.ts +25 -25
- package/src/person/person.controller.ts +176 -176
- package/src/person/person.service.ts +4825 -4825
- package/src/proposal/dto/proposal.dto.ts +341 -0
- package/src/proposal/proposal-contract.subscriber.ts +43 -0
- package/src/proposal/proposal-event.types.ts +130 -0
- package/src/proposal/proposal.controller.ts +168 -0
- package/src/proposal/proposal.module.ts +19 -0
- package/src/proposal/proposal.service.ts +2525 -0
|
@@ -231,44 +231,44 @@ let PersonService = class PersonService {
|
|
|
231
231
|
const visibilityFilter = allowCompanyRegistration
|
|
232
232
|
? api_prisma_1.Prisma.empty
|
|
233
233
|
: api_prisma_1.Prisma.sql `AND p.type = 'individual'`;
|
|
234
|
-
const stageRows = await this.prismaService.$queryRaw(api_prisma_1.Prisma.sql `
|
|
235
|
-
SELECT
|
|
236
|
-
sh.to_stage,
|
|
237
|
-
sh.from_stage,
|
|
238
|
-
sh.changed_at,
|
|
239
|
-
sh.changed_by_user_id
|
|
240
|
-
FROM crm_stage_history sh
|
|
241
|
-
INNER JOIN person p ON p.id = sh.person_id
|
|
242
|
-
WHERE 1 = 1
|
|
243
|
-
${visibilityFilter}
|
|
244
|
-
AND sh.changed_at >= CAST(${startIso} AS TIMESTAMPTZ)
|
|
245
|
-
AND sh.changed_at <= CAST(${endIso} AS TIMESTAMPTZ)
|
|
234
|
+
const stageRows = await this.prismaService.$queryRaw(api_prisma_1.Prisma.sql `
|
|
235
|
+
SELECT
|
|
236
|
+
sh.to_stage,
|
|
237
|
+
sh.from_stage,
|
|
238
|
+
sh.changed_at,
|
|
239
|
+
sh.changed_by_user_id
|
|
240
|
+
FROM crm_stage_history sh
|
|
241
|
+
INNER JOIN person p ON p.id = sh.person_id
|
|
242
|
+
WHERE 1 = 1
|
|
243
|
+
${visibilityFilter}
|
|
244
|
+
AND sh.changed_at >= CAST(${startIso} AS TIMESTAMPTZ)
|
|
245
|
+
AND sh.changed_at <= CAST(${endIso} AS TIMESTAMPTZ)
|
|
246
246
|
`);
|
|
247
|
-
const activityRows = await this.prismaService.$queryRaw(api_prisma_1.Prisma.sql `
|
|
248
|
-
SELECT
|
|
249
|
-
a.type,
|
|
250
|
-
a.source_kind,
|
|
251
|
-
a.created_at,
|
|
252
|
-
a.completed_at,
|
|
253
|
-
a.owner_user_id,
|
|
254
|
-
a.created_by_user_id,
|
|
255
|
-
a.completed_by_user_id
|
|
256
|
-
FROM crm_activity a
|
|
257
|
-
INNER JOIN person p ON p.id = a.person_id
|
|
258
|
-
WHERE 1 = 1
|
|
259
|
-
${visibilityFilter}
|
|
260
|
-
AND (
|
|
261
|
-
(
|
|
262
|
-
a.created_at >= CAST(${startIso} AS TIMESTAMPTZ)
|
|
263
|
-
AND a.created_at <= CAST(${endIso} AS TIMESTAMPTZ)
|
|
264
|
-
)
|
|
265
|
-
OR (
|
|
266
|
-
a.source_kind = 'followup'
|
|
267
|
-
AND a.completed_at IS NOT NULL
|
|
268
|
-
AND a.completed_at >= CAST(${startIso} AS TIMESTAMPTZ)
|
|
269
|
-
AND a.completed_at <= CAST(${endIso} AS TIMESTAMPTZ)
|
|
270
|
-
)
|
|
271
|
-
)
|
|
247
|
+
const activityRows = await this.prismaService.$queryRaw(api_prisma_1.Prisma.sql `
|
|
248
|
+
SELECT
|
|
249
|
+
a.type,
|
|
250
|
+
a.source_kind,
|
|
251
|
+
a.created_at,
|
|
252
|
+
a.completed_at,
|
|
253
|
+
a.owner_user_id,
|
|
254
|
+
a.created_by_user_id,
|
|
255
|
+
a.completed_by_user_id
|
|
256
|
+
FROM crm_activity a
|
|
257
|
+
INNER JOIN person p ON p.id = a.person_id
|
|
258
|
+
WHERE 1 = 1
|
|
259
|
+
${visibilityFilter}
|
|
260
|
+
AND (
|
|
261
|
+
(
|
|
262
|
+
a.created_at >= CAST(${startIso} AS TIMESTAMPTZ)
|
|
263
|
+
AND a.created_at <= CAST(${endIso} AS TIMESTAMPTZ)
|
|
264
|
+
)
|
|
265
|
+
OR (
|
|
266
|
+
a.source_kind = 'followup'
|
|
267
|
+
AND a.completed_at IS NOT NULL
|
|
268
|
+
AND a.completed_at >= CAST(${startIso} AS TIMESTAMPTZ)
|
|
269
|
+
AND a.completed_at <= CAST(${endIso} AS TIMESTAMPTZ)
|
|
270
|
+
)
|
|
271
|
+
)
|
|
272
272
|
`);
|
|
273
273
|
const summary = {
|
|
274
274
|
new_leads: enrichedCreatedPeople.length,
|
|
@@ -518,13 +518,13 @@ let PersonService = class PersonService {
|
|
|
518
518
|
const excludedPersonFilter = excludedPersonId > 0
|
|
519
519
|
? api_prisma_1.Prisma.sql ` AND c.person_id <> ${excludedPersonId}`
|
|
520
520
|
: api_prisma_1.Prisma.empty;
|
|
521
|
-
const phoneRows = await this.prismaService.$queryRaw(api_prisma_1.Prisma.sql `
|
|
522
|
-
SELECT DISTINCT c.person_id
|
|
523
|
-
FROM contact c
|
|
524
|
-
JOIN contact_type ct ON ct.id = c.contact_type_id
|
|
525
|
-
WHERE UPPER(ct.code) IN ('PHONE', 'MOBILE', 'WHATSAPP')
|
|
526
|
-
AND regexp_replace(COALESCE(c.value, ''), '[^0-9]+', '', 'g') = ${normalizedPhone}
|
|
527
|
-
${excludedPersonFilter}
|
|
521
|
+
const phoneRows = await this.prismaService.$queryRaw(api_prisma_1.Prisma.sql `
|
|
522
|
+
SELECT DISTINCT c.person_id
|
|
523
|
+
FROM contact c
|
|
524
|
+
JOIN contact_type ct ON ct.id = c.contact_type_id
|
|
525
|
+
WHERE UPPER(ct.code) IN ('PHONE', 'MOBILE', 'WHATSAPP')
|
|
526
|
+
AND regexp_replace(COALESCE(c.value, ''), '[^0-9]+', '', 'g') = ${normalizedPhone}
|
|
527
|
+
${excludedPersonFilter}
|
|
528
528
|
`);
|
|
529
529
|
for (const row of phoneRows) {
|
|
530
530
|
this.addDuplicateReason(reasonsByPersonId, row.person_id, 'phone');
|
|
@@ -537,12 +537,12 @@ let PersonService = class PersonService {
|
|
|
537
537
|
const documentTypeFilter = documentTypeId > 0
|
|
538
538
|
? api_prisma_1.Prisma.sql ` AND d.document_type_id = ${documentTypeId}`
|
|
539
539
|
: api_prisma_1.Prisma.empty;
|
|
540
|
-
const documentRows = await this.prismaService.$queryRaw(api_prisma_1.Prisma.sql `
|
|
541
|
-
SELECT DISTINCT d.person_id
|
|
542
|
-
FROM document d
|
|
543
|
-
WHERE regexp_replace(COALESCE(d.value, ''), '[^0-9]+', '', 'g') = ${normalizedDocument}
|
|
544
|
-
${excludedPersonFilter}
|
|
545
|
-
${documentTypeFilter}
|
|
540
|
+
const documentRows = await this.prismaService.$queryRaw(api_prisma_1.Prisma.sql `
|
|
541
|
+
SELECT DISTINCT d.person_id
|
|
542
|
+
FROM document d
|
|
543
|
+
WHERE regexp_replace(COALESCE(d.value, ''), '[^0-9]+', '', 'g') = ${normalizedDocument}
|
|
544
|
+
${excludedPersonFilter}
|
|
545
|
+
${documentTypeFilter}
|
|
546
546
|
`);
|
|
547
547
|
for (const row of documentRows) {
|
|
548
548
|
this.addDuplicateReason(reasonsByPersonId, row.person_id, 'document');
|
|
@@ -717,26 +717,26 @@ let PersonService = class PersonService {
|
|
|
717
717
|
lifecycleStage: paginationParams.lifecycle_stage,
|
|
718
718
|
});
|
|
719
719
|
const orderBy = this.getAccountOrderBySql(paginationParams.sortField, paginationParams.sortOrder);
|
|
720
|
-
const totalRows = await this.prismaService.$queryRaw(api_prisma_1.Prisma.sql `
|
|
721
|
-
SELECT COUNT(*) AS total
|
|
722
|
-
FROM person p
|
|
723
|
-
INNER JOIN person_company pc ON pc.id = p.id
|
|
724
|
-
WHERE p.type = 'company'
|
|
725
|
-
${filters}
|
|
720
|
+
const totalRows = await this.prismaService.$queryRaw(api_prisma_1.Prisma.sql `
|
|
721
|
+
SELECT COUNT(*) AS total
|
|
722
|
+
FROM person p
|
|
723
|
+
INNER JOIN person_company pc ON pc.id = p.id
|
|
724
|
+
WHERE p.type = 'company'
|
|
725
|
+
${filters}
|
|
726
726
|
`);
|
|
727
727
|
const total = this.coerceCount((_a = totalRows[0]) === null || _a === void 0 ? void 0 : _a.total);
|
|
728
728
|
if (total === 0) {
|
|
729
729
|
return this.createEmptyAccountPagination(page, pageSize);
|
|
730
730
|
}
|
|
731
|
-
const rows = await this.prismaService.$queryRaw(api_prisma_1.Prisma.sql `
|
|
732
|
-
SELECT p.id AS person_id
|
|
733
|
-
FROM person p
|
|
734
|
-
INNER JOIN person_company pc ON pc.id = p.id
|
|
735
|
-
WHERE p.type = 'company'
|
|
736
|
-
${filters}
|
|
737
|
-
ORDER BY ${orderBy}, p.id ASC
|
|
738
|
-
LIMIT ${pageSize}
|
|
739
|
-
OFFSET ${skip}
|
|
731
|
+
const rows = await this.prismaService.$queryRaw(api_prisma_1.Prisma.sql `
|
|
732
|
+
SELECT p.id AS person_id
|
|
733
|
+
FROM person p
|
|
734
|
+
INNER JOIN person_company pc ON pc.id = p.id
|
|
735
|
+
WHERE p.type = 'company'
|
|
736
|
+
${filters}
|
|
737
|
+
ORDER BY ${orderBy}, p.id ASC
|
|
738
|
+
LIMIT ${pageSize}
|
|
739
|
+
OFFSET ${skip}
|
|
740
740
|
`);
|
|
741
741
|
const personIds = rows.map((row) => row.person_id).filter((id) => id > 0);
|
|
742
742
|
if (personIds.length === 0) {
|
|
@@ -784,15 +784,15 @@ let PersonService = class PersonService {
|
|
|
784
784
|
prospects: 0,
|
|
785
785
|
};
|
|
786
786
|
}
|
|
787
|
-
const rows = await this.prismaService.$queryRaw(api_prisma_1.Prisma.sql `
|
|
788
|
-
SELECT
|
|
789
|
-
COUNT(*) AS total,
|
|
790
|
-
COUNT(*) FILTER (WHERE p.status = 'active') AS active,
|
|
791
|
-
COUNT(*) FILTER (WHERE pc.account_lifecycle_stage = 'customer') AS customers,
|
|
792
|
-
COUNT(*) FILTER (WHERE pc.account_lifecycle_stage = 'prospect') AS prospects
|
|
793
|
-
FROM person p
|
|
794
|
-
INNER JOIN person_company pc ON pc.id = p.id
|
|
795
|
-
WHERE p.type = 'company'
|
|
787
|
+
const rows = await this.prismaService.$queryRaw(api_prisma_1.Prisma.sql `
|
|
788
|
+
SELECT
|
|
789
|
+
COUNT(*) AS total,
|
|
790
|
+
COUNT(*) FILTER (WHERE p.status = 'active') AS active,
|
|
791
|
+
COUNT(*) FILTER (WHERE pc.account_lifecycle_stage = 'customer') AS customers,
|
|
792
|
+
COUNT(*) FILTER (WHERE pc.account_lifecycle_stage = 'prospect') AS prospects
|
|
793
|
+
FROM person p
|
|
794
|
+
INNER JOIN person_company pc ON pc.id = p.id
|
|
795
|
+
WHERE p.type = 'company'
|
|
796
796
|
`);
|
|
797
797
|
return {
|
|
798
798
|
total: this.coerceCount((_a = rows[0]) === null || _a === void 0 ? void 0 : _a.total),
|
|
@@ -902,44 +902,44 @@ let PersonService = class PersonService {
|
|
|
902
902
|
type: paginationParams.type,
|
|
903
903
|
priority: paginationParams.priority,
|
|
904
904
|
});
|
|
905
|
-
const totalRows = await this.prismaService.$queryRaw(api_prisma_1.Prisma.sql `
|
|
906
|
-
SELECT COUNT(*) AS total
|
|
907
|
-
FROM crm_activity a
|
|
908
|
-
INNER JOIN person p ON p.id = a.person_id
|
|
909
|
-
LEFT JOIN "user" owner_user ON owner_user.id = a.owner_user_id
|
|
910
|
-
WHERE 1 = 1
|
|
911
|
-
${filters}
|
|
905
|
+
const totalRows = await this.prismaService.$queryRaw(api_prisma_1.Prisma.sql `
|
|
906
|
+
SELECT COUNT(*) AS total
|
|
907
|
+
FROM crm_activity a
|
|
908
|
+
INNER JOIN person p ON p.id = a.person_id
|
|
909
|
+
LEFT JOIN "user" owner_user ON owner_user.id = a.owner_user_id
|
|
910
|
+
WHERE 1 = 1
|
|
911
|
+
${filters}
|
|
912
912
|
`);
|
|
913
913
|
const total = this.coerceCount((_a = totalRows[0]) === null || _a === void 0 ? void 0 : _a.total);
|
|
914
914
|
if (total === 0) {
|
|
915
915
|
return this.createEmptyCrmActivityPagination(page, pageSize);
|
|
916
916
|
}
|
|
917
|
-
const rows = await this.prismaService.$queryRaw(api_prisma_1.Prisma.sql `
|
|
918
|
-
SELECT
|
|
919
|
-
a.id,
|
|
920
|
-
a.person_id,
|
|
921
|
-
a.owner_user_id,
|
|
922
|
-
a.type,
|
|
923
|
-
a.subject,
|
|
924
|
-
a.notes,
|
|
925
|
-
a.due_at,
|
|
926
|
-
a.completed_at,
|
|
927
|
-
a.created_at,
|
|
928
|
-
a.priority,
|
|
929
|
-
p.name AS person_name,
|
|
930
|
-
p.type AS person_type,
|
|
931
|
-
p.status AS person_status,
|
|
932
|
-
pc.trade_name AS person_trade_name,
|
|
933
|
-
owner_user.name AS owner_user_name
|
|
934
|
-
FROM crm_activity a
|
|
935
|
-
INNER JOIN person p ON p.id = a.person_id
|
|
936
|
-
LEFT JOIN person_company pc ON pc.id = p.id
|
|
937
|
-
LEFT JOIN "user" owner_user ON owner_user.id = a.owner_user_id
|
|
938
|
-
WHERE 1 = 1
|
|
939
|
-
${filters}
|
|
940
|
-
ORDER BY a.due_at ASC, a.id ASC
|
|
941
|
-
LIMIT ${pageSize}
|
|
942
|
-
OFFSET ${skip}
|
|
917
|
+
const rows = await this.prismaService.$queryRaw(api_prisma_1.Prisma.sql `
|
|
918
|
+
SELECT
|
|
919
|
+
a.id,
|
|
920
|
+
a.person_id,
|
|
921
|
+
a.owner_user_id,
|
|
922
|
+
a.type,
|
|
923
|
+
a.subject,
|
|
924
|
+
a.notes,
|
|
925
|
+
a.due_at,
|
|
926
|
+
a.completed_at,
|
|
927
|
+
a.created_at,
|
|
928
|
+
a.priority,
|
|
929
|
+
p.name AS person_name,
|
|
930
|
+
p.type AS person_type,
|
|
931
|
+
p.status AS person_status,
|
|
932
|
+
pc.trade_name AS person_trade_name,
|
|
933
|
+
owner_user.name AS owner_user_name
|
|
934
|
+
FROM crm_activity a
|
|
935
|
+
INNER JOIN person p ON p.id = a.person_id
|
|
936
|
+
LEFT JOIN person_company pc ON pc.id = p.id
|
|
937
|
+
LEFT JOIN "user" owner_user ON owner_user.id = a.owner_user_id
|
|
938
|
+
WHERE 1 = 1
|
|
939
|
+
${filters}
|
|
940
|
+
ORDER BY a.due_at ASC, a.id ASC
|
|
941
|
+
LIMIT ${pageSize}
|
|
942
|
+
OFFSET ${skip}
|
|
943
943
|
`);
|
|
944
944
|
const data = rows.map((row) => this.mapCrmActivityListRow(row));
|
|
945
945
|
const lastPage = Math.max(1, Math.ceil(total / pageSize));
|
|
@@ -959,24 +959,24 @@ let PersonService = class PersonService {
|
|
|
959
959
|
const visibilityFilter = allowCompanyRegistration
|
|
960
960
|
? api_prisma_1.Prisma.empty
|
|
961
961
|
: api_prisma_1.Prisma.sql `AND p.type = 'individual'`;
|
|
962
|
-
const rows = await this.prismaService.$queryRaw(api_prisma_1.Prisma.sql `
|
|
963
|
-
SELECT
|
|
964
|
-
COUNT(*) AS total,
|
|
965
|
-
COUNT(*) FILTER (
|
|
966
|
-
WHERE a.completed_at IS NULL
|
|
967
|
-
AND a.due_at >= NOW()
|
|
968
|
-
) AS pending,
|
|
969
|
-
COUNT(*) FILTER (
|
|
970
|
-
WHERE a.completed_at IS NULL
|
|
971
|
-
AND a.due_at < NOW()
|
|
972
|
-
) AS overdue,
|
|
973
|
-
COUNT(*) FILTER (
|
|
974
|
-
WHERE a.completed_at IS NOT NULL
|
|
975
|
-
) AS completed
|
|
976
|
-
FROM crm_activity a
|
|
977
|
-
INNER JOIN person p ON p.id = a.person_id
|
|
978
|
-
WHERE 1 = 1
|
|
979
|
-
${visibilityFilter}
|
|
962
|
+
const rows = await this.prismaService.$queryRaw(api_prisma_1.Prisma.sql `
|
|
963
|
+
SELECT
|
|
964
|
+
COUNT(*) AS total,
|
|
965
|
+
COUNT(*) FILTER (
|
|
966
|
+
WHERE a.completed_at IS NULL
|
|
967
|
+
AND a.due_at >= NOW()
|
|
968
|
+
) AS pending,
|
|
969
|
+
COUNT(*) FILTER (
|
|
970
|
+
WHERE a.completed_at IS NULL
|
|
971
|
+
AND a.due_at < NOW()
|
|
972
|
+
) AS overdue,
|
|
973
|
+
COUNT(*) FILTER (
|
|
974
|
+
WHERE a.completed_at IS NOT NULL
|
|
975
|
+
) AS completed
|
|
976
|
+
FROM crm_activity a
|
|
977
|
+
INNER JOIN person p ON p.id = a.person_id
|
|
978
|
+
WHERE 1 = 1
|
|
979
|
+
${visibilityFilter}
|
|
980
980
|
`);
|
|
981
981
|
return {
|
|
982
982
|
total: this.coerceCount((_a = rows[0]) === null || _a === void 0 ? void 0 : _a.total),
|
|
@@ -990,37 +990,37 @@ let PersonService = class PersonService {
|
|
|
990
990
|
const visibilityFilter = allowCompanyRegistration
|
|
991
991
|
? api_prisma_1.Prisma.empty
|
|
992
992
|
: api_prisma_1.Prisma.sql `AND p.type = 'individual'`;
|
|
993
|
-
const rows = await this.prismaService.$queryRaw(api_prisma_1.Prisma.sql `
|
|
994
|
-
SELECT
|
|
995
|
-
a.id,
|
|
996
|
-
a.person_id,
|
|
997
|
-
a.owner_user_id,
|
|
998
|
-
a.created_by_user_id,
|
|
999
|
-
a.completed_by_user_id,
|
|
1000
|
-
a.type,
|
|
1001
|
-
a.subject,
|
|
1002
|
-
a.notes,
|
|
1003
|
-
a.due_at,
|
|
1004
|
-
a.completed_at,
|
|
1005
|
-
a.created_at,
|
|
1006
|
-
a.priority,
|
|
1007
|
-
a.source_kind,
|
|
1008
|
-
p.name AS person_name,
|
|
1009
|
-
p.type AS person_type,
|
|
1010
|
-
p.status AS person_status,
|
|
1011
|
-
pc.trade_name AS person_trade_name,
|
|
1012
|
-
owner_user.name AS owner_user_name,
|
|
1013
|
-
created_by_user.name AS created_by_user_name,
|
|
1014
|
-
completed_by_user.name AS completed_by_user_name
|
|
1015
|
-
FROM crm_activity a
|
|
1016
|
-
INNER JOIN person p ON p.id = a.person_id
|
|
1017
|
-
LEFT JOIN person_company pc ON pc.id = p.id
|
|
1018
|
-
LEFT JOIN "user" owner_user ON owner_user.id = a.owner_user_id
|
|
1019
|
-
LEFT JOIN "user" created_by_user ON created_by_user.id = a.created_by_user_id
|
|
1020
|
-
LEFT JOIN "user" completed_by_user ON completed_by_user.id = a.completed_by_user_id
|
|
1021
|
-
WHERE a.id = ${id}
|
|
1022
|
-
${visibilityFilter}
|
|
1023
|
-
LIMIT 1
|
|
993
|
+
const rows = await this.prismaService.$queryRaw(api_prisma_1.Prisma.sql `
|
|
994
|
+
SELECT
|
|
995
|
+
a.id,
|
|
996
|
+
a.person_id,
|
|
997
|
+
a.owner_user_id,
|
|
998
|
+
a.created_by_user_id,
|
|
999
|
+
a.completed_by_user_id,
|
|
1000
|
+
a.type,
|
|
1001
|
+
a.subject,
|
|
1002
|
+
a.notes,
|
|
1003
|
+
a.due_at,
|
|
1004
|
+
a.completed_at,
|
|
1005
|
+
a.created_at,
|
|
1006
|
+
a.priority,
|
|
1007
|
+
a.source_kind,
|
|
1008
|
+
p.name AS person_name,
|
|
1009
|
+
p.type AS person_type,
|
|
1010
|
+
p.status AS person_status,
|
|
1011
|
+
pc.trade_name AS person_trade_name,
|
|
1012
|
+
owner_user.name AS owner_user_name,
|
|
1013
|
+
created_by_user.name AS created_by_user_name,
|
|
1014
|
+
completed_by_user.name AS completed_by_user_name
|
|
1015
|
+
FROM crm_activity a
|
|
1016
|
+
INNER JOIN person p ON p.id = a.person_id
|
|
1017
|
+
LEFT JOIN person_company pc ON pc.id = p.id
|
|
1018
|
+
LEFT JOIN "user" owner_user ON owner_user.id = a.owner_user_id
|
|
1019
|
+
LEFT JOIN "user" created_by_user ON created_by_user.id = a.created_by_user_id
|
|
1020
|
+
LEFT JOIN "user" completed_by_user ON completed_by_user.id = a.completed_by_user_id
|
|
1021
|
+
WHERE a.id = ${id}
|
|
1022
|
+
${visibilityFilter}
|
|
1023
|
+
LIMIT 1
|
|
1024
1024
|
`);
|
|
1025
1025
|
const row = rows[0];
|
|
1026
1026
|
if (!row) {
|
|
@@ -1035,17 +1035,17 @@ let PersonService = class PersonService {
|
|
|
1035
1035
|
? api_prisma_1.Prisma.empty
|
|
1036
1036
|
: api_prisma_1.Prisma.sql `AND p.type = 'individual'`;
|
|
1037
1037
|
return this.prismaService.$transaction(async (tx) => {
|
|
1038
|
-
const rows = (await tx.$queryRaw(api_prisma_1.Prisma.sql `
|
|
1039
|
-
SELECT
|
|
1040
|
-
a.id,
|
|
1041
|
-
a.person_id,
|
|
1042
|
-
a.completed_at,
|
|
1043
|
-
a.source_kind
|
|
1044
|
-
FROM crm_activity a
|
|
1045
|
-
INNER JOIN person p ON p.id = a.person_id
|
|
1046
|
-
WHERE a.id = ${id}
|
|
1047
|
-
${visibilityFilter}
|
|
1048
|
-
LIMIT 1
|
|
1038
|
+
const rows = (await tx.$queryRaw(api_prisma_1.Prisma.sql `
|
|
1039
|
+
SELECT
|
|
1040
|
+
a.id,
|
|
1041
|
+
a.person_id,
|
|
1042
|
+
a.completed_at,
|
|
1043
|
+
a.source_kind
|
|
1044
|
+
FROM crm_activity a
|
|
1045
|
+
INNER JOIN person p ON p.id = a.person_id
|
|
1046
|
+
WHERE a.id = ${id}
|
|
1047
|
+
${visibilityFilter}
|
|
1048
|
+
LIMIT 1
|
|
1049
1049
|
`));
|
|
1050
1050
|
const activity = rows[0];
|
|
1051
1051
|
if (!activity) {
|
|
@@ -1058,13 +1058,13 @@ let PersonService = class PersonService {
|
|
|
1058
1058
|
};
|
|
1059
1059
|
}
|
|
1060
1060
|
const completedAt = new Date();
|
|
1061
|
-
await tx.$executeRaw(api_prisma_1.Prisma.sql `
|
|
1062
|
-
UPDATE crm_activity
|
|
1063
|
-
SET
|
|
1064
|
-
completed_at = CAST(${completedAt.toISOString()} AS TIMESTAMPTZ),
|
|
1065
|
-
completed_by_user_id = ${actorUserId},
|
|
1066
|
-
updated_at = NOW()
|
|
1067
|
-
WHERE id = ${id}
|
|
1061
|
+
await tx.$executeRaw(api_prisma_1.Prisma.sql `
|
|
1062
|
+
UPDATE crm_activity
|
|
1063
|
+
SET
|
|
1064
|
+
completed_at = CAST(${completedAt.toISOString()} AS TIMESTAMPTZ),
|
|
1065
|
+
completed_by_user_id = ${actorUserId},
|
|
1066
|
+
updated_at = NOW()
|
|
1067
|
+
WHERE id = ${id}
|
|
1068
1068
|
`);
|
|
1069
1069
|
if (activity.source_kind === 'followup') {
|
|
1070
1070
|
await this.upsertMetadataValue(tx, activity.person_id, NEXT_ACTION_AT_METADATA_KEY, null);
|
|
@@ -1093,30 +1093,30 @@ let PersonService = class PersonService {
|
|
|
1093
1093
|
dateTo: paginationParams.date_to,
|
|
1094
1094
|
});
|
|
1095
1095
|
const followupTimestampSql = this.getFollowupTimestampSql();
|
|
1096
|
-
const totalRows = await this.prismaService.$queryRaw(api_prisma_1.Prisma.sql `
|
|
1097
|
-
SELECT COUNT(*) AS total
|
|
1098
|
-
FROM person p
|
|
1099
|
-
INNER JOIN person_metadata pm_next
|
|
1100
|
-
ON pm_next.person_id = p.id
|
|
1101
|
-
AND pm_next.key = ${NEXT_ACTION_AT_METADATA_KEY}
|
|
1102
|
-
WHERE 1 = 1
|
|
1103
|
-
${filters}
|
|
1096
|
+
const totalRows = await this.prismaService.$queryRaw(api_prisma_1.Prisma.sql `
|
|
1097
|
+
SELECT COUNT(*) AS total
|
|
1098
|
+
FROM person p
|
|
1099
|
+
INNER JOIN person_metadata pm_next
|
|
1100
|
+
ON pm_next.person_id = p.id
|
|
1101
|
+
AND pm_next.key = ${NEXT_ACTION_AT_METADATA_KEY}
|
|
1102
|
+
WHERE 1 = 1
|
|
1103
|
+
${filters}
|
|
1104
1104
|
`);
|
|
1105
1105
|
const total = this.coerceCount((_a = totalRows[0]) === null || _a === void 0 ? void 0 : _a.total);
|
|
1106
1106
|
if (total === 0) {
|
|
1107
1107
|
return this.createEmptyFollowupPagination(page, pageSize);
|
|
1108
1108
|
}
|
|
1109
|
-
const rows = await this.prismaService.$queryRaw(api_prisma_1.Prisma.sql `
|
|
1110
|
-
SELECT p.id AS person_id
|
|
1111
|
-
FROM person p
|
|
1112
|
-
INNER JOIN person_metadata pm_next
|
|
1113
|
-
ON pm_next.person_id = p.id
|
|
1114
|
-
AND pm_next.key = ${NEXT_ACTION_AT_METADATA_KEY}
|
|
1115
|
-
WHERE 1 = 1
|
|
1116
|
-
${filters}
|
|
1117
|
-
ORDER BY ${followupTimestampSql} ASC, p.id ASC
|
|
1118
|
-
LIMIT ${pageSize}
|
|
1119
|
-
OFFSET ${skip}
|
|
1109
|
+
const rows = await this.prismaService.$queryRaw(api_prisma_1.Prisma.sql `
|
|
1110
|
+
SELECT p.id AS person_id
|
|
1111
|
+
FROM person p
|
|
1112
|
+
INNER JOIN person_metadata pm_next
|
|
1113
|
+
ON pm_next.person_id = p.id
|
|
1114
|
+
AND pm_next.key = ${NEXT_ACTION_AT_METADATA_KEY}
|
|
1115
|
+
WHERE 1 = 1
|
|
1116
|
+
${filters}
|
|
1117
|
+
ORDER BY ${followupTimestampSql} ASC, p.id ASC
|
|
1118
|
+
LIMIT ${pageSize}
|
|
1119
|
+
OFFSET ${skip}
|
|
1120
1120
|
`);
|
|
1121
1121
|
const personIds = rows.map((row) => row.person_id).filter((id) => id > 0);
|
|
1122
1122
|
const people = personIds.length > 0
|
|
@@ -1185,25 +1185,25 @@ let PersonService = class PersonService {
|
|
|
1185
1185
|
});
|
|
1186
1186
|
const followupTimestampSql = this.getFollowupTimestampSql();
|
|
1187
1187
|
const { todayStartIso, tomorrowStartIso } = this.getFollowupDayBoundaryIsoStrings();
|
|
1188
|
-
const rows = await this.prismaService.$queryRaw(api_prisma_1.Prisma.sql `
|
|
1189
|
-
SELECT
|
|
1190
|
-
COUNT(*) AS total,
|
|
1191
|
-
COUNT(*) FILTER (
|
|
1192
|
-
WHERE ${followupTimestampSql} >= CAST(${todayStartIso} AS TIMESTAMPTZ)
|
|
1193
|
-
AND ${followupTimestampSql} < CAST(${tomorrowStartIso} AS TIMESTAMPTZ)
|
|
1194
|
-
) AS today,
|
|
1195
|
-
COUNT(*) FILTER (
|
|
1196
|
-
WHERE ${followupTimestampSql} < CAST(${todayStartIso} AS TIMESTAMPTZ)
|
|
1197
|
-
) AS overdue,
|
|
1198
|
-
COUNT(*) FILTER (
|
|
1199
|
-
WHERE ${followupTimestampSql} >= CAST(${tomorrowStartIso} AS TIMESTAMPTZ)
|
|
1200
|
-
) AS upcoming
|
|
1201
|
-
FROM person p
|
|
1202
|
-
INNER JOIN person_metadata pm_next
|
|
1203
|
-
ON pm_next.person_id = p.id
|
|
1204
|
-
AND pm_next.key = ${NEXT_ACTION_AT_METADATA_KEY}
|
|
1205
|
-
WHERE 1 = 1
|
|
1206
|
-
${filters}
|
|
1188
|
+
const rows = await this.prismaService.$queryRaw(api_prisma_1.Prisma.sql `
|
|
1189
|
+
SELECT
|
|
1190
|
+
COUNT(*) AS total,
|
|
1191
|
+
COUNT(*) FILTER (
|
|
1192
|
+
WHERE ${followupTimestampSql} >= CAST(${todayStartIso} AS TIMESTAMPTZ)
|
|
1193
|
+
AND ${followupTimestampSql} < CAST(${tomorrowStartIso} AS TIMESTAMPTZ)
|
|
1194
|
+
) AS today,
|
|
1195
|
+
COUNT(*) FILTER (
|
|
1196
|
+
WHERE ${followupTimestampSql} < CAST(${todayStartIso} AS TIMESTAMPTZ)
|
|
1197
|
+
) AS overdue,
|
|
1198
|
+
COUNT(*) FILTER (
|
|
1199
|
+
WHERE ${followupTimestampSql} >= CAST(${tomorrowStartIso} AS TIMESTAMPTZ)
|
|
1200
|
+
) AS upcoming
|
|
1201
|
+
FROM person p
|
|
1202
|
+
INNER JOIN person_metadata pm_next
|
|
1203
|
+
ON pm_next.person_id = p.id
|
|
1204
|
+
AND pm_next.key = ${NEXT_ACTION_AT_METADATA_KEY}
|
|
1205
|
+
WHERE 1 = 1
|
|
1206
|
+
${filters}
|
|
1207
1207
|
`);
|
|
1208
1208
|
return {
|
|
1209
1209
|
total: this.coerceCount((_a = rows[0]) === null || _a === void 0 ? void 0 : _a.total),
|
|
@@ -2059,25 +2059,25 @@ let PersonService = class PersonService {
|
|
|
2059
2059
|
const fromStageSql = fromStage
|
|
2060
2060
|
? api_prisma_1.Prisma.sql `CAST(${fromStage} AS crm_stage_history_from_stage_enum)`
|
|
2061
2061
|
: api_prisma_1.Prisma.sql `NULL`;
|
|
2062
|
-
await tx.$executeRaw(api_prisma_1.Prisma.sql `
|
|
2063
|
-
INSERT INTO crm_stage_history (
|
|
2064
|
-
person_id,
|
|
2065
|
-
from_stage,
|
|
2066
|
-
to_stage,
|
|
2067
|
-
changed_by_user_id,
|
|
2068
|
-
changed_at,
|
|
2069
|
-
created_at,
|
|
2070
|
-
updated_at
|
|
2071
|
-
)
|
|
2072
|
-
VALUES (
|
|
2073
|
-
${personId},
|
|
2074
|
-
${fromStageSql},
|
|
2075
|
-
CAST(${toStage} AS crm_stage_history_to_stage_enum),
|
|
2076
|
-
${changedByUserId},
|
|
2077
|
-
NOW(),
|
|
2078
|
-
NOW(),
|
|
2079
|
-
NOW()
|
|
2080
|
-
)
|
|
2062
|
+
await tx.$executeRaw(api_prisma_1.Prisma.sql `
|
|
2063
|
+
INSERT INTO crm_stage_history (
|
|
2064
|
+
person_id,
|
|
2065
|
+
from_stage,
|
|
2066
|
+
to_stage,
|
|
2067
|
+
changed_by_user_id,
|
|
2068
|
+
changed_at,
|
|
2069
|
+
created_at,
|
|
2070
|
+
updated_at
|
|
2071
|
+
)
|
|
2072
|
+
VALUES (
|
|
2073
|
+
${personId},
|
|
2074
|
+
${fromStageSql},
|
|
2075
|
+
CAST(${toStage} AS crm_stage_history_to_stage_enum),
|
|
2076
|
+
${changedByUserId},
|
|
2077
|
+
NOW(),
|
|
2078
|
+
NOW(),
|
|
2079
|
+
NOW()
|
|
2080
|
+
)
|
|
2081
2081
|
`);
|
|
2082
2082
|
}
|
|
2083
2083
|
async syncPersonSubtypeData(tx, personId, currentType, data, locale) {
|
|
@@ -2723,94 +2723,94 @@ let PersonService = class PersonService {
|
|
|
2723
2723
|
return ownerUserId && ownerUserId > 0 ? ownerUserId : null;
|
|
2724
2724
|
}
|
|
2725
2725
|
async upsertFollowupActivity(tx, { personId, ownerUserId, dueAt, notes, actorUserId, }) {
|
|
2726
|
-
const existingRows = (await tx.$queryRaw(api_prisma_1.Prisma.sql `
|
|
2727
|
-
SELECT id
|
|
2728
|
-
FROM crm_activity
|
|
2729
|
-
WHERE person_id = ${personId}
|
|
2730
|
-
AND source_kind = 'followup'
|
|
2731
|
-
AND completed_at IS NULL
|
|
2732
|
-
ORDER BY id DESC
|
|
2733
|
-
LIMIT 1
|
|
2726
|
+
const existingRows = (await tx.$queryRaw(api_prisma_1.Prisma.sql `
|
|
2727
|
+
SELECT id
|
|
2728
|
+
FROM crm_activity
|
|
2729
|
+
WHERE person_id = ${personId}
|
|
2730
|
+
AND source_kind = 'followup'
|
|
2731
|
+
AND completed_at IS NULL
|
|
2732
|
+
ORDER BY id DESC
|
|
2733
|
+
LIMIT 1
|
|
2734
2734
|
`));
|
|
2735
2735
|
const existing = existingRows[0];
|
|
2736
2736
|
const normalizedNotes = this.normalizeTextOrNull(notes);
|
|
2737
2737
|
if (existing) {
|
|
2738
|
-
await tx.$executeRaw(api_prisma_1.Prisma.sql `
|
|
2739
|
-
UPDATE crm_activity
|
|
2740
|
-
SET
|
|
2741
|
-
owner_user_id = ${ownerUserId},
|
|
2742
|
-
type = CAST(${'task'} AS crm_activity_type_enum),
|
|
2743
|
-
subject = ${this.getFollowupActivitySubject()},
|
|
2744
|
-
notes = ${normalizedNotes},
|
|
2745
|
-
due_at = CAST(${dueAt} AS TIMESTAMPTZ),
|
|
2746
|
-
priority = CAST(${'medium'} AS crm_activity_priority_enum),
|
|
2747
|
-
updated_at = NOW()
|
|
2748
|
-
WHERE id = ${existing.id}
|
|
2738
|
+
await tx.$executeRaw(api_prisma_1.Prisma.sql `
|
|
2739
|
+
UPDATE crm_activity
|
|
2740
|
+
SET
|
|
2741
|
+
owner_user_id = ${ownerUserId},
|
|
2742
|
+
type = CAST(${'task'} AS crm_activity_type_enum),
|
|
2743
|
+
subject = ${this.getFollowupActivitySubject()},
|
|
2744
|
+
notes = ${normalizedNotes},
|
|
2745
|
+
due_at = CAST(${dueAt} AS TIMESTAMPTZ),
|
|
2746
|
+
priority = CAST(${'medium'} AS crm_activity_priority_enum),
|
|
2747
|
+
updated_at = NOW()
|
|
2748
|
+
WHERE id = ${existing.id}
|
|
2749
2749
|
`);
|
|
2750
2750
|
return;
|
|
2751
2751
|
}
|
|
2752
|
-
await tx.$executeRaw(api_prisma_1.Prisma.sql `
|
|
2753
|
-
INSERT INTO crm_activity (
|
|
2754
|
-
person_id,
|
|
2755
|
-
owner_user_id,
|
|
2756
|
-
created_by_user_id,
|
|
2757
|
-
type,
|
|
2758
|
-
subject,
|
|
2759
|
-
notes,
|
|
2760
|
-
due_at,
|
|
2761
|
-
priority,
|
|
2762
|
-
source_kind,
|
|
2763
|
-
created_at,
|
|
2764
|
-
updated_at
|
|
2765
|
-
)
|
|
2766
|
-
VALUES (
|
|
2767
|
-
${personId},
|
|
2768
|
-
${ownerUserId},
|
|
2769
|
-
${actorUserId},
|
|
2770
|
-
CAST(${'task'} AS crm_activity_type_enum),
|
|
2771
|
-
${this.getFollowupActivitySubject()},
|
|
2772
|
-
${normalizedNotes},
|
|
2773
|
-
CAST(${dueAt} AS TIMESTAMPTZ),
|
|
2774
|
-
CAST(${'medium'} AS crm_activity_priority_enum),
|
|
2775
|
-
CAST(${'followup'} AS crm_activity_source_kind_enum),
|
|
2776
|
-
NOW(),
|
|
2777
|
-
NOW()
|
|
2778
|
-
)
|
|
2752
|
+
await tx.$executeRaw(api_prisma_1.Prisma.sql `
|
|
2753
|
+
INSERT INTO crm_activity (
|
|
2754
|
+
person_id,
|
|
2755
|
+
owner_user_id,
|
|
2756
|
+
created_by_user_id,
|
|
2757
|
+
type,
|
|
2758
|
+
subject,
|
|
2759
|
+
notes,
|
|
2760
|
+
due_at,
|
|
2761
|
+
priority,
|
|
2762
|
+
source_kind,
|
|
2763
|
+
created_at,
|
|
2764
|
+
updated_at
|
|
2765
|
+
)
|
|
2766
|
+
VALUES (
|
|
2767
|
+
${personId},
|
|
2768
|
+
${ownerUserId},
|
|
2769
|
+
${actorUserId},
|
|
2770
|
+
CAST(${'task'} AS crm_activity_type_enum),
|
|
2771
|
+
${this.getFollowupActivitySubject()},
|
|
2772
|
+
${normalizedNotes},
|
|
2773
|
+
CAST(${dueAt} AS TIMESTAMPTZ),
|
|
2774
|
+
CAST(${'medium'} AS crm_activity_priority_enum),
|
|
2775
|
+
CAST(${'followup'} AS crm_activity_source_kind_enum),
|
|
2776
|
+
NOW(),
|
|
2777
|
+
NOW()
|
|
2778
|
+
)
|
|
2779
2779
|
`);
|
|
2780
2780
|
}
|
|
2781
2781
|
async createCompletedInteractionActivity(tx, { personId, ownerUserId, interaction, actorUserId, }) {
|
|
2782
2782
|
const completedAt = new Date(interaction.created_at);
|
|
2783
|
-
await tx.$executeRaw(api_prisma_1.Prisma.sql `
|
|
2784
|
-
INSERT INTO crm_activity (
|
|
2785
|
-
person_id,
|
|
2786
|
-
owner_user_id,
|
|
2787
|
-
created_by_user_id,
|
|
2788
|
-
completed_by_user_id,
|
|
2789
|
-
type,
|
|
2790
|
-
subject,
|
|
2791
|
-
notes,
|
|
2792
|
-
due_at,
|
|
2793
|
-
completed_at,
|
|
2794
|
-
priority,
|
|
2795
|
-
source_kind,
|
|
2796
|
-
created_at,
|
|
2797
|
-
updated_at
|
|
2798
|
-
)
|
|
2799
|
-
VALUES (
|
|
2800
|
-
${personId},
|
|
2801
|
-
${ownerUserId},
|
|
2802
|
-
${actorUserId},
|
|
2803
|
-
${actorUserId},
|
|
2804
|
-
CAST(${interaction.type} AS crm_activity_type_enum),
|
|
2805
|
-
${this.getInteractionActivitySubject(interaction.type)},
|
|
2806
|
-
${this.normalizeTextOrNull(interaction.notes)},
|
|
2807
|
-
CAST(${interaction.created_at} AS TIMESTAMPTZ),
|
|
2808
|
-
CAST(${interaction.created_at} AS TIMESTAMPTZ),
|
|
2809
|
-
CAST(${'medium'} AS crm_activity_priority_enum),
|
|
2810
|
-
CAST(${'interaction'} AS crm_activity_source_kind_enum),
|
|
2811
|
-
CAST(${interaction.created_at} AS TIMESTAMPTZ),
|
|
2812
|
-
NOW()
|
|
2813
|
-
)
|
|
2783
|
+
await tx.$executeRaw(api_prisma_1.Prisma.sql `
|
|
2784
|
+
INSERT INTO crm_activity (
|
|
2785
|
+
person_id,
|
|
2786
|
+
owner_user_id,
|
|
2787
|
+
created_by_user_id,
|
|
2788
|
+
completed_by_user_id,
|
|
2789
|
+
type,
|
|
2790
|
+
subject,
|
|
2791
|
+
notes,
|
|
2792
|
+
due_at,
|
|
2793
|
+
completed_at,
|
|
2794
|
+
priority,
|
|
2795
|
+
source_kind,
|
|
2796
|
+
created_at,
|
|
2797
|
+
updated_at
|
|
2798
|
+
)
|
|
2799
|
+
VALUES (
|
|
2800
|
+
${personId},
|
|
2801
|
+
${ownerUserId},
|
|
2802
|
+
${actorUserId},
|
|
2803
|
+
${actorUserId},
|
|
2804
|
+
CAST(${interaction.type} AS crm_activity_type_enum),
|
|
2805
|
+
${this.getInteractionActivitySubject(interaction.type)},
|
|
2806
|
+
${this.normalizeTextOrNull(interaction.notes)},
|
|
2807
|
+
CAST(${interaction.created_at} AS TIMESTAMPTZ),
|
|
2808
|
+
CAST(${interaction.created_at} AS TIMESTAMPTZ),
|
|
2809
|
+
CAST(${'medium'} AS crm_activity_priority_enum),
|
|
2810
|
+
CAST(${'interaction'} AS crm_activity_source_kind_enum),
|
|
2811
|
+
CAST(${interaction.created_at} AS TIMESTAMPTZ),
|
|
2812
|
+
NOW()
|
|
2813
|
+
)
|
|
2814
2814
|
`);
|
|
2815
2815
|
}
|
|
2816
2816
|
getFollowupActivitySubject() {
|
|
@@ -3080,33 +3080,33 @@ let PersonService = class PersonService {
|
|
|
3080
3080
|
const searchLike = `%${search}%`;
|
|
3081
3081
|
const normalizedDigits = this.normalizeDigits(search);
|
|
3082
3082
|
const digitsLike = `%${normalizedDigits}%`;
|
|
3083
|
-
filters.push(api_prisma_1.Prisma.sql `
|
|
3084
|
-
AND (
|
|
3085
|
-
p.name ILIKE ${searchLike}
|
|
3086
|
-
OR COALESCE(pc.trade_name, '') ILIKE ${searchLike}
|
|
3087
|
-
OR COALESCE(pc.city, '') ILIKE ${searchLike}
|
|
3088
|
-
OR COALESCE(pc.state, '') ILIKE ${searchLike}
|
|
3089
|
-
OR EXISTS (
|
|
3090
|
-
SELECT 1
|
|
3091
|
-
FROM contact c
|
|
3092
|
-
INNER JOIN contact_type ct ON ct.id = c.contact_type_id
|
|
3093
|
-
WHERE c.person_id = p.id
|
|
3094
|
-
AND UPPER(ct.code) = 'EMAIL'
|
|
3095
|
-
AND c.value ILIKE ${searchLike}
|
|
3096
|
-
)
|
|
3083
|
+
filters.push(api_prisma_1.Prisma.sql `
|
|
3084
|
+
AND (
|
|
3085
|
+
p.name ILIKE ${searchLike}
|
|
3086
|
+
OR COALESCE(pc.trade_name, '') ILIKE ${searchLike}
|
|
3087
|
+
OR COALESCE(pc.city, '') ILIKE ${searchLike}
|
|
3088
|
+
OR COALESCE(pc.state, '') ILIKE ${searchLike}
|
|
3089
|
+
OR EXISTS (
|
|
3090
|
+
SELECT 1
|
|
3091
|
+
FROM contact c
|
|
3092
|
+
INNER JOIN contact_type ct ON ct.id = c.contact_type_id
|
|
3093
|
+
WHERE c.person_id = p.id
|
|
3094
|
+
AND UPPER(ct.code) = 'EMAIL'
|
|
3095
|
+
AND c.value ILIKE ${searchLike}
|
|
3096
|
+
)
|
|
3097
3097
|
${normalizedDigits.length > 0
|
|
3098
|
-
? api_prisma_1.Prisma.sql `
|
|
3099
|
-
OR EXISTS (
|
|
3100
|
-
SELECT 1
|
|
3101
|
-
FROM contact c
|
|
3102
|
-
INNER JOIN contact_type ct ON ct.id = c.contact_type_id
|
|
3103
|
-
WHERE c.person_id = p.id
|
|
3104
|
-
AND UPPER(ct.code) IN ('PHONE', 'MOBILE', 'WHATSAPP')
|
|
3105
|
-
AND regexp_replace(COALESCE(c.value, ''), '[^0-9]+', '', 'g') ILIKE ${digitsLike}
|
|
3106
|
-
)
|
|
3098
|
+
? api_prisma_1.Prisma.sql `
|
|
3099
|
+
OR EXISTS (
|
|
3100
|
+
SELECT 1
|
|
3101
|
+
FROM contact c
|
|
3102
|
+
INNER JOIN contact_type ct ON ct.id = c.contact_type_id
|
|
3103
|
+
WHERE c.person_id = p.id
|
|
3104
|
+
AND UPPER(ct.code) IN ('PHONE', 'MOBILE', 'WHATSAPP')
|
|
3105
|
+
AND regexp_replace(COALESCE(c.value, ''), '[^0-9]+', '', 'g') ILIKE ${digitsLike}
|
|
3106
|
+
)
|
|
3107
3107
|
`
|
|
3108
|
-
: api_prisma_1.Prisma.empty}
|
|
3109
|
-
)
|
|
3108
|
+
: api_prisma_1.Prisma.empty}
|
|
3109
|
+
)
|
|
3110
3110
|
`);
|
|
3111
3111
|
}
|
|
3112
3112
|
return filters.length > 0 ? api_prisma_1.Prisma.join(filters, '\n') : api_prisma_1.Prisma.empty;
|
|
@@ -3156,13 +3156,13 @@ let PersonService = class PersonService {
|
|
|
3156
3156
|
}
|
|
3157
3157
|
if (search) {
|
|
3158
3158
|
const searchLike = `%${search}%`;
|
|
3159
|
-
filters.push(api_prisma_1.Prisma.sql `
|
|
3160
|
-
AND (
|
|
3161
|
-
a.subject ILIKE ${searchLike}
|
|
3162
|
-
OR COALESCE(a.notes, '') ILIKE ${searchLike}
|
|
3163
|
-
OR p.name ILIKE ${searchLike}
|
|
3164
|
-
OR COALESCE(owner_user.name, '') ILIKE ${searchLike}
|
|
3165
|
-
)
|
|
3159
|
+
filters.push(api_prisma_1.Prisma.sql `
|
|
3160
|
+
AND (
|
|
3161
|
+
a.subject ILIKE ${searchLike}
|
|
3162
|
+
OR COALESCE(a.notes, '') ILIKE ${searchLike}
|
|
3163
|
+
OR p.name ILIKE ${searchLike}
|
|
3164
|
+
OR COALESCE(owner_user.name, '') ILIKE ${searchLike}
|
|
3165
|
+
)
|
|
3166
3166
|
`);
|
|
3167
3167
|
}
|
|
3168
3168
|
return filters.length > 0 ? api_prisma_1.Prisma.join(filters, '\n') : api_prisma_1.Prisma.empty;
|
|
@@ -3243,16 +3243,16 @@ let PersonService = class PersonService {
|
|
|
3243
3243
|
}
|
|
3244
3244
|
async findPersonIdsByNormalizedDigits(normalizedDigits) {
|
|
3245
3245
|
const likeValue = `%${normalizedDigits}%`;
|
|
3246
|
-
const rows = await this.prismaService.$queryRaw(api_prisma_1.Prisma.sql `
|
|
3247
|
-
SELECT DISTINCT p.id
|
|
3248
|
-
FROM person p
|
|
3249
|
-
LEFT JOIN contact c ON c.person_id = p.id
|
|
3250
|
-
LEFT JOIN document d ON d.person_id = p.id
|
|
3251
|
-
LEFT JOIN person_address pa ON pa.person_id = p.id
|
|
3252
|
-
LEFT JOIN address a ON a.id = pa.address_id
|
|
3253
|
-
WHERE regexp_replace(COALESCE(c.value, ''), '[^0-9]+', '', 'g') ILIKE ${likeValue}
|
|
3254
|
-
OR regexp_replace(COALESCE(d.value, ''), '[^0-9]+', '', 'g') ILIKE ${likeValue}
|
|
3255
|
-
OR regexp_replace(COALESCE(a.postal_code, ''), '[^0-9]+', '', 'g') ILIKE ${likeValue}
|
|
3246
|
+
const rows = await this.prismaService.$queryRaw(api_prisma_1.Prisma.sql `
|
|
3247
|
+
SELECT DISTINCT p.id
|
|
3248
|
+
FROM person p
|
|
3249
|
+
LEFT JOIN contact c ON c.person_id = p.id
|
|
3250
|
+
LEFT JOIN document d ON d.person_id = p.id
|
|
3251
|
+
LEFT JOIN person_address pa ON pa.person_id = p.id
|
|
3252
|
+
LEFT JOIN address a ON a.id = pa.address_id
|
|
3253
|
+
WHERE regexp_replace(COALESCE(c.value, ''), '[^0-9]+', '', 'g') ILIKE ${likeValue}
|
|
3254
|
+
OR regexp_replace(COALESCE(d.value, ''), '[^0-9]+', '', 'g') ILIKE ${likeValue}
|
|
3255
|
+
OR regexp_replace(COALESCE(a.postal_code, ''), '[^0-9]+', '', 'g') ILIKE ${likeValue}
|
|
3256
3256
|
`);
|
|
3257
3257
|
return rows.map((row) => row.id);
|
|
3258
3258
|
}
|