@talkpilot/core-db 1.3.9 → 1.3.12
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/.cursor/rules/development.mdc +65 -65
- package/DEVELOPMENT.md +141 -141
- package/README.md +297 -257
- package/README_OLD.md +160 -160
- package/dist/municipal/tickets/index.d.ts +1 -1
- package/dist/municipal/tickets/index.d.ts.map +1 -1
- package/dist/municipal/tickets/tickets.statistics.aggregation.d.ts +34 -0
- package/dist/municipal/tickets/tickets.statistics.aggregation.d.ts.map +1 -1
- package/dist/municipal/tickets/tickets.statistics.aggregation.js +14 -1
- package/dist/municipal/tickets/tickets.statistics.aggregation.js.map +1 -1
- package/dist/municipal/tickets/tickets.statistics.getters.d.ts.map +1 -1
- package/dist/municipal/tickets/tickets.statistics.getters.js +15 -6
- package/dist/municipal/tickets/tickets.statistics.getters.js.map +1 -1
- package/dist/municipal/tickets/tickets.types.d.ts +1 -0
- package/dist/municipal/tickets/tickets.types.d.ts.map +1 -1
- package/dist/talkpilot/calls/calls.dashboard.d.ts +3 -0
- package/dist/talkpilot/calls/calls.dashboard.d.ts.map +1 -0
- package/dist/talkpilot/calls/calls.dashboard.js +191 -0
- package/dist/talkpilot/calls/calls.dashboard.js.map +1 -0
- package/dist/talkpilot/calls/calls.statistics.getters.d.ts.map +1 -1
- package/dist/talkpilot/calls/calls.statistics.getters.js +39 -10
- package/dist/talkpilot/calls/calls.statistics.getters.js.map +1 -1
- package/dist/talkpilot/calls/calls.statistics.types.d.ts +1 -0
- package/dist/talkpilot/calls/calls.statistics.types.d.ts.map +1 -1
- package/dist/talkpilot/clientsConfig/clientsConfig.types.d.ts +1 -1
- package/dist/talkpilot/clientsConfig/clientsConfig.types.d.ts.map +1 -1
- package/dist/talkpilot/contextNotes/contextNotes.getters.d.ts.map +1 -1
- package/dist/talkpilot/contextNotes/contextNotes.getters.js +1 -3
- package/dist/talkpilot/contextNotes/contextNotes.getters.js.map +1 -1
- package/dist/test-utils/factories/talkpilot/contextNotes.d.ts.map +1 -1
- package/dist/test-utils/factories/talkpilot/contextNotes.js +4 -1
- package/dist/test-utils/factories/talkpilot/contextNotes.js.map +1 -1
- package/dist/utils/date.utils.d.ts.map +1 -1
- package/dist/utils/date.utils.js +7 -2
- package/dist/utils/date.utils.js.map +1 -1
- package/jest.config.js +20 -20
- package/package.json +46 -46
- package/src/municipal/muniIssues/__tests__/muniIssues.setters.spec.ts +94 -92
- package/src/municipal/tickets/__tests__/tickets.statistics.spec.ts +99 -68
- package/src/municipal/tickets/index.ts +9 -3
- package/src/municipal/tickets/tickets.statistics.aggregation.ts +110 -96
- package/src/municipal/tickets/tickets.statistics.getters.ts +132 -109
- package/src/municipal/tickets/tickets.types.ts +54 -53
- package/src/talkpilot/calls/__tests__/calls.statistics.spec.ts +481 -375
- package/src/talkpilot/calls/calls.statistics.getters.ts +668 -590
- package/src/talkpilot/calls/calls.statistics.types.ts +48 -47
- package/src/talkpilot/clientsConfig/clientsConfig.types.ts +127 -127
- package/src/talkpilot/contextNotes/__tests__/contextNotes.getters.spec.ts +217 -176
- package/src/talkpilot/contextNotes/contextNotes.getters.ts +85 -86
- package/src/talkpilot/products/__tests__/products.getters.spec.ts +44 -45
- package/src/test-utils/factories/talkpilot/contextNotes.ts +40 -33
- package/src/utils/date.utils.ts +126 -116
- package/tsconfig.json +23 -23
- package/.claude/settings.local.json +0 -11
- package/dist/municipal/tickets/tickets.deprecated.getters.d.ts +0 -12
- package/dist/municipal/tickets/tickets.deprecated.getters.d.ts.map +0 -1
- package/dist/municipal/tickets/tickets.deprecated.getters.js +0 -131
- package/dist/municipal/tickets/tickets.deprecated.getters.js.map +0 -1
- package/dist/municipal/tickets/tickets.statistics.dates.d.ts +0 -7
- package/dist/municipal/tickets/tickets.statistics.dates.d.ts.map +0 -1
- package/dist/municipal/tickets/tickets.statistics.dates.js +0 -40
- package/dist/municipal/tickets/tickets.statistics.dates.js.map +0 -1
- package/dist/municipal/tickets/tickets.statistics.pipeline.d.ts +0 -53
- package/dist/municipal/tickets/tickets.statistics.pipeline.d.ts.map +0 -1
- package/dist/municipal/tickets/tickets.statistics.pipeline.js +0 -112
- package/dist/municipal/tickets/tickets.statistics.pipeline.js.map +0 -1
- package/dist/municipal/tickets/tickets.statistics.utils.d.ts +0 -7
- package/dist/municipal/tickets/tickets.statistics.utils.d.ts.map +0 -1
- package/dist/municipal/tickets/tickets.statistics.utils.js +0 -40
- package/dist/municipal/tickets/tickets.statistics.utils.js.map +0 -1
- package/dist/talkpilot/calls/calls.statistics.ticketScope.d.ts +0 -12
- package/dist/talkpilot/calls/calls.statistics.ticketScope.d.ts.map +0 -1
- package/dist/talkpilot/calls/calls.statistics.ticketScope.js +0 -37
- package/dist/talkpilot/calls/calls.statistics.ticketScope.js.map +0 -1
- package/dist/talkpilot/calls/calls.statistics.tickets.d.ts +0 -17
- package/dist/talkpilot/calls/calls.statistics.tickets.d.ts.map +0 -1
- package/dist/talkpilot/calls/calls.statistics.tickets.js +0 -33
- package/dist/talkpilot/calls/calls.statistics.tickets.js.map +0 -1
- package/dist/utils/statistics.aggregation.d.ts +0 -20
- package/dist/utils/statistics.aggregation.d.ts.map +0 -1
- package/dist/utils/statistics.aggregation.js +0 -43
- package/dist/utils/statistics.aggregation.js.map +0 -1
package/jest.config.js
CHANGED
|
@@ -1,20 +1,20 @@
|
|
|
1
|
-
/** @type {import('ts-jest').JestConfigWithTsJest} */
|
|
2
|
-
module.exports = {
|
|
3
|
-
preset: 'ts-jest',
|
|
4
|
-
testEnvironment: 'node',
|
|
5
|
-
roots: ['<rootDir>/src'],
|
|
6
|
-
testPathIgnorePatterns: ['<rootDir>/src/__tests__/legacy/'],
|
|
7
|
-
testMatch: ['**/__tests__/**/*.spec.ts', '**/*.spec.ts'],
|
|
8
|
-
transform: {
|
|
9
|
-
'^.+\\.tsx?$': ['ts-jest', {
|
|
10
|
-
tsconfig: 'tsconfig.json',
|
|
11
|
-
}],
|
|
12
|
-
},
|
|
13
|
-
setupFilesAfterEnv: ['<rootDir>/src/__tests__/setup.ts'],
|
|
14
|
-
maxWorkers: 1,
|
|
15
|
-
verbose: true,
|
|
16
|
-
forceExit: true,
|
|
17
|
-
clearMocks: true,
|
|
18
|
-
resetMocks: true,
|
|
19
|
-
restoreMocks: true,
|
|
20
|
-
};
|
|
1
|
+
/** @type {import('ts-jest').JestConfigWithTsJest} */
|
|
2
|
+
module.exports = {
|
|
3
|
+
preset: 'ts-jest',
|
|
4
|
+
testEnvironment: 'node',
|
|
5
|
+
roots: ['<rootDir>/src'],
|
|
6
|
+
testPathIgnorePatterns: ['<rootDir>/src/__tests__/legacy/'],
|
|
7
|
+
testMatch: ['**/__tests__/**/*.spec.ts', '**/*.spec.ts'],
|
|
8
|
+
transform: {
|
|
9
|
+
'^.+\\.tsx?$': ['ts-jest', {
|
|
10
|
+
tsconfig: 'tsconfig.json',
|
|
11
|
+
}],
|
|
12
|
+
},
|
|
13
|
+
setupFilesAfterEnv: ['<rootDir>/src/__tests__/setup.ts'],
|
|
14
|
+
maxWorkers: 1,
|
|
15
|
+
verbose: true,
|
|
16
|
+
forceExit: true,
|
|
17
|
+
clearMocks: true,
|
|
18
|
+
resetMocks: true,
|
|
19
|
+
restoreMocks: true,
|
|
20
|
+
};
|
package/package.json
CHANGED
|
@@ -1,46 +1,46 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@talkpilot/core-db",
|
|
3
|
-
"version": "1.3.
|
|
4
|
-
"description": "Core database package for centralized connections and ORM integration.",
|
|
5
|
-
"main": "dist/index.js",
|
|
6
|
-
"types": "dist/index.d.ts",
|
|
7
|
-
"scripts": {
|
|
8
|
-
"build": "tsc",
|
|
9
|
-
"dev": "tsc --watch",
|
|
10
|
-
"test": "jest",
|
|
11
|
-
"lint": "eslint 'src/**/*.{ts,tsx}'",
|
|
12
|
-
"format": "prettier --write \"src/**/*.{ts,tsx}\"",
|
|
13
|
-
"prepare": "npm run build"
|
|
14
|
-
},
|
|
15
|
-
"keywords": [
|
|
16
|
-
"database",
|
|
17
|
-
"orm",
|
|
18
|
-
"typescript",
|
|
19
|
-
"postgres",
|
|
20
|
-
"db-client"
|
|
21
|
-
],
|
|
22
|
-
"author": "",
|
|
23
|
-
"license": "MIT",
|
|
24
|
-
"dependencies": {
|
|
25
|
-
"dayjs": "^1.11.21",
|
|
26
|
-
"express": "^4.18.0",
|
|
27
|
-
"google-libphonenumber": "^3.2.0",
|
|
28
|
-
"mongodb": "^6.11.0"
|
|
29
|
-
},
|
|
30
|
-
"devDependencies": {
|
|
31
|
-
"@faker-js/faker": "^8.0.0",
|
|
32
|
-
"@types/express": "^4.17.0",
|
|
33
|
-
"@types/google-libphonenumber": "^7.4.0",
|
|
34
|
-
"@types/jest": "^29.0.0",
|
|
35
|
-
"@types/node": "^20.0.0",
|
|
36
|
-
"fishery": "^2.4.0",
|
|
37
|
-
"jest": "^29.0.0",
|
|
38
|
-
"mongodb-memory-server": "^10.0.0",
|
|
39
|
-
"prettier": "^3.8.2",
|
|
40
|
-
"ts-jest": "^29.0.0",
|
|
41
|
-
"typescript": "^5.0.0"
|
|
42
|
-
},
|
|
43
|
-
"publishConfig": {
|
|
44
|
-
"access": "public"
|
|
45
|
-
}
|
|
46
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "@talkpilot/core-db",
|
|
3
|
+
"version": "1.3.12",
|
|
4
|
+
"description": "Core database package for centralized connections and ORM integration.",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
7
|
+
"scripts": {
|
|
8
|
+
"build": "tsc",
|
|
9
|
+
"dev": "tsc --watch",
|
|
10
|
+
"test": "jest",
|
|
11
|
+
"lint": "eslint 'src/**/*.{ts,tsx}'",
|
|
12
|
+
"format": "prettier --write \"src/**/*.{ts,tsx}\"",
|
|
13
|
+
"prepare": "npm run build"
|
|
14
|
+
},
|
|
15
|
+
"keywords": [
|
|
16
|
+
"database",
|
|
17
|
+
"orm",
|
|
18
|
+
"typescript",
|
|
19
|
+
"postgres",
|
|
20
|
+
"db-client"
|
|
21
|
+
],
|
|
22
|
+
"author": "",
|
|
23
|
+
"license": "MIT",
|
|
24
|
+
"dependencies": {
|
|
25
|
+
"dayjs": "^1.11.21",
|
|
26
|
+
"express": "^4.18.0",
|
|
27
|
+
"google-libphonenumber": "^3.2.0",
|
|
28
|
+
"mongodb": "^6.11.0"
|
|
29
|
+
},
|
|
30
|
+
"devDependencies": {
|
|
31
|
+
"@faker-js/faker": "^8.0.0",
|
|
32
|
+
"@types/express": "^4.17.0",
|
|
33
|
+
"@types/google-libphonenumber": "^7.4.0",
|
|
34
|
+
"@types/jest": "^29.0.0",
|
|
35
|
+
"@types/node": "^20.0.0",
|
|
36
|
+
"fishery": "^2.4.0",
|
|
37
|
+
"jest": "^29.0.0",
|
|
38
|
+
"mongodb-memory-server": "^10.0.0",
|
|
39
|
+
"prettier": "^3.8.2",
|
|
40
|
+
"ts-jest": "^29.0.0",
|
|
41
|
+
"typescript": "^5.0.0"
|
|
42
|
+
},
|
|
43
|
+
"publishConfig": {
|
|
44
|
+
"access": "public"
|
|
45
|
+
}
|
|
46
|
+
}
|
|
@@ -1,92 +1,94 @@
|
|
|
1
|
-
import { createMuniIssue } from "../muniIssues.setters";
|
|
2
|
-
import {
|
|
3
|
-
generateMuniIssueId,
|
|
4
|
-
getMuniIssueById,
|
|
5
|
-
getMuniIssueByJiraKey,
|
|
6
|
-
} from "../muniIssues.getters";
|
|
7
|
-
import { createMuniIssueInput } from "../../../test-utils/factories";
|
|
8
|
-
|
|
9
|
-
describe("muniIssues setters", () => {
|
|
10
|
-
describe("createMuniIssue", () => {
|
|
11
|
-
it("should insert a well-formed document with createdAt and nested content/jira", async () => {
|
|
12
|
-
const input = createMuniIssueInput();
|
|
13
|
-
const id = generateMuniIssueId();
|
|
14
|
-
|
|
15
|
-
const insertedId = await createMuniIssue(input, id);
|
|
16
|
-
|
|
17
|
-
const saved = await getMuniIssueById(insertedId.toString());
|
|
18
|
-
expect(saved).toMatchObject({
|
|
19
|
-
callSid: input.callSid,
|
|
20
|
-
clientId: input.clientId,
|
|
21
|
-
cityName: input.cityName,
|
|
22
|
-
issueContent: input.issueContent,
|
|
23
|
-
jira: input.jira,
|
|
24
|
-
});
|
|
25
|
-
expect(saved?.createdAt).toBeInstanceOf(Date);
|
|
26
|
-
});
|
|
27
|
-
|
|
28
|
-
it("should default jira.syncStatus to created when not provided", async () => {
|
|
29
|
-
const id = generateMuniIssueId();
|
|
30
|
-
|
|
31
|
-
const insertedId = await createMuniIssue(
|
|
32
|
-
createMuniIssueInput({ jira: { key: "CP-9" } }),
|
|
33
|
-
id,
|
|
34
|
-
);
|
|
35
|
-
|
|
36
|
-
const saved = await getMuniIssueById(insertedId.toString());
|
|
37
|
-
expect(saved?.jira.syncStatus).toBe("created");
|
|
38
|
-
});
|
|
39
|
-
|
|
40
|
-
it("should store long issueDescription and desiredBehavior in full", async () => {
|
|
41
|
-
const issueDescription = "a".repeat(2000);
|
|
42
|
-
const desiredBehavior = "b".repeat(2000);
|
|
43
|
-
const id = generateMuniIssueId();
|
|
44
|
-
|
|
45
|
-
const insertedId = await createMuniIssue(
|
|
46
|
-
createMuniIssueInput({
|
|
47
|
-
issueContent: {
|
|
48
|
-
issuerName: "Dana",
|
|
49
|
-
issuerRole: "Agent",
|
|
50
|
-
issueDescription,
|
|
51
|
-
desiredBehavior,
|
|
52
|
-
},
|
|
53
|
-
}),
|
|
54
|
-
id,
|
|
55
|
-
);
|
|
56
|
-
|
|
57
|
-
const saved = await getMuniIssueById(insertedId.toString());
|
|
58
|
-
expect(saved?.issueContent.issueDescription).toHaveLength(2000);
|
|
59
|
-
expect(saved?.issueContent.desiredBehavior).toBe(desiredBehavior);
|
|
60
|
-
});
|
|
61
|
-
|
|
62
|
-
it("should persist the caller-supplied _id so the Jira ticket can link back", async () => {
|
|
63
|
-
const id = generateMuniIssueId();
|
|
64
|
-
|
|
65
|
-
const insertedId = await createMuniIssue(createMuniIssueInput(), id);
|
|
66
|
-
|
|
67
|
-
expect(insertedId.toString()).toBe(id.toString());
|
|
68
|
-
expect(await getMuniIssueById(id.toString())).not.toBeNull();
|
|
69
|
-
});
|
|
70
|
-
});
|
|
71
|
-
|
|
72
|
-
describe("getMuniIssueById", () => {
|
|
73
|
-
it("should return null for an unknown or malformed id instead of throwing", async () => {
|
|
74
|
-
expect(
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
});
|
|
1
|
+
import { createMuniIssue } from "../muniIssues.setters";
|
|
2
|
+
import {
|
|
3
|
+
generateMuniIssueId,
|
|
4
|
+
getMuniIssueById,
|
|
5
|
+
getMuniIssueByJiraKey,
|
|
6
|
+
} from "../muniIssues.getters";
|
|
7
|
+
import { createMuniIssueInput } from "../../../test-utils/factories";
|
|
8
|
+
|
|
9
|
+
describe("muniIssues setters", () => {
|
|
10
|
+
describe("createMuniIssue", () => {
|
|
11
|
+
it("should insert a well-formed document with createdAt and nested content/jira", async () => {
|
|
12
|
+
const input = createMuniIssueInput();
|
|
13
|
+
const id = generateMuniIssueId();
|
|
14
|
+
|
|
15
|
+
const insertedId = await createMuniIssue(input, id);
|
|
16
|
+
|
|
17
|
+
const saved = await getMuniIssueById(insertedId.toString());
|
|
18
|
+
expect(saved).toMatchObject({
|
|
19
|
+
callSid: input.callSid,
|
|
20
|
+
clientId: input.clientId,
|
|
21
|
+
cityName: input.cityName,
|
|
22
|
+
issueContent: input.issueContent,
|
|
23
|
+
jira: input.jira,
|
|
24
|
+
});
|
|
25
|
+
expect(saved?.createdAt).toBeInstanceOf(Date);
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
it("should default jira.syncStatus to created when not provided", async () => {
|
|
29
|
+
const id = generateMuniIssueId();
|
|
30
|
+
|
|
31
|
+
const insertedId = await createMuniIssue(
|
|
32
|
+
createMuniIssueInput({ jira: { key: "CP-9" } }),
|
|
33
|
+
id,
|
|
34
|
+
);
|
|
35
|
+
|
|
36
|
+
const saved = await getMuniIssueById(insertedId.toString());
|
|
37
|
+
expect(saved?.jira.syncStatus).toBe("created");
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
it("should store long issueDescription and desiredBehavior in full", async () => {
|
|
41
|
+
const issueDescription = "a".repeat(2000);
|
|
42
|
+
const desiredBehavior = "b".repeat(2000);
|
|
43
|
+
const id = generateMuniIssueId();
|
|
44
|
+
|
|
45
|
+
const insertedId = await createMuniIssue(
|
|
46
|
+
createMuniIssueInput({
|
|
47
|
+
issueContent: {
|
|
48
|
+
issuerName: "Dana",
|
|
49
|
+
issuerRole: "Agent",
|
|
50
|
+
issueDescription,
|
|
51
|
+
desiredBehavior,
|
|
52
|
+
},
|
|
53
|
+
}),
|
|
54
|
+
id,
|
|
55
|
+
);
|
|
56
|
+
|
|
57
|
+
const saved = await getMuniIssueById(insertedId.toString());
|
|
58
|
+
expect(saved?.issueContent.issueDescription).toHaveLength(2000);
|
|
59
|
+
expect(saved?.issueContent.desiredBehavior).toBe(desiredBehavior);
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
it("should persist the caller-supplied _id so the Jira ticket can link back", async () => {
|
|
63
|
+
const id = generateMuniIssueId();
|
|
64
|
+
|
|
65
|
+
const insertedId = await createMuniIssue(createMuniIssueInput(), id);
|
|
66
|
+
|
|
67
|
+
expect(insertedId.toString()).toBe(id.toString());
|
|
68
|
+
expect(await getMuniIssueById(id.toString())).not.toBeNull();
|
|
69
|
+
});
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
describe("getMuniIssueById", () => {
|
|
73
|
+
it("should return null for an unknown or malformed id instead of throwing", async () => {
|
|
74
|
+
expect(
|
|
75
|
+
await getMuniIssueById(generateMuniIssueId().toString()),
|
|
76
|
+
).toBeNull();
|
|
77
|
+
expect(await getMuniIssueById("not-a-valid-id")).toBeNull();
|
|
78
|
+
});
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
describe("getMuniIssueByJiraKey", () => {
|
|
82
|
+
it("should find the issue with the given Jira key", async () => {
|
|
83
|
+
await createMuniIssue(
|
|
84
|
+
createMuniIssueInput({ jira: { key: "CP-555" } }),
|
|
85
|
+
generateMuniIssueId(),
|
|
86
|
+
);
|
|
87
|
+
|
|
88
|
+
const found = await getMuniIssueByJiraKey("CP-555");
|
|
89
|
+
|
|
90
|
+
expect(found?.jira.key).toBe("CP-555");
|
|
91
|
+
expect(await getMuniIssueByJiraKey("CP-nope")).toBeNull();
|
|
92
|
+
});
|
|
93
|
+
});
|
|
94
|
+
});
|
|
@@ -1,68 +1,99 @@
|
|
|
1
|
-
import {
|
|
2
|
-
findCallSidDraftTicketCountsByCity,
|
|
3
|
-
findCallSidTicketCountsByCity,
|
|
4
|
-
getTicketsCollection,
|
|
5
|
-
ticketStatsDateScopeFromYmd,
|
|
6
|
-
} from "../../../index";
|
|
7
|
-
import { createTicket } from "../../../test-utils/factories";
|
|
8
|
-
|
|
9
|
-
const CITY = "tests" as const;
|
|
10
|
-
const TZ = "Asia/Jerusalem";
|
|
11
|
-
const mayScope = () =>
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
await
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
createTicket({
|
|
60
|
-
cityName: CITY,
|
|
61
|
-
callSid: "CA-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
1
|
+
import {
|
|
2
|
+
findCallSidDraftTicketCountsByCity,
|
|
3
|
+
findCallSidTicketCountsByCity,
|
|
4
|
+
getTicketsCollection,
|
|
5
|
+
ticketStatsDateScopeFromYmd,
|
|
6
|
+
} from "../../../index";
|
|
7
|
+
import { createTicket } from "../../../test-utils/factories";
|
|
8
|
+
|
|
9
|
+
const CITY = "tests" as const;
|
|
10
|
+
const TZ = "Asia/Jerusalem";
|
|
11
|
+
const mayScope = () =>
|
|
12
|
+
ticketStatsDateScopeFromYmd("2026-05-01", "2026-05-31", TZ);
|
|
13
|
+
|
|
14
|
+
describe("tickets statistics getters", () => {
|
|
15
|
+
it("should scope callSid lookups to the provided createdAt range", async () => {
|
|
16
|
+
await getTicketsCollection().insertMany([
|
|
17
|
+
createTicket({
|
|
18
|
+
cityName: CITY,
|
|
19
|
+
callSid: "CA-in-range",
|
|
20
|
+
createdAt: new Date("2026-05-15T10:00:00.000Z"),
|
|
21
|
+
updatedAt: new Date("2026-05-15T10:00:00.000Z"),
|
|
22
|
+
}),
|
|
23
|
+
createTicket({
|
|
24
|
+
cityName: CITY,
|
|
25
|
+
callSid: "CA-out-of-range",
|
|
26
|
+
createdAt: new Date("2024-01-01T10:00:00.000Z"),
|
|
27
|
+
updatedAt: new Date("2024-01-01T10:00:00.000Z"),
|
|
28
|
+
}),
|
|
29
|
+
]);
|
|
30
|
+
expect(await findCallSidTicketCountsByCity(CITY, mayScope())).toEqual(
|
|
31
|
+
new Map([["CA-in-range", 1]]),
|
|
32
|
+
);
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
it("should treat whitespace-only event_subject_id as draft for legacy tickets", async () => {
|
|
36
|
+
await getTicketsCollection().insertMany([
|
|
37
|
+
createTicket({
|
|
38
|
+
cityName: CITY,
|
|
39
|
+
callSid: "CA-draft-whitespace",
|
|
40
|
+
createdAt: new Date("2026-05-15T10:00:00.000Z"),
|
|
41
|
+
updatedAt: new Date("2026-05-15T10:00:00.000Z"),
|
|
42
|
+
externalCallFields: { event_subject_id: " \t " },
|
|
43
|
+
}),
|
|
44
|
+
createTicket({
|
|
45
|
+
cityName: CITY,
|
|
46
|
+
callSid: "CA-not-draft",
|
|
47
|
+
createdAt: new Date("2026-05-16T10:00:00.000Z"),
|
|
48
|
+
updatedAt: new Date("2026-05-16T10:00:00.000Z"),
|
|
49
|
+
externalCallFields: { event_subject_id: "100" },
|
|
50
|
+
}),
|
|
51
|
+
]);
|
|
52
|
+
expect(await findCallSidDraftTicketCountsByCity(CITY, mayScope())).toEqual(
|
|
53
|
+
new Map([["CA-draft-whitespace", 1]]),
|
|
54
|
+
);
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
it("should use isDraft when set, overriding legacy heuristics", async () => {
|
|
58
|
+
await getTicketsCollection().insertMany([
|
|
59
|
+
createTicket({
|
|
60
|
+
cityName: CITY,
|
|
61
|
+
callSid: "CA-explicit-draft",
|
|
62
|
+
isDraft: true,
|
|
63
|
+
createdAt: new Date("2026-05-15T10:00:00.000Z"),
|
|
64
|
+
updatedAt: new Date("2026-05-15T10:00:00.000Z"),
|
|
65
|
+
externalCallFields: { event_subject_id: "100" },
|
|
66
|
+
}),
|
|
67
|
+
createTicket({
|
|
68
|
+
cityName: CITY,
|
|
69
|
+
callSid: "CA-explicit-not-draft",
|
|
70
|
+
isDraft: false,
|
|
71
|
+
createdAt: new Date("2026-05-16T10:00:00.000Z"),
|
|
72
|
+
updatedAt: new Date("2026-05-16T10:00:00.000Z"),
|
|
73
|
+
externalCallFields: {},
|
|
74
|
+
}),
|
|
75
|
+
]);
|
|
76
|
+
expect(await findCallSidDraftTicketCountsByCity(CITY, mayScope())).toEqual(
|
|
77
|
+
new Map([["CA-explicit-draft", 1]]),
|
|
78
|
+
);
|
|
79
|
+
});
|
|
80
|
+
it("should count multiple tickets on the same callSid", async () => {
|
|
81
|
+
await getTicketsCollection().insertMany([
|
|
82
|
+
createTicket({
|
|
83
|
+
cityName: CITY,
|
|
84
|
+
callSid: "CA-multi",
|
|
85
|
+
createdAt: new Date("2026-05-15T10:00:00.000Z"),
|
|
86
|
+
updatedAt: new Date("2026-05-15T10:00:00.000Z"),
|
|
87
|
+
}),
|
|
88
|
+
createTicket({
|
|
89
|
+
cityName: CITY,
|
|
90
|
+
callSid: "CA-multi",
|
|
91
|
+
createdAt: new Date("2026-05-15T11:00:00.000Z"),
|
|
92
|
+
updatedAt: new Date("2026-05-15T11:00:00.000Z"),
|
|
93
|
+
}),
|
|
94
|
+
]);
|
|
95
|
+
expect(await findCallSidTicketCountsByCity(CITY, mayScope())).toEqual(
|
|
96
|
+
new Map([["CA-multi", 2]]),
|
|
97
|
+
);
|
|
98
|
+
});
|
|
99
|
+
});
|
|
@@ -1,3 +1,9 @@
|
|
|
1
|
-
export * from "./tickets.getters";
|
|
2
|
-
export * from "./tickets.statistics.getters";
|
|
3
|
-
export type {
|
|
1
|
+
export * from "./tickets.getters";
|
|
2
|
+
export * from "./tickets.statistics.getters";
|
|
3
|
+
export type {
|
|
4
|
+
Ticket,
|
|
5
|
+
TicketDoc,
|
|
6
|
+
SubjectItem,
|
|
7
|
+
TicketStatsDateScope,
|
|
8
|
+
TicketSubjectRow,
|
|
9
|
+
} from "./tickets.types";
|