@webitel/api-services 26.8.66 → 26.8.68

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@webitel/api-services",
3
- "version": "26.8.66",
3
+ "version": "26.8.68",
4
4
  "private": false,
5
5
  "repository": {
6
6
  "type": "git",
@@ -3,12 +3,14 @@ import { beforeEach, describe, expect, it, vi } from 'vitest';
3
3
  const searchMemberInQueue = vi.fn();
4
4
  const resetMembersCount = vi.fn();
5
5
  const resetMembers = vi.fn();
6
+ const searchMemberCommunication = vi.fn();
6
7
 
7
8
  vi.mock('../../../../gen-wire', () => ({
8
9
  getMemberService: () => ({
9
10
  searchMemberInQueue,
10
11
  resetMembersCount,
11
12
  resetMembers,
13
+ searchMemberCommunication,
12
14
  }),
13
15
  }));
14
16
 
@@ -173,3 +175,68 @@ describe('QueueMembersAPI.getQuantity', () => {
173
175
  ).resolves.toBe(0);
174
176
  });
175
177
  });
178
+
179
+ describe('QueueMembersAPI.getCommunications', () => {
180
+ beforeEach(() => {
181
+ searchMemberCommunication.mockReset().mockResolvedValue({
182
+ data: {
183
+ items: [
184
+ {
185
+ id: '1',
186
+ destination: '380',
187
+ },
188
+ ],
189
+ next: true,
190
+ },
191
+ });
192
+ });
193
+
194
+ it('requests one member of one queue with the sort and page', async () => {
195
+ await QueueMembersAPI.getCommunications({
196
+ parentId: 7,
197
+ memberId: 42,
198
+ page: 2,
199
+ size: 20,
200
+ sort: '-priority',
201
+ });
202
+
203
+ expect(searchMemberCommunication).toHaveBeenCalledWith('7', '42', {
204
+ page: 2,
205
+ size: 20,
206
+ sort: '-priority',
207
+ fields: undefined,
208
+ });
209
+ });
210
+
211
+ it('returns the items with the next flag', async () => {
212
+ const { items, next } = await QueueMembersAPI.getCommunications({
213
+ parentId: 7,
214
+ memberId: 42,
215
+ });
216
+
217
+ expect(items).toEqual([
218
+ {
219
+ id: '1',
220
+ destination: '380',
221
+ },
222
+ ]);
223
+ expect(next).toBe(true);
224
+ });
225
+
226
+ /** an empty list comes back as `{}` */
227
+ it('defaults to an empty last page', async () => {
228
+ searchMemberCommunication.mockResolvedValue({
229
+ data: {},
230
+ });
231
+
232
+ await expect(
233
+ QueueMembersAPI.getCommunications({
234
+ parentId: 7,
235
+ memberId: 42,
236
+ }),
237
+ ).resolves.toEqual({
238
+ items: [],
239
+ next: false,
240
+ });
241
+ });
242
+ });
@@ -183,6 +183,43 @@ const getMembersList = async (params: ApiParams) => {
183
183
  }
184
184
  };
185
185
 
186
+ const getMemberCommunications = async ({
187
+ parentId,
188
+ memberId,
189
+ page,
190
+ size,
191
+ sort,
192
+ fields,
193
+ }: ApiParams & {
194
+ parentId: ApiId;
195
+ memberId: ApiId;
196
+ }) => {
197
+ try {
198
+ const response = await getMemberService().searchMemberCommunication(
199
+ String(parentId),
200
+ String(memberId),
201
+ {
202
+ page,
203
+ size,
204
+ sort,
205
+ fields,
206
+ },
207
+ );
208
+ const { items, next } = applyTransform(response.data, [
209
+ snakeToCamel(),
210
+ merge(getDefaultGetListResponse()),
211
+ ]);
212
+ return {
213
+ items,
214
+ next,
215
+ };
216
+ } catch (err) {
217
+ throw applyTransform(err, [
218
+ notify,
219
+ ]);
220
+ }
221
+ };
222
+
186
223
  /**
187
224
  * Streamed CSV/XLSX export of the current filter set. Returns the raw axios
188
225
  * response with an unread Blob body — the caller passes it to the shared
@@ -518,6 +555,7 @@ const deleteMembersBulk = async ({
518
555
 
519
556
  export const QueueMembersAPI = {
520
557
  getList: getMembersList,
558
+ getCommunications: getMemberCommunications,
521
559
  exportMembers,
522
560
  getQuantity: getMembersQuantity,
523
561
  get: getMember,
@@ -46,6 +46,10 @@ export * from './queueResGroup/queueResGroup.validations';
46
46
  export * from './queueSkill/queueSkill.validations';
47
47
  export * from './sla/sla.validations';
48
48
  export * from './slaCondition/slaCondition.validations';
49
+ export * from './team/team.validations';
50
+ export * from './teamAgent/teamAgent.validations';
51
+ export * from './teamFlow/teamFlow.validations';
52
+ export * from './teamHook/teamHook.validations';
49
53
  export * from './typeExtension/typeExtension.validations';
50
54
  export * from './types';
51
55
  export * from './user/user.validations';
@@ -0,0 +1,85 @@
1
+ import { getDefaultsFromZodSchema } from '@webitel/api-services/gen/utils';
2
+ import { describe, expect, it } from 'vitest';
3
+
4
+ import { teamSchema } from '../team.validations';
5
+
6
+ const filledTeam = {
7
+ name: 'Support',
8
+ strategy: 'random',
9
+ maxNoAnswer: 3,
10
+ wrapUpTime: 15,
11
+ noAnswerDelayTime: 30,
12
+ taskAcceptTimeout: 30,
13
+ callTimeout: 60,
14
+ inviteChatTimeout: 30,
15
+ };
16
+
17
+ const issuePaths = (value: Record<string, unknown>) =>
18
+ teamSchema
19
+ .safeParse(value)
20
+ .error?.issues.map((issue) => issue.path.join('.')) ?? [];
21
+
22
+ describe('teamSchema', () => {
23
+ it('seeds a new team with the defaults the form expects', () => {
24
+ expect(getDefaultsFromZodSchema(teamSchema, {})).toMatchObject({
25
+ name: '',
26
+ description: '',
27
+ strategy: '',
28
+ admin: [],
29
+ screenControl: false,
30
+ maxNoAnswer: 3,
31
+ wrapUpTime: 15,
32
+ noAnswerDelayTime: 30,
33
+ taskAcceptTimeout: 30,
34
+ callTimeout: 60,
35
+ inviteChatTimeout: 30,
36
+ });
37
+ });
38
+
39
+ it('requires a name and a strategy', () => {
40
+ const paths = issuePaths({
41
+ ...filledTeam,
42
+ name: '',
43
+ strategy: '',
44
+ });
45
+
46
+ expect(paths).toContain('name');
47
+ expect(paths).toContain('strategy');
48
+ });
49
+
50
+ it('requires every timing parameter', () => {
51
+ const paths = issuePaths({
52
+ ...filledTeam,
53
+ maxNoAnswer: null,
54
+ wrapUpTime: null,
55
+ noAnswerDelayTime: null,
56
+ taskAcceptTimeout: null,
57
+ callTimeout: null,
58
+ inviteChatTimeout: null,
59
+ });
60
+
61
+ expect(paths).toEqual(
62
+ expect.arrayContaining([
63
+ 'maxNoAnswer',
64
+ 'wrapUpTime',
65
+ 'noAnswerDelayTime',
66
+ 'taskAcceptTimeout',
67
+ 'callTimeout',
68
+ 'inviteChatTimeout',
69
+ ]),
70
+ );
71
+ });
72
+
73
+ it('accepts a zero timing parameter', () => {
74
+ expect(
75
+ teamSchema.safeParse({
76
+ ...filledTeam,
77
+ wrapUpTime: 0,
78
+ }).success,
79
+ ).toBe(true);
80
+ });
81
+
82
+ it('accepts a filled team', () => {
83
+ expect(teamSchema.safeParse(filledTeam).success).toBe(true);
84
+ });
85
+ });
@@ -0,0 +1,20 @@
1
+ import type { EngineAgentTeam } from '@webitel/api-services/gen/models';
2
+ import { z } from 'zod';
3
+
4
+ import { flexibleLookupSchema } from '../_shared/lookup.validations';
5
+ import type { ZodShape } from '../types';
6
+
7
+ export const teamSchema = z.object<ZodShape<EngineAgentTeam>>({
8
+ id: z.string().optional(),
9
+ name: z.string().min(1).default(''),
10
+ description: z.string().optional().default(''),
11
+ strategy: z.string().min(1).default(''),
12
+ admin: z.array(flexibleLookupSchema).optional().default([]),
13
+ screenControl: z.boolean().optional().default(false),
14
+ maxNoAnswer: z.number().default(3),
15
+ wrapUpTime: z.number().default(15),
16
+ noAnswerDelayTime: z.number().default(30),
17
+ taskAcceptTimeout: z.number().default(30),
18
+ callTimeout: z.number().default(60),
19
+ inviteChatTimeout: z.number().default(30),
20
+ });
@@ -0,0 +1,24 @@
1
+ import { describe, expect, it } from 'vitest';
2
+
3
+ import { teamAgentSchema } from '../teamAgent.validations';
4
+
5
+ describe('teamAgentSchema', () => {
6
+ it('requires an agent', () => {
7
+ expect(
8
+ teamAgentSchema.safeParse({
9
+ agent: {},
10
+ }).success,
11
+ ).toBe(false);
12
+ });
13
+
14
+ it('accepts a picked agent', () => {
15
+ expect(
16
+ teamAgentSchema.safeParse({
17
+ agent: {
18
+ id: '1',
19
+ name: 'John',
20
+ },
21
+ }).success,
22
+ ).toBe(true);
23
+ });
24
+ });
@@ -0,0 +1,7 @@
1
+ import { z } from 'zod';
2
+
3
+ import { filledLookupSchema } from '../_shared/lookup.validations';
4
+
5
+ export const teamAgentSchema = z.object({
6
+ agent: filledLookupSchema,
7
+ });
@@ -0,0 +1,32 @@
1
+ import { describe, expect, it } from 'vitest';
2
+
3
+ import { teamFlowSchema } from '../teamFlow.validations';
4
+
5
+ const issuePaths = (value: Record<string, unknown>) =>
6
+ teamFlowSchema
7
+ .safeParse(value)
8
+ .error?.issues.map((issue) => issue.path.join('.')) ?? [];
9
+
10
+ describe('teamFlowSchema', () => {
11
+ it('requires a name and a flow schema', () => {
12
+ const paths = issuePaths({
13
+ name: '',
14
+ schema: {},
15
+ });
16
+
17
+ expect(paths).toContain('name');
18
+ expect(paths).toContain('schema');
19
+ });
20
+
21
+ it('accepts a filled flow', () => {
22
+ expect(
23
+ teamFlowSchema.safeParse({
24
+ name: 'Service',
25
+ schema: {
26
+ id: 1,
27
+ name: 'Flow',
28
+ },
29
+ }).success,
30
+ ).toBe(true);
31
+ });
32
+ });
@@ -0,0 +1,12 @@
1
+ import type { EngineTeamTrigger } from '@webitel/api-services/gen/models';
2
+ import { z } from 'zod';
3
+
4
+ import { filledLookupSchema } from '../_shared/lookup.validations';
5
+ import type { ZodShape } from '../types';
6
+
7
+ export const teamFlowSchema = z.object<ZodShape<EngineTeamTrigger>>({
8
+ name: z.string().min(1),
9
+ description: z.string().optional(),
10
+ schema: filledLookupSchema,
11
+ enabled: z.boolean().default(true),
12
+ });
@@ -0,0 +1,32 @@
1
+ import { describe, expect, it } from 'vitest';
2
+
3
+ import { teamHookSchema } from '../teamHook.validations';
4
+
5
+ const issuePaths = (value: Record<string, unknown>) =>
6
+ teamHookSchema
7
+ .safeParse(value)
8
+ .error?.issues.map((issue) => issue.path.join('.')) ?? [];
9
+
10
+ describe('teamHookSchema', () => {
11
+ it('requires an event and a flow schema', () => {
12
+ const paths = issuePaths({
13
+ event: '',
14
+ schema: {},
15
+ });
16
+
17
+ expect(paths).toContain('event');
18
+ expect(paths).toContain('schema');
19
+ });
20
+
21
+ it('accepts a filled hook', () => {
22
+ expect(
23
+ teamHookSchema.safeParse({
24
+ event: 'agent_status',
25
+ schema: {
26
+ id: 1,
27
+ name: 'Flow',
28
+ },
29
+ }).success,
30
+ ).toBe(true);
31
+ });
32
+ });
@@ -0,0 +1,12 @@
1
+ import type { EngineTeamHook } from '@webitel/api-services/gen/models';
2
+ import { z } from 'zod';
3
+
4
+ import { filledLookupSchema } from '../_shared/lookup.validations';
5
+ import type { ZodShape } from '../types';
6
+
7
+ export const teamHookSchema = z.object<ZodShape<EngineTeamHook>>({
8
+ event: z.string().min(1),
9
+ schema: filledLookupSchema,
10
+ properties: z.array(z.string()).optional(),
11
+ enabled: z.boolean().default(true),
12
+ });