@ikatec/digisac-api-sdk 4.14.0 → 4.16.0
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/README.md +10 -3
- package/dist/apis/absence/AbsenceApi.cjs +2 -2
- package/dist/apis/absence/AbsenceApi.cjs.map +1 -1
- package/dist/apis/absence/AbsenceApi.d.ts +2 -2
- package/dist/apis/absence/AbsenceApi.mjs +2 -2
- package/dist/apis/absence/AbsenceApi.mjs.map +1 -1
- package/dist/apis/absence/types.d.ts +1 -1
- package/dist/apis/answers/AnswersApi.cjs +23 -2
- package/dist/apis/answers/AnswersApi.cjs.map +1 -1
- package/dist/apis/answers/AnswersApi.d.ts +16 -2
- package/dist/apis/answers/AnswersApi.d.ts.map +1 -1
- package/dist/apis/answers/AnswersApi.mjs +23 -2
- package/dist/apis/answers/AnswersApi.mjs.map +1 -1
- package/dist/apis/answers/types.d.ts +1 -2
- package/dist/apis/answers/types.d.ts.map +1 -1
- package/dist/apis/authHistory/AuthHistoryApi.cjs +9 -2
- package/dist/apis/authHistory/AuthHistoryApi.cjs.map +1 -1
- package/dist/apis/authHistory/AuthHistoryApi.d.ts +7 -2
- package/dist/apis/authHistory/AuthHistoryApi.d.ts.map +1 -1
- package/dist/apis/authHistory/AuthHistoryApi.mjs +9 -2
- package/dist/apis/authHistory/AuthHistoryApi.mjs.map +1 -1
- package/dist/apis/authHistory/types.d.ts +6 -1
- package/dist/apis/authHistory/types.d.ts.map +1 -1
- package/dist/apis/bots/BotsApi.cjs +16 -7
- package/dist/apis/bots/BotsApi.cjs.map +1 -1
- package/dist/apis/bots/BotsApi.d.ts +13 -7
- package/dist/apis/bots/BotsApi.d.ts.map +1 -1
- package/dist/apis/bots/BotsApi.mjs +16 -7
- package/dist/apis/bots/BotsApi.mjs.map +1 -1
- package/dist/apis/bots/types.d.ts +12 -2
- package/dist/apis/bots/types.d.ts.map +1 -1
- package/dist/apis/campaigns/CampaignsApi.cjs +25 -1
- package/dist/apis/campaigns/CampaignsApi.cjs.map +1 -1
- package/dist/apis/campaigns/CampaignsApi.d.ts +16 -1
- package/dist/apis/campaigns/CampaignsApi.d.ts.map +1 -1
- package/dist/apis/campaigns/CampaignsApi.mjs +25 -1
- package/dist/apis/campaigns/CampaignsApi.mjs.map +1 -1
- package/dist/apis/campaigns/types.d.ts +98 -6
- package/dist/apis/campaigns/types.d.ts.map +1 -1
- package/dist/apis/cards/types.d.ts +5 -5
- package/dist/apis/categories/CategoriesApi.cjs +1 -2
- package/dist/apis/categories/CategoriesApi.cjs.map +1 -1
- package/dist/apis/categories/CategoriesApi.d.ts +1 -2
- package/dist/apis/categories/CategoriesApi.d.ts.map +1 -1
- package/dist/apis/categories/CategoriesApi.mjs +1 -2
- package/dist/apis/categories/CategoriesApi.mjs.map +1 -1
- package/dist/apis/clientFeedback/ClientFeedbackApi.cjs +2 -3
- package/dist/apis/clientFeedback/ClientFeedbackApi.cjs.map +1 -1
- package/dist/apis/clientFeedback/ClientFeedbackApi.d.ts +2 -3
- package/dist/apis/clientFeedback/ClientFeedbackApi.d.ts.map +1 -1
- package/dist/apis/clientFeedback/ClientFeedbackApi.mjs +2 -3
- package/dist/apis/clientFeedback/ClientFeedbackApi.mjs.map +1 -1
- package/dist/apis/contacts/ContactsApi.cjs +20 -6
- package/dist/apis/contacts/ContactsApi.cjs.map +1 -1
- package/dist/apis/contacts/ContactsApi.d.ts +28 -4
- package/dist/apis/contacts/ContactsApi.d.ts.map +1 -1
- package/dist/apis/contacts/ContactsApi.mjs +20 -6
- package/dist/apis/contacts/ContactsApi.mjs.map +1 -1
- package/dist/apis/contacts/types.d.ts +101 -2
- package/dist/apis/contacts/types.d.ts.map +1 -1
- package/dist/apis/customFields/types.d.ts +4 -4
- package/dist/apis/dashboard/DashboardApi.cjs +3 -3
- package/dist/apis/dashboard/DashboardApi.cjs.map +1 -1
- package/dist/apis/dashboard/DashboardApi.d.ts +3 -3
- package/dist/apis/dashboard/DashboardApi.mjs +3 -3
- package/dist/apis/dashboard/DashboardApi.mjs.map +1 -1
- package/dist/apis/dashboard/types.d.ts +11 -4
- package/dist/apis/dashboard/types.d.ts.map +1 -1
- package/dist/apis/departments/DepartmentsApi.cjs +5 -5
- package/dist/apis/departments/DepartmentsApi.cjs.map +1 -1
- package/dist/apis/departments/DepartmentsApi.d.ts +5 -5
- package/dist/apis/departments/DepartmentsApi.mjs +5 -5
- package/dist/apis/departments/DepartmentsApi.mjs.map +1 -1
- package/dist/apis/departments/types.d.ts +6 -0
- package/dist/apis/departments/types.d.ts.map +1 -1
- package/dist/apis/distribution/DistributionApi.cjs +3 -4
- package/dist/apis/distribution/DistributionApi.cjs.map +1 -1
- package/dist/apis/distribution/DistributionApi.d.ts +3 -4
- package/dist/apis/distribution/DistributionApi.d.ts.map +1 -1
- package/dist/apis/distribution/DistributionApi.mjs +3 -4
- package/dist/apis/distribution/DistributionApi.mjs.map +1 -1
- package/dist/apis/files/FilesApi.cjs +13 -1
- package/dist/apis/files/FilesApi.cjs.map +1 -1
- package/dist/apis/files/FilesApi.d.ts +12 -2
- package/dist/apis/files/FilesApi.d.ts.map +1 -1
- package/dist/apis/files/FilesApi.mjs +13 -1
- package/dist/apis/files/FilesApi.mjs.map +1 -1
- package/dist/apis/files/types.d.ts +19 -1
- package/dist/apis/files/types.d.ts.map +1 -1
- package/dist/apis/kanbanCards/KanbanCardsApi.cjs +32 -0
- package/dist/apis/kanbanCards/KanbanCardsApi.cjs.map +1 -1
- package/dist/apis/kanbanCards/KanbanCardsApi.d.ts +27 -1
- package/dist/apis/kanbanCards/KanbanCardsApi.d.ts.map +1 -1
- package/dist/apis/kanbanCards/KanbanCardsApi.mjs +32 -0
- package/dist/apis/kanbanCards/KanbanCardsApi.mjs.map +1 -1
- package/dist/apis/kanbanCards/types.d.ts +1 -1
- package/dist/apis/kanbanCards/types.d.ts.map +1 -1
- package/dist/apis/kanbanColumns/KanbanColumnsApi.cjs +19 -0
- package/dist/apis/kanbanColumns/KanbanColumnsApi.cjs.map +1 -1
- package/dist/apis/kanbanColumns/KanbanColumnsApi.d.ts +16 -1
- package/dist/apis/kanbanColumns/KanbanColumnsApi.d.ts.map +1 -1
- package/dist/apis/kanbanColumns/KanbanColumnsApi.mjs +19 -0
- package/dist/apis/kanbanColumns/KanbanColumnsApi.mjs.map +1 -1
- package/dist/apis/kanbanColumns/types.d.ts +4 -0
- package/dist/apis/kanbanColumns/types.d.ts.map +1 -1
- package/dist/apis/messages/MessagesApi.cjs +13 -4
- package/dist/apis/messages/MessagesApi.cjs.map +1 -1
- package/dist/apis/messages/MessagesApi.d.ts +13 -4
- package/dist/apis/messages/MessagesApi.d.ts.map +1 -1
- package/dist/apis/messages/MessagesApi.mjs +13 -4
- package/dist/apis/messages/MessagesApi.mjs.map +1 -1
- package/dist/apis/messages/types.d.ts +5 -0
- package/dist/apis/messages/types.d.ts.map +1 -1
- package/dist/apis/pipeline/types.d.ts +7 -8
- package/dist/apis/pipeline/types.d.ts.map +1 -1
- package/dist/apis/quickReplies/types.d.ts +4 -1
- package/dist/apis/quickReplies/types.d.ts.map +1 -1
- package/dist/apis/schedule/types.d.ts +41 -10
- package/dist/apis/schedule/types.d.ts.map +1 -1
- package/dist/apis/terms/TermsApi.cjs +2 -2
- package/dist/apis/terms/TermsApi.cjs.map +1 -1
- package/dist/apis/terms/TermsApi.d.ts +2 -2
- package/dist/apis/terms/TermsApi.mjs +2 -2
- package/dist/apis/terms/TermsApi.mjs.map +1 -1
- package/dist/apis/tickets/TicketsApi.cjs +18 -8
- package/dist/apis/tickets/TicketsApi.cjs.map +1 -1
- package/dist/apis/tickets/TicketsApi.d.ts +15 -8
- package/dist/apis/tickets/TicketsApi.d.ts.map +1 -1
- package/dist/apis/tickets/TicketsApi.mjs +18 -8
- package/dist/apis/tickets/TicketsApi.mjs.map +1 -1
- package/dist/apis/tickets/types.d.ts +4 -1
- package/dist/apis/tickets/types.d.ts.map +1 -1
- package/dist/apis/timetable/TimetableApi.cjs +6 -0
- package/dist/apis/timetable/TimetableApi.cjs.map +1 -1
- package/dist/apis/timetable/TimetableApi.d.ts +6 -0
- package/dist/apis/timetable/TimetableApi.d.ts.map +1 -1
- package/dist/apis/timetable/TimetableApi.mjs +6 -0
- package/dist/apis/timetable/TimetableApi.mjs.map +1 -1
- package/dist/apis/timetable/types.d.ts +8 -0
- package/dist/apis/timetable/types.d.ts.map +1 -1
- package/dist/apis/users/UsersApi.cjs +11 -3
- package/dist/apis/users/UsersApi.cjs.map +1 -1
- package/dist/apis/users/UsersApi.d.ts +10 -4
- package/dist/apis/users/UsersApi.d.ts.map +1 -1
- package/dist/apis/users/UsersApi.mjs +11 -3
- package/dist/apis/users/UsersApi.mjs.map +1 -1
- package/dist/apis/users/types.d.ts +26 -0
- package/dist/apis/users/types.d.ts.map +1 -1
- package/dist/apis/webhooks/types.d.ts +51 -6
- package/dist/apis/webhooks/types.d.ts.map +1 -1
- package/dist/core/BaseReadApi.cjs +2 -2
- package/dist/core/BaseReadApi.cjs.map +1 -1
- package/dist/core/BaseReadApi.d.ts +2 -2
- package/dist/core/BaseReadApi.mjs +2 -2
- package/dist/core/BaseReadApi.mjs.map +1 -1
- package/dist/core/errors.cjs +4 -1
- package/dist/core/errors.cjs.map +1 -1
- package/dist/core/errors.d.ts +4 -1
- package/dist/core/errors.d.ts.map +1 -1
- package/dist/core/errors.mjs +4 -1
- package/dist/core/errors.mjs.map +1 -1
- package/package.json +1 -1
- package/src/apis/absence/AbsenceApi.ts +2 -2
- package/src/apis/absence/types.ts +1 -1
- package/src/apis/answers/AnswersApi.test.ts +32 -0
- package/src/apis/answers/AnswersApi.ts +38 -2
- package/src/apis/answers/types.ts +1 -2
- package/src/apis/authHistory/AuthHistoryApi.test.ts +16 -0
- package/src/apis/authHistory/AuthHistoryApi.ts +10 -2
- package/src/apis/authHistory/types.ts +6 -1
- package/src/apis/bots/BotsApi.test.ts +16 -0
- package/src/apis/bots/BotsApi.ts +25 -7
- package/src/apis/bots/types.ts +12 -2
- package/src/apis/campaigns/CampaignsApi.test.ts +48 -0
- package/src/apis/campaigns/CampaignsApi.ts +31 -2
- package/src/apis/campaigns/types.ts +101 -3
- package/src/apis/cards/types.ts +5 -5
- package/src/apis/categories/CategoriesApi.ts +1 -2
- package/src/apis/clientFeedback/ClientFeedbackApi.ts +2 -3
- package/src/apis/contacts/ContactsApi.test.ts +49 -2
- package/src/apis/contacts/ContactsApi.ts +64 -4
- package/src/apis/contacts/types.ts +111 -1
- package/src/apis/creditMovements/CreditMovementsApi.test.ts +1 -1
- package/src/apis/customFields/types.ts +4 -4
- package/src/apis/dashboard/DashboardApi.test-d.ts +9 -0
- package/src/apis/dashboard/DashboardApi.ts +3 -3
- package/src/apis/dashboard/types.ts +11 -4
- package/src/apis/departments/DepartmentsApi.ts +5 -5
- package/src/apis/departments/types.ts +13 -0
- package/src/apis/distribution/DistributionApi.ts +3 -4
- package/src/apis/files/FilesApi.test.ts +21 -0
- package/src/apis/files/FilesApi.ts +19 -1
- package/src/apis/files/types.ts +20 -1
- package/src/apis/kanbanCards/KanbanCardsApi.test.ts +21 -0
- package/src/apis/kanbanCards/KanbanCardsApi.ts +47 -1
- package/src/apis/kanbanCards/types.ts +1 -1
- package/src/apis/kanbanColumns/KanbanColumnsApi.test.ts +26 -0
- package/src/apis/kanbanColumns/KanbanColumnsApi.ts +31 -0
- package/src/apis/kanbanColumns/types.ts +5 -0
- package/src/apis/messages/MessagesApi.ts +13 -4
- package/src/apis/messages/types.ts +5 -0
- package/src/apis/payloads.test-d.ts +245 -5
- package/src/apis/pipeline/types.ts +7 -8
- package/src/apis/queryFormat.test.ts +13 -0
- package/src/apis/quickReplies/types.ts +4 -1
- package/src/apis/schedule/types.ts +42 -10
- package/src/apis/terms/TermsApi.ts +2 -2
- package/src/apis/tickets/TicketsApi.ts +28 -8
- package/src/apis/tickets/types.ts +4 -1
- package/src/apis/timetable/TimetableApi.ts +6 -0
- package/src/apis/timetable/types.ts +9 -0
- package/src/apis/users/UsersApi.test.ts +17 -0
- package/src/apis/users/UsersApi.ts +21 -3
- package/src/apis/users/types.ts +28 -0
- package/src/apis/webhooks/types.ts +53 -6
- package/src/core/BaseReadApi.ts +2 -2
- package/src/core/errors.ts +4 -1
|
@@ -34,6 +34,8 @@ export type CampaignConfig = {
|
|
|
34
34
|
nameField?: string
|
|
35
35
|
/** Column name in the import file used as the phone number. */
|
|
36
36
|
numberField?: string
|
|
37
|
+
/** Column name in the import file used as the username (contacts known only by it). */
|
|
38
|
+
usernameField?: string
|
|
37
39
|
delimiter?: ',' | ';' | ':' | string
|
|
38
40
|
error?: {
|
|
39
41
|
message: string
|
|
@@ -65,7 +67,10 @@ export type Campaign = {
|
|
|
65
67
|
marketingIntegration?: boolean
|
|
66
68
|
/** Always `null`: the campaign has no such column (answered by the transformer). */
|
|
67
69
|
userId?: null
|
|
68
|
-
/**
|
|
70
|
+
/**
|
|
71
|
+
* In the pages of `getMany` (not with `paginate: false`) and in `getOne`: messages sent and
|
|
72
|
+
* viewed (ack 3).
|
|
73
|
+
*/
|
|
69
74
|
stats?: { sent: number; viewed: number }
|
|
70
75
|
accountId: string
|
|
71
76
|
serviceId: string
|
|
@@ -116,9 +121,21 @@ export type CampaignRelationships =
|
|
|
116
121
|
| 'messages'
|
|
117
122
|
| 'importFile'
|
|
118
123
|
|
|
124
|
+
/** The media of a header parameter of the template (send it as `{ link: '<url>' }`). */
|
|
125
|
+
export type CampaignTemplateMedia = {
|
|
126
|
+
link?: string
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* A parameter of the template: `text`, or the media of its `type` (`image`, `video` or
|
|
131
|
+
* `document`).
|
|
132
|
+
*/
|
|
119
133
|
export type CampaignTemplateParameterItem = {
|
|
120
134
|
type: string
|
|
121
135
|
text?: string
|
|
136
|
+
image?: CampaignTemplateMedia
|
|
137
|
+
video?: CampaignTemplateMedia
|
|
138
|
+
document?: CampaignTemplateMedia
|
|
122
139
|
}
|
|
123
140
|
|
|
124
141
|
export type CampaignTemplateParameter = {
|
|
@@ -135,30 +152,111 @@ export type CampaignFileTemplate = {
|
|
|
135
152
|
name?: string
|
|
136
153
|
}
|
|
137
154
|
|
|
155
|
+
/** A message of the campaign to create (without `hsm`, the campaign sends these). */
|
|
156
|
+
export type CampaignMessageInput = {
|
|
157
|
+
text?: string
|
|
158
|
+
/** The attachment of the message, as a data URL (`data:<mimetype>;base64,<content>`). */
|
|
159
|
+
base64Url?: string
|
|
160
|
+
/** @deprecated Ignored by the backend: send the attachment as `base64Url`. */
|
|
161
|
+
fileId?: string
|
|
162
|
+
}
|
|
163
|
+
|
|
138
164
|
export type CreateCampaignPayload = {
|
|
139
165
|
title: string
|
|
140
166
|
serviceId: string
|
|
141
167
|
config?: { minInterval: number | string; maxInterval: number | string }
|
|
142
168
|
tagIds?: string[]
|
|
143
|
-
messages?:
|
|
169
|
+
messages?: CampaignMessageInput[]
|
|
170
|
+
/** On create, replaces the `text` of every message (and is the text of the template message). */
|
|
171
|
+
text?: string
|
|
144
172
|
isScheduled?: boolean
|
|
145
173
|
sendsAt?: string | null
|
|
146
174
|
mustOpenTicket?: boolean
|
|
147
175
|
defaultDepartmentId?: string | null
|
|
148
176
|
defaultUserId?: string | null
|
|
177
|
+
/** @deprecated Ignored by the backend: the contacts come from `tagIds` or the import `fileId`. */
|
|
149
178
|
contacts?: Record<string, string>[]
|
|
179
|
+
/** @deprecated Ignored by the backend: the contacts come from `tagIds` or the import `fileId`. */
|
|
150
180
|
useTags?: boolean
|
|
181
|
+
/**
|
|
182
|
+
* On create, the import file (CSV) of the contacts, uploaded with
|
|
183
|
+
* `attachedType: 'campaign.file'`. The columns are read by `nameField`, `numberField` and
|
|
184
|
+
* `usernameField`.
|
|
185
|
+
*/
|
|
151
186
|
fileId?: string
|
|
187
|
+
/** On create, stored in `config.nameField` (a `config.nameField` sent here is replaced). */
|
|
152
188
|
nameField?: string
|
|
189
|
+
/** On create, stored in `config.numberField` (a `config.numberField` sent here is replaced). */
|
|
153
190
|
numberField?: string
|
|
191
|
+
/** Stored in `config.usernameField` (a `config.usernameField` sent here is replaced). */
|
|
192
|
+
usernameField?: string
|
|
154
193
|
// whatsapp-business specific
|
|
194
|
+
/**
|
|
195
|
+
* The template to send. On create, the campaign gets one message of it and `messages` is not
|
|
196
|
+
* read.
|
|
197
|
+
*/
|
|
155
198
|
hsm?: WhatsappBusinessTemplate
|
|
156
199
|
parameters?: CampaignTemplateParameter[]
|
|
200
|
+
/**
|
|
201
|
+
* The header file of the template message (only with `hsm`), already uploaded. Takes precedence
|
|
202
|
+
* over `fileTemplate`.
|
|
203
|
+
*/
|
|
204
|
+
hsmFileId?: string
|
|
205
|
+
/**
|
|
206
|
+
* The header media of the template message: `base64Url` as a data URL, with its `mimetype`
|
|
207
|
+
* (required on create) and `name`. On create, read only when `tagIds` is sent (an empty array is
|
|
208
|
+
* enough); with the import `fileId`, prefer `hsmFileId`. On update, it only replaces the header
|
|
209
|
+
* file the template message already has: send it only with a new data URL, and leave it out to
|
|
210
|
+
* keep the header.
|
|
211
|
+
*/
|
|
157
212
|
fileTemplate?: CampaignFileTemplate
|
|
158
213
|
marketingIntegration?: boolean
|
|
159
214
|
}
|
|
160
215
|
|
|
161
|
-
|
|
216
|
+
/**
|
|
217
|
+
* A message of `updateById`. With the `id` of an existing message, the message gets the `text`
|
|
218
|
+
* sent; without `id`, it is created (and `base64Url` is read as in the create).
|
|
219
|
+
*/
|
|
220
|
+
export type UpdateCampaignMessageInput = CampaignMessageInput & {
|
|
221
|
+
id?: string
|
|
222
|
+
/**
|
|
223
|
+
* On WhatsApp connections, keeps the attachment of an existing message (send the `file` of the
|
|
224
|
+
* message read); with `file`, `base64Url` is not read. Without `file` and `base64Url`, the
|
|
225
|
+
* attachment is removed.
|
|
226
|
+
*/
|
|
227
|
+
file?: unknown
|
|
228
|
+
/**
|
|
229
|
+
* On WhatsApp connections, the name of the new attachment in `base64Url`: to replace the
|
|
230
|
+
* attachment of an existing message, send `base64Url` with a new name and without `file`.
|
|
231
|
+
*/
|
|
232
|
+
fileName?: string
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
/**
|
|
236
|
+
* `updateById` (`PUT`). A non-empty `messages` replaces the messages: the ones with the `id` of an
|
|
237
|
+
* existing message update it, the ones without `id` are created and the existing ones left out are
|
|
238
|
+
* deleted (omitted, or `[]`, keeps them).
|
|
239
|
+
*
|
|
240
|
+
* Send `isScheduled` (with `sendsAt`) and `mustOpenTicket` (with `defaultDepartmentId` and
|
|
241
|
+
* `defaultUserId`) on every call: without `isScheduled: true`, `sendsAt` is stored as `null` and a
|
|
242
|
+
* scheduled campaign is no longer started at the date; without `mustOpenTicket: true`, the default
|
|
243
|
+
* department and user are cleared.
|
|
244
|
+
*
|
|
245
|
+
* On WhatsApp Business connections, send the existing message by its `id` (a message without `id`
|
|
246
|
+
* is created without the template), together with `hsm` and `parameters`: every update that sends
|
|
247
|
+
* `messages` or `hsm` rewrites both on the existing messages (a missing one is stored empty).
|
|
248
|
+
*/
|
|
249
|
+
export type UpdateCampaignPayload = Omit<
|
|
250
|
+
Partial<CreateCampaignPayload>,
|
|
251
|
+
'text' | 'usernameField' | 'hsmFileId' | 'messages' | 'config'
|
|
252
|
+
> & {
|
|
253
|
+
/**
|
|
254
|
+
* Replaces the stored config as a whole. `minInterval` and `maxInterval` go as strings (a number
|
|
255
|
+
* answers 400).
|
|
256
|
+
*/
|
|
257
|
+
config?: { minInterval: number | string; maxInterval: number | string }
|
|
258
|
+
messages?: UpdateCampaignMessageInput[]
|
|
259
|
+
}
|
|
162
260
|
|
|
163
261
|
/** The visible states the `status` filter of `getMany` takes (`'scheduled'` is derived from `isScheduled` + `sendsAt`). */
|
|
164
262
|
export type CampaignListStatus = CampaignStatus | 'scheduled'
|
package/src/apis/cards/types.ts
CHANGED
|
@@ -182,8 +182,8 @@ export type BulkMoveCardsPayload = {
|
|
|
182
182
|
export type BulkMoveCardsResult = { movedCount: number; ignoredCount: number }
|
|
183
183
|
|
|
184
184
|
/**
|
|
185
|
-
* Creates a product of a card, or updates the product of `id`.
|
|
186
|
-
* a missing
|
|
185
|
+
* Creates a product of a card, or updates the product of `id`. `name`, `ammount` and `value` are
|
|
186
|
+
* required (a missing one answers 500).
|
|
187
187
|
*/
|
|
188
188
|
export type SaveCardProductPayload = {
|
|
189
189
|
id?: string
|
|
@@ -218,9 +218,9 @@ export type CardOwner = {
|
|
|
218
218
|
}
|
|
219
219
|
|
|
220
220
|
/**
|
|
221
|
-
* Body of `POST /cards/getCards`:
|
|
222
|
-
*
|
|
223
|
-
*
|
|
221
|
+
* Body of `POST /cards/getCards`: a list query of the cards. Send `where.accountId` with the id of
|
|
222
|
+
* the current account (`accountId` of `MeApi.getMe`). `order` accepts card fields and
|
|
223
|
+
* `contact.name`.
|
|
224
224
|
*/
|
|
225
225
|
export type GetCardsPayload = Omit<
|
|
226
226
|
ListQuery<Card>,
|
|
@@ -15,8 +15,7 @@ export class CategoriesApi extends BaseCrudApi<
|
|
|
15
15
|
}
|
|
16
16
|
|
|
17
17
|
/**
|
|
18
|
-
* Deletes a category. Resolves the text `'OK'`; an unknown id answers 500.
|
|
19
|
-
* permission.
|
|
18
|
+
* Deletes a category. Resolves the text `'OK'`; an unknown id answers 500.
|
|
20
19
|
*/
|
|
21
20
|
override deleteById(id: string, headers?: Record<string, string>): Promise<'OK'> {
|
|
22
21
|
return super.deleteById(id, headers)
|
|
@@ -9,9 +9,8 @@ export class ClientFeedbackApi
|
|
|
9
9
|
private readonly basePath = '/client-feedback'
|
|
10
10
|
|
|
11
11
|
/**
|
|
12
|
-
* @deprecated The route is
|
|
13
|
-
*
|
|
14
|
-
* feedback on the AI summary is stored when the ticket is closed.
|
|
12
|
+
* @deprecated The route is not available (it answers 500). Send the rating of the AI summary
|
|
13
|
+
* when closing the ticket: `ContactsApi.closeTicket` with `aiSummaryRating`.
|
|
15
14
|
*/
|
|
16
15
|
create(
|
|
17
16
|
body: CreateClientFeedbackPayload,
|
|
@@ -138,6 +138,19 @@ describe('ContactsApi', () => {
|
|
|
138
138
|
await api.getById('cnt-1', undefined, headers)
|
|
139
139
|
expect(client.get).toHaveBeenCalledWith('/contacts/cnt-1', headers)
|
|
140
140
|
})
|
|
141
|
+
|
|
142
|
+
it('sends formatCustomFields and the include of the custom fields in the query', async () => {
|
|
143
|
+
vi.mocked(client.get).mockResolvedValue(contact)
|
|
144
|
+
const query = {
|
|
145
|
+
include: [{ model: 'customFieldValues' as const, include: ['customField' as const] }],
|
|
146
|
+
formatCustomFields: true,
|
|
147
|
+
}
|
|
148
|
+
await api.getById('cnt-1', query)
|
|
149
|
+
expect(client.get).toHaveBeenCalledWith(
|
|
150
|
+
`/contacts/cnt-1?query=${encodeURIComponent(JSON.stringify(query))}`,
|
|
151
|
+
undefined,
|
|
152
|
+
)
|
|
153
|
+
})
|
|
141
154
|
})
|
|
142
155
|
|
|
143
156
|
// ── create ───────────────────────────────────────────────────────
|
|
@@ -352,14 +365,26 @@ describe('ContactsApi', () => {
|
|
|
352
365
|
|
|
353
366
|
describe('transferTicket', () => {
|
|
354
367
|
it('calls client.post with /contacts/:id/ticket/transfer and payload', async () => {
|
|
355
|
-
vi.mocked(client.post).mockResolvedValue(
|
|
368
|
+
vi.mocked(client.post).mockResolvedValue(true)
|
|
356
369
|
const result = await api.transferTicket('c1', { departmentId: 'd1' })
|
|
357
370
|
expect(client.post).toHaveBeenCalledWith(
|
|
358
371
|
'/contacts/c1/ticket/transfer',
|
|
359
372
|
{ departmentId: 'd1' },
|
|
360
373
|
undefined,
|
|
361
374
|
)
|
|
362
|
-
expect(result).
|
|
375
|
+
expect(result).toBe(true)
|
|
376
|
+
})
|
|
377
|
+
|
|
378
|
+
it('sends includeKanbanCardId and resolves the id of the card', async () => {
|
|
379
|
+
vi.mocked(client.post).mockResolvedValue({ kanbanCardId: 'kc1' })
|
|
380
|
+
const payload = {
|
|
381
|
+
departmentId: 'd1',
|
|
382
|
+
kanbanCardColumnId: 'col1',
|
|
383
|
+
includeKanbanCardId: true,
|
|
384
|
+
} as const
|
|
385
|
+
const result = await api.transferTicket('c1', payload)
|
|
386
|
+
expect(client.post).toHaveBeenCalledWith('/contacts/c1/ticket/transfer', payload, undefined)
|
|
387
|
+
expect(result.kanbanCardId).toBe('kc1')
|
|
363
388
|
})
|
|
364
389
|
|
|
365
390
|
it('includes optional userId and forwards custom headers', async () => {
|
|
@@ -374,6 +399,28 @@ describe('ContactsApi', () => {
|
|
|
374
399
|
})
|
|
375
400
|
})
|
|
376
401
|
|
|
402
|
+
// ── closeTicket ──────────────────────────────────────────────────
|
|
403
|
+
|
|
404
|
+
describe('closeTicket', () => {
|
|
405
|
+
it('calls client.post with /contacts/:id/ticket/close and an empty body by default', async () => {
|
|
406
|
+
vi.mocked(client.post).mockResolvedValue(true)
|
|
407
|
+
expect(await api.closeTicket('c1')).toBe(true)
|
|
408
|
+
expect(client.post).toHaveBeenCalledWith('/contacts/c1/ticket/close', {}, undefined)
|
|
409
|
+
})
|
|
410
|
+
|
|
411
|
+
it('sends the subjects, the comment and the rating of the AI summary', async () => {
|
|
412
|
+
vi.mocked(client.post).mockResolvedValue(true)
|
|
413
|
+
const headers = { 'X-Custom': 'h' }
|
|
414
|
+
const payload = {
|
|
415
|
+
ticketTopicIds: ['tt1'],
|
|
416
|
+
comments: 'Resolvido',
|
|
417
|
+
aiSummaryRating: '5' as const,
|
|
418
|
+
}
|
|
419
|
+
await api.closeTicket('c1', payload, headers)
|
|
420
|
+
expect(client.post).toHaveBeenCalledWith('/contacts/c1/ticket/close', payload, headers)
|
|
421
|
+
})
|
|
422
|
+
})
|
|
423
|
+
|
|
377
424
|
// ── createMany ───────────────────────────────────────────────────
|
|
378
425
|
|
|
379
426
|
describe('createMany', () => {
|
|
@@ -6,7 +6,10 @@ import type {
|
|
|
6
6
|
BlockContactPayload,
|
|
7
7
|
BulkTransferTicketsPayload,
|
|
8
8
|
BulkTransferTicketsResult,
|
|
9
|
+
CloseTicketPayload,
|
|
9
10
|
Contact,
|
|
11
|
+
ContactGetByIdQuery,
|
|
12
|
+
ContactListQuery,
|
|
10
13
|
ContactMediaPage,
|
|
11
14
|
ContactMediaQuery,
|
|
12
15
|
ContactsSelection,
|
|
@@ -19,16 +22,37 @@ import type {
|
|
|
19
22
|
ExportTemplatePayload,
|
|
20
23
|
ImportContactsPayload,
|
|
21
24
|
SyncContactPayload,
|
|
25
|
+
TransferTicketKanbanCardResult,
|
|
22
26
|
TransferTicketPayload,
|
|
23
27
|
UpdateContactPayload,
|
|
24
28
|
SummarizeTicketResult,
|
|
25
29
|
} from './types'
|
|
26
30
|
|
|
27
|
-
export class ContactsApi extends BaseCrudApi<
|
|
31
|
+
export class ContactsApi extends BaseCrudApi<
|
|
32
|
+
Contact,
|
|
33
|
+
CreateContactPayload,
|
|
34
|
+
UpdateContactPayload,
|
|
35
|
+
ContactListQuery
|
|
36
|
+
> {
|
|
28
37
|
constructor(client: ApiClient) {
|
|
29
38
|
super(client, '/contacts')
|
|
30
39
|
}
|
|
31
40
|
|
|
41
|
+
/**
|
|
42
|
+
* Returns a contact by ID. When it does not exist the route answers 200 with an empty body, which
|
|
43
|
+
* resolves to `undefined`. With `formatCustomFields: true` (and the include
|
|
44
|
+
* `{ model: 'customFieldValues', include: ['customField'] }`), the custom fields come keyed by name
|
|
45
|
+
* in `customFields`.
|
|
46
|
+
* @permissions contacts.view
|
|
47
|
+
*/
|
|
48
|
+
override getById(
|
|
49
|
+
id: string,
|
|
50
|
+
query?: ContactGetByIdQuery,
|
|
51
|
+
headers?: Record<string, string>,
|
|
52
|
+
): Promise<Contact> {
|
|
53
|
+
return super.getById(id, query, headers)
|
|
54
|
+
}
|
|
55
|
+
|
|
32
56
|
/**
|
|
33
57
|
* Downloads the CSV template (`;`-separated header line, in the language of the user) for
|
|
34
58
|
* importing contacts, with columns based on the service type. Answered with no Content-Type.
|
|
@@ -119,20 +143,56 @@ export class ContactsApi extends BaseCrudApi<Contact, CreateContactPayload, Upda
|
|
|
119
143
|
/**
|
|
120
144
|
* Opens (or transfers) the contact's ticket to a department, and optionally a user.
|
|
121
145
|
* This is the real ticket-open flow used by the UI — there is no `POST /tickets`.
|
|
146
|
+
* Resolves `true`, or `{ kanbanCardId }` with `includeKanbanCardId: true`. When the current
|
|
147
|
+
* ticket of the contact is already closed, the call only releases it and opens nothing: call it
|
|
148
|
+
* again to open a ticket.
|
|
122
149
|
* @permissions tickets.transfer.all OR tickets.transfer.me
|
|
123
150
|
*/
|
|
151
|
+
transferTicket(
|
|
152
|
+
contactId: string,
|
|
153
|
+
payload: TransferTicketPayload & { includeKanbanCardId: true },
|
|
154
|
+
headers?: Record<string, string>,
|
|
155
|
+
): Promise<TransferTicketKanbanCardResult>
|
|
156
|
+
transferTicket(
|
|
157
|
+
contactId: string,
|
|
158
|
+
payload: TransferTicketPayload & { includeKanbanCardId?: false },
|
|
159
|
+
headers?: Record<string, string>,
|
|
160
|
+
): Promise<true>
|
|
124
161
|
transferTicket(
|
|
125
162
|
contactId: string,
|
|
126
163
|
payload: TransferTicketPayload,
|
|
127
164
|
headers?: Record<string, string>,
|
|
128
|
-
): Promise<
|
|
129
|
-
|
|
165
|
+
): Promise<true | TransferTicketKanbanCardResult>
|
|
166
|
+
transferTicket(
|
|
167
|
+
contactId: string,
|
|
168
|
+
payload: TransferTicketPayload,
|
|
169
|
+
headers?: Record<string, string>,
|
|
170
|
+
): Promise<true | TransferTicketKanbanCardResult> {
|
|
171
|
+
return this.client.post<true | TransferTicketKanbanCardResult, TransferTicketPayload>(
|
|
130
172
|
`${this.basePath}/${contactId}/ticket/transfer`,
|
|
131
173
|
payload,
|
|
132
174
|
headers,
|
|
133
175
|
)
|
|
134
176
|
}
|
|
135
177
|
|
|
178
|
+
/**
|
|
179
|
+
* Closes the open ticket of the contact and resolves `true`. A contact without an open ticket
|
|
180
|
+
* answers 500, or `true` (closing nothing) when its current ticket is already closed. An unknown
|
|
181
|
+
* subject in `ticketTopicIds`, or one of another department, answers 400.
|
|
182
|
+
* @permissions tickets.close.me OR tickets.close.all
|
|
183
|
+
*/
|
|
184
|
+
closeTicket(
|
|
185
|
+
contactId: string,
|
|
186
|
+
payload: CloseTicketPayload = {},
|
|
187
|
+
headers?: Record<string, string>,
|
|
188
|
+
): Promise<true> {
|
|
189
|
+
return this.client.post<true, CloseTicketPayload>(
|
|
190
|
+
`${this.basePath}/${contactId}/ticket/close`,
|
|
191
|
+
payload,
|
|
192
|
+
headers,
|
|
193
|
+
)
|
|
194
|
+
}
|
|
195
|
+
|
|
136
196
|
/**
|
|
137
197
|
* Creates or updates several contacts in one call. Existing contacts (same service and
|
|
138
198
|
* number or e-mail) are updated; the others are created. Returns the resulting contacts.
|
|
@@ -204,7 +264,7 @@ export class ContactsApi extends BaseCrudApi<Contact, CreateContactPayload, Upda
|
|
|
204
264
|
/**
|
|
205
265
|
* Blocks or unblocks a contact. Blocking closes the contact's open ticket. Requires the
|
|
206
266
|
* block list to be active on the account (`settings.isBlockListActive`; 400 otherwise).
|
|
207
|
-
* `byUserId`
|
|
267
|
+
* Send `byUserId` with the logged user (`id` of `MeApi.getMe`), as the web app does.
|
|
208
268
|
* @permissions contacts.block
|
|
209
269
|
*/
|
|
210
270
|
block(id: string, body: BlockContactPayload, headers?: Record<string, string>): Promise<Contact> {
|
|
@@ -1,10 +1,11 @@
|
|
|
1
|
+
import type { CustomField, CustomFieldType } from '../customFields/types'
|
|
1
2
|
import type { Department } from '../departments/types'
|
|
2
3
|
import type { Person } from '../people/types'
|
|
3
4
|
import type { Service } from '../services/types'
|
|
4
5
|
import type { Tag } from '../tags/types'
|
|
5
6
|
import type { Ticket } from '../tickets/types'
|
|
6
7
|
import type { User } from '../users/types'
|
|
7
|
-
import type { IncludeItem, ListQuery, WhereClause } from '../../core/types'
|
|
8
|
+
import type { GetByIdQuery, IncludeItem, ListQuery, WhereClause } from '../../core/types'
|
|
8
9
|
|
|
9
10
|
export type ContactStatus = 'online' | 'offline' | 'absent'
|
|
10
11
|
export type ContactOrigin = 'api' | 'app' | 'campaign' | 'driver' | 'import' | 'web'
|
|
@@ -95,6 +96,56 @@ export type ContactDataBlock = {
|
|
|
95
96
|
description: string
|
|
96
97
|
}
|
|
97
98
|
|
|
99
|
+
/**
|
|
100
|
+
* A value of a custom field of the contact, as `include: ['customFieldValues']` answers it (the
|
|
101
|
+
* stored row).
|
|
102
|
+
*/
|
|
103
|
+
export type CustomFieldValue = {
|
|
104
|
+
id: string
|
|
105
|
+
customFieldId: string
|
|
106
|
+
/** The contact. */
|
|
107
|
+
relatedId: string
|
|
108
|
+
relatedType: string | null
|
|
109
|
+
/**
|
|
110
|
+
* The value as stored: text, or JSON text for the composite types (`date-range`, `hour-range`,
|
|
111
|
+
* `numeric`, `monetary`, `phone`, `postal-code`).
|
|
112
|
+
*/
|
|
113
|
+
value: string
|
|
114
|
+
createdAt: string
|
|
115
|
+
updatedAt: string
|
|
116
|
+
deletedAt: string | null
|
|
117
|
+
// relationships
|
|
118
|
+
customField?: CustomField
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* A custom field of the contact as `formatCustomFields: true` answers it, keyed by the name of the
|
|
123
|
+
* field in `Contact.customFields`.
|
|
124
|
+
*/
|
|
125
|
+
export type FormattedCustomField = {
|
|
126
|
+
name: string
|
|
127
|
+
/** The value, parsed from JSON for the composite types. */
|
|
128
|
+
value: unknown
|
|
129
|
+
/** Id of the value. */
|
|
130
|
+
id: string
|
|
131
|
+
type: CustomFieldType
|
|
132
|
+
/** Id of the field. */
|
|
133
|
+
fieldId: string
|
|
134
|
+
/** When the field was created. */
|
|
135
|
+
createdAt: string
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/** A custom field value sent in the create or update of a contact. */
|
|
139
|
+
export type ContactCustomFieldInput = {
|
|
140
|
+
/**
|
|
141
|
+
* Id of the custom field (`CustomField.id`, `FormattedCustomField.fieldId` or
|
|
142
|
+
* `CustomFieldValue.customFieldId`), not the id of the value.
|
|
143
|
+
*/
|
|
144
|
+
id: string
|
|
145
|
+
/** Text, or an object for the composite types (stored as JSON). */
|
|
146
|
+
value: unknown
|
|
147
|
+
}
|
|
148
|
+
|
|
98
149
|
export type Contact = {
|
|
99
150
|
id: string
|
|
100
151
|
idFromService: string | null
|
|
@@ -139,6 +190,13 @@ export type Contact = {
|
|
|
139
190
|
person?: Person | null
|
|
140
191
|
tags?: Tag[]
|
|
141
192
|
currentTicket?: Ticket | null
|
|
193
|
+
/** With `include: ['customFieldValues']`, unless `formatCustomFields` is set. */
|
|
194
|
+
customFieldValues?: CustomFieldValue[]
|
|
195
|
+
/**
|
|
196
|
+
* With `formatCustomFields: true` and the include
|
|
197
|
+
* `{ model: 'customFieldValues', include: ['customField'] }`: the values keyed by the field name.
|
|
198
|
+
*/
|
|
199
|
+
customFields?: Record<string, FormattedCustomField>
|
|
142
200
|
}
|
|
143
201
|
|
|
144
202
|
export type ContactRelationships =
|
|
@@ -148,6 +206,23 @@ export type ContactRelationships =
|
|
|
148
206
|
| 'person'
|
|
149
207
|
| 'tags'
|
|
150
208
|
| 'currentTicket'
|
|
209
|
+
| 'customFieldValues'
|
|
210
|
+
| 'customFields'
|
|
211
|
+
|
|
212
|
+
type FormatCustomFieldsOption = {
|
|
213
|
+
/**
|
|
214
|
+
* Answers `customFields` keyed by the field name instead of the raw `customFieldValues` (with the
|
|
215
|
+
* include `{ model: 'customFieldValues', include: ['customField'] }`; without the nested
|
|
216
|
+
* `customField`, `customFields` comes empty).
|
|
217
|
+
*/
|
|
218
|
+
formatCustomFields?: boolean
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
/** Query of `ContactsApi.getById`. */
|
|
222
|
+
export type ContactGetByIdQuery = GetByIdQuery<Contact> & FormatCustomFieldsOption
|
|
223
|
+
|
|
224
|
+
/** Query of `ContactsApi.getMany` and `getOne`. */
|
|
225
|
+
export type ContactListQuery = ListQuery<Contact> & FormatCustomFieldsOption
|
|
151
226
|
|
|
152
227
|
export type CreateContactPayload = {
|
|
153
228
|
name?: string
|
|
@@ -160,6 +235,8 @@ export type CreateContactPayload = {
|
|
|
160
235
|
data?: ContactData
|
|
161
236
|
note?: string
|
|
162
237
|
origin?: ContactOrigin
|
|
238
|
+
/** Values of the custom fields of the account. An id that is not a custom field answers 400. */
|
|
239
|
+
customFields?: ContactCustomFieldInput[]
|
|
163
240
|
}
|
|
164
241
|
|
|
165
242
|
export type UpdateContactPayload = {
|
|
@@ -174,6 +251,11 @@ export type UpdateContactPayload = {
|
|
|
174
251
|
block?: boolean
|
|
175
252
|
/** Tag IDs to associate with the contact. */
|
|
176
253
|
tagIds?: string[]
|
|
254
|
+
/**
|
|
255
|
+
* Values of the custom fields of the account: a value of the same field is updated. An id that is
|
|
256
|
+
* not a custom field is skipped.
|
|
257
|
+
*/
|
|
258
|
+
customFields?: ContactCustomFieldInput[]
|
|
177
259
|
}
|
|
178
260
|
|
|
179
261
|
/** Result of `ContactsApi.summarizeTicket`. */
|
|
@@ -209,6 +291,34 @@ export type TransferTicketPayload = {
|
|
|
209
291
|
kanbanCardColumnId?: string
|
|
210
292
|
kanbanCardSubject?: string
|
|
211
293
|
initialMessage?: string
|
|
294
|
+
/** `true` (the boolean) resolves the id of the kanban card instead of `true`. */
|
|
295
|
+
includeKanbanCardId?: boolean
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
/** What `ContactsApi.transferTicket` resolves to with `includeKanbanCardId: true`. */
|
|
299
|
+
export type TransferTicketKanbanCardResult = {
|
|
300
|
+
/**
|
|
301
|
+
* The kanban card of the ticket (created, or the contact's card moved, in `kanbanCardColumnId`);
|
|
302
|
+
* `null` without `kanbanCardColumnId` (even when the ticket gets a card in the initial column of
|
|
303
|
+
* the board: send `kanbanCardColumnId` to read its id), when the department has no board, or when
|
|
304
|
+
* the call only released a closed ticket.
|
|
305
|
+
*/
|
|
306
|
+
kanbanCardId: string | null
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
/** The rating of the AI summary of the ticket. */
|
|
310
|
+
export type AiSummaryRating = '1' | '2' | '3' | '4' | '5'
|
|
311
|
+
|
|
312
|
+
export type CloseTicketPayload = {
|
|
313
|
+
/**
|
|
314
|
+
* Subjects of the ticket: of its department, or linked to no department. An unknown subject, or
|
|
315
|
+
* one of another department, answers 400.
|
|
316
|
+
*/
|
|
317
|
+
ticketTopicIds?: string[]
|
|
318
|
+
/** The closing comment. */
|
|
319
|
+
comments?: string
|
|
320
|
+
/** Stored as the feedback of the AI summary of the ticket. */
|
|
321
|
+
aiSummaryRating?: AiSummaryRating
|
|
212
322
|
}
|
|
213
323
|
|
|
214
324
|
/**
|
|
@@ -83,6 +83,6 @@ describe('CreditMovementsApi', () => {
|
|
|
83
83
|
const withoutRaw: ApiClient = { ...client, requestRaw: undefined }
|
|
84
84
|
await expect(
|
|
85
85
|
new CreditMovementsApi(withoutRaw).exportXlsx({ from: 'a', to: 'b', where: { $and: [] } }),
|
|
86
|
-
).rejects.toThrow('requestRaw')
|
|
86
|
+
).rejects.toThrow('exportXlsx needs a client with requestRaw')
|
|
87
87
|
})
|
|
88
88
|
})
|
|
@@ -22,10 +22,10 @@ export type CustomFieldOption = {
|
|
|
22
22
|
}
|
|
23
23
|
|
|
24
24
|
/**
|
|
25
|
-
* Settings of a custom field
|
|
26
|
-
*
|
|
27
|
-
*
|
|
28
|
-
* `
|
|
25
|
+
* Settings of a custom field (a free JSON object, answered as stored). The fields below are the
|
|
26
|
+
* ones the web app form sends: `options` for the `list` and `checkbox` types, `min`/`max` for
|
|
27
|
+
* `numeric` and `monetary`, `currency` for `monetary`, `maxLength` for `text` and `long-text`, and
|
|
28
|
+
* `placeholder` for the inputs.
|
|
29
29
|
*/
|
|
30
30
|
export type CustomFieldSettings = {
|
|
31
31
|
options?: CustomFieldOption[]
|
|
@@ -47,3 +47,12 @@ expectType<Promise<DashboardPeriodItem[] | DashboardGrouped<DashboardPeriodItem>
|
|
|
47
47
|
expectError(dashboard.getByPeriod({ grouping: 'quarterly' }))
|
|
48
48
|
expectError(dashboard.getByTopic({ withTotals: true }))
|
|
49
49
|
expectError(dashboard.getByService({ withTotals: true }))
|
|
50
|
+
|
|
51
|
+
// ── one connection, tag and subject (not a list) ────────────────────
|
|
52
|
+
|
|
53
|
+
expectType<Promise<DashboardPeriodItem[]>>(
|
|
54
|
+
dashboard.getByPeriod({ serviceId: 's-1', tagId: 't-1', ticketTopicId: 'tt-1' }),
|
|
55
|
+
)
|
|
56
|
+
expectError(dashboard.getByPeriod({ serviceId: ['s-1', 's-2'] }))
|
|
57
|
+
expectError(dashboard.getByPeriod({ tagId: ['t-1'] }))
|
|
58
|
+
expectError(dashboard.getByPeriod({ ticketTopicId: ['tt-1'] }))
|
|
@@ -12,9 +12,9 @@ import type {
|
|
|
12
12
|
} from './types'
|
|
13
13
|
|
|
14
14
|
/**
|
|
15
|
-
* Service statistics ("Estatísticas de atendimento").
|
|
16
|
-
*
|
|
17
|
-
*
|
|
15
|
+
* Service statistics ("Estatísticas de atendimento"). Every route takes the same
|
|
16
|
+
* {@link DashboardQuery} filters; the grouped routes answer one item per day, user, department,
|
|
17
|
+
* topic or connection.
|
|
18
18
|
*/
|
|
19
19
|
export class DashboardApi extends BaseApi {
|
|
20
20
|
public readonly basePath = '/dashboard'
|
|
@@ -14,7 +14,11 @@ export type DashboardQuery = {
|
|
|
14
14
|
startPeriod?: string
|
|
15
15
|
/** ISO date-time. Default: the end of the `startPeriod` day (or of today). */
|
|
16
16
|
endPeriod?: string
|
|
17
|
-
/**
|
|
17
|
+
/**
|
|
18
|
+
* Which ticket date the period filters: opening (`openDate`, the default) or closing. Sent
|
|
19
|
+
* without it, together with `status: 'all'`, the period is not applied. `getByPeriod` needs it:
|
|
20
|
+
* always send it there (the `openDate` default does not apply to that route).
|
|
21
|
+
*/
|
|
18
22
|
periodType?: 'openDate' | 'closeDate'
|
|
19
23
|
/** Ticket status (`closed`, not `close`). */
|
|
20
24
|
status?: 'all' | 'open' | 'closed'
|
|
@@ -39,9 +43,12 @@ export type DashboardQuery = {
|
|
|
39
43
|
*/
|
|
40
44
|
userParticipation?: 'last' | 'middle'
|
|
41
45
|
userStatus?: 'active' | 'archived' | 'all'
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
46
|
+
/** One connection id (unlike `departmentId` and `userId`, not a list). */
|
|
47
|
+
serviceId?: string
|
|
48
|
+
/** One tag id (not a list). */
|
|
49
|
+
tagId?: string
|
|
50
|
+
/** One ticket subject id (not a list). */
|
|
51
|
+
ticketTopicId?: string
|
|
45
52
|
/**
|
|
46
53
|
* Granularity of the `getByPeriod` items (the other routes ignore it). Default: `daily`. See
|
|
47
54
|
* {@link DashboardGrouping} for the `name` of the items.
|
|
@@ -21,11 +21,11 @@ export class DepartmentsApi extends ArchivableCrudApi<
|
|
|
21
21
|
|
|
22
22
|
/**
|
|
23
23
|
* Archives (`archive: true`) or restores (`archive: false`) a department through the route used
|
|
24
|
-
* by the UI
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
* connections, marks its schedules as done and unlinks its users and quick replies. Resolves
|
|
28
|
-
* stored department (not transformed); an unknown id answers 500.
|
|
24
|
+
* by the UI: archiving refuses (403 `Cannot archive department.`) a department in use, or when it
|
|
25
|
+
* is the only active department of the account (the `extra` of the error is an
|
|
26
|
+
* `ArchiveDepartmentErrorExtra`). Archiving also clears it as the default department of contacts
|
|
27
|
+
* and connections, marks its schedules as done and unlinks its users and quick replies. Resolves
|
|
28
|
+
* the stored department (not transformed); an unknown id answers 500.
|
|
29
29
|
* @permissions departments.view OR departments.archive
|
|
30
30
|
*/
|
|
31
31
|
archiveWithValidation(
|