@floristcloud/api-lib 1.2.140 → 1.2.142

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.
@@ -16,6 +16,13 @@ const GetClientListRequestSchema = zod_1.z.object({
16
16
  searchQuery: zod_1.z.string().optional(),
17
17
  sortByBalance: zod_1.z.union([zod_1.z.literal('asc'), zod_1.z.literal('desc')]).optional(),
18
18
  responsibleUserUUID: zod_1.z.string().optional(),
19
+ // Клиенты без ответственного. Отдельный флаг, а не responsibleUserUUID со специальным значением:
20
+ // в query всё приходит строкой, и «null» пришлось бы отличать от клиента с таким именем.
21
+ // true — только с ответственным, false — только без него.
22
+ hasResponsible: zod_1.z
23
+ .string()
24
+ .optional()
25
+ .transform(val => (val === 'true' ? true : val === 'false' ? false : undefined)),
19
26
  hasContract: zod_1.z
20
27
  .string()
21
28
  .optional()
@@ -0,0 +1,16 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.AssignGroupClientResponsibleContractCommand = void 0;
4
+ const zod_1 = require("zod");
5
+ const client_responsible_assignment_schema_1 = require("../../../schemas/client/client-responsible-assignment.schema");
6
+ const client_responsible_assignment_result_schema_1 = require("../../../schemas/client/client-responsible-assignment-result.schema");
7
+ const AssignGroupClientResponsibleRequestSchema = client_responsible_assignment_schema_1.ClientResponsibleAssignmentSchema;
8
+ const AssignGroupClientResponsibleResponseSchema = zod_1.z.object({
9
+ message: zod_1.z.string().optional(),
10
+ data: client_responsible_assignment_result_schema_1.ClientResponsibleAssignmentResultSchema,
11
+ });
12
+ var AssignGroupClientResponsibleContractCommand;
13
+ (function (AssignGroupClientResponsibleContractCommand) {
14
+ AssignGroupClientResponsibleContractCommand.RequestSchema = AssignGroupClientResponsibleRequestSchema;
15
+ AssignGroupClientResponsibleContractCommand.ResponseSchema = AssignGroupClientResponsibleResponseSchema;
16
+ })(AssignGroupClientResponsibleContractCommand || (exports.AssignGroupClientResponsibleContractCommand = AssignGroupClientResponsibleContractCommand = {}));
@@ -35,3 +35,4 @@ __exportStar(require("./marking/create-client-marking.command"), exports);
35
35
  __exportStar(require("./marking/update-client-marking.command"), exports);
36
36
  __exportStar(require("./marking/delete-client-marking.command"), exports);
37
37
  __exportStar(require("./marking/get-client-marking-by-client-list.command"), exports);
38
+ __exportStar(require("./group/assign-group-client-responsible.command"), exports);
@@ -9,10 +9,24 @@ const PriceCorrectionAnalyzeRequestSchema = zod_1.z
9
9
  .object({
10
10
  productUUIDList: zod_1.z.array(zod_1.z.string().uuid()).optional(),
11
11
  consignmentUUID: zod_1.z.string().uuid().optional(),
12
+ /**
13
+ * Режим цены — обязателен и без умолчания, как в execute.
14
+ *
15
+ * Раньше analyze этого поля не знал и считал `onlyChanged` по OR обоих режимов: строка
16
+ * попадала в выдачу, если разошлась цена со скидкой ИЛИ без. На клиенте с фиксированной
17
+ * скидкой это выносило в предпросмотр каждую его позицию — цена строки законно ниже
18
+ * каталожной ровно на скидку, и «без скидок» это выглядит расхождением. Execute при этом
19
+ * считает предикат в выбранном режиме, то есть предпросмотр и применение расходились на
20
+ * целую партию.
21
+ */
22
+ withDiscount: zod_1.z.boolean(),
12
23
  // Поставка на сотни товаров даёт десятки тысяч позиций, из которых после правки прайса
13
24
  // меняются единицы. По умолчанию отдаём только те, где цена реально расходится; полный
14
25
  // список — режим «показать всё».
15
26
  onlyChanged: zod_1.z.boolean().optional().default(true),
27
+ // Позиции, которые применить нельзя (статус заказа, заказ в передаточном документе).
28
+ // `true` — скрыть их из выдачи; сколько их всего, видно по `skippedTotal`.
29
+ excludeSkipped: zod_1.z.boolean().optional().default(false),
16
30
  // Страница обязательна по смыслу, а не по схеме: строк здесь товары × заказы, то есть
17
31
  // десятки тысяч на партию, и безлимитная выдача кладёт запрос независимо от того, сколько
18
32
  // из неё нарисует таблица. Усечение при этом урезает только предпросмотр — execute в
@@ -33,8 +47,20 @@ const PriceCorrectionAnalyzeResponseSchema = zod_1.z.object({
33
47
  message: zod_1.z.string().optional(),
34
48
  data: zod_1.z.object({
35
49
  items: zod_1.z.array(schemas_1.PriceCorrectionAnalyzeItemSchema),
36
- // Сколько строк во всём наборе после фильтра `onlyChanged`, а не на странице.
50
+ /**
51
+ * Размер выдачи, а не страницы: по нему листают. Учитывает ВСЕ фильтры запроса, включая
52
+ * `excludeSkipped`.
53
+ */
37
54
  total: zod_1.z.number(),
55
+ /**
56
+ * Сколько строк набора применить нельзя — статус заказа или заказ в передаточном документе.
57
+ *
58
+ * Считается по набору после `onlyChanged`, но ДО `excludeSkipped`: иначе при скрытых
59
+ * непроходных строках это всегда был бы ноль и шапку «столько-то не пройдёт» стало бы не из
60
+ * чего собрать. Отсюда: применимых строк — `total` при `excludeSkipped: true` и
61
+ * `total − skippedTotal` при `false`.
62
+ */
63
+ skippedTotal: zod_1.z.number(),
38
64
  }),
39
65
  });
40
66
  var PriceCorrectionAnalyzeContractCommand;
@@ -42,7 +42,17 @@ const PriceCorrectionExecuteResponseSchema = zod_1.z.object({
42
42
  // равно перезапрашивает analyze, чтобы обновить таблицу.
43
43
  results: zod_1.z.array(schemas_1.PriceCorrectionExecuteResultItemSchema),
44
44
  orders: zod_1.z.array(schemas_1.PriceCorrectionExecuteOrderItemSchema),
45
+ /**
46
+ * «Строк в нужной цене после прогона», а не «строк изменено».
47
+ *
48
+ * Применение сходящееся: позиция, уже стоящая в нужной цене, — успех, а не отказ, поэтому
49
+ * повтор запроса и ретрай после таймаута безопасны и дают тот же ответ. Из-за этого при
50
+ * `onlyChanged: false` в счётчик попадают и нетронутые позиции. При `onlyChanged: true`
51
+ * таких строк здесь не будет: они отсеиваются до обработки и в счётчики не идут вовсе.
52
+ */
45
53
  successCount: zod_1.z.number(),
54
+ // Строки, которые прогон не применил: статус заказа, заказ в передаточном документе, отказ
55
+ // применения. Каждая из них есть в `results` — с точностью до потолка (см. `isTruncated`).
46
56
  skippedCount: zod_1.z.number(),
47
57
  // `results` в scope-форме обрезан по лимиту. Полные числа — в счётчиках и в `orders`.
48
58
  isTruncated: zod_1.z.boolean(),
@@ -0,0 +1,8 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.CLIENT_GROUP_ACTIONS_LIMITS = void 0;
4
+ exports.CLIENT_GROUP_ACTIONS_LIMITS = {
5
+ // Верхняя граница на размер группы: панель шлёт выделение со страницы списка,
6
+ // а необъявленный предел означал бы неограниченный UPDATE по чужому запросу.
7
+ MAX_CLIENTS_PER_REQUEST: 500,
8
+ };
@@ -144,6 +144,11 @@ exports.ERRORS = {
144
144
  CLIENT_FETCH_FAILED: { code: 'CL005', message: 'Error when retrieving a list of clients', httpCode: 500 },
145
145
  CLIENT_ALREADY_EXIST: { code: 'CL006', message: 'Client with this properties already exist', httpCode: 409 },
146
146
  CLIENT_ACCESS_DENIED: { code: 'CL043', message: 'You are not responsible for this client', httpCode: 403 },
147
+ CLIENT_RESPONSIBLE_USER_NOT_ASSIGNABLE: {
148
+ code: 'CL045',
149
+ message: 'The responsible user does not belong to this company or has no panel role',
150
+ httpCode: 404,
151
+ },
147
152
  CLIENT_EMAIL_ALREADY_EXIST: { code: 'CL007', message: 'Client with this email already exist', httpCode: 409 },
148
153
  CLIENT_PHONE_ALREADY_EXIST: { code: 'CL008', message: 'Client with this phone already exist', httpCode: 409 },
149
154
  CLIENT_WITH_SAME_USER_ALREADY_EXIST: { code: 'CL009', message: 'Client with same user already exist', httpCode: 409 },
@@ -28,3 +28,4 @@ __exportStar(require("./settings.constant"), exports);
28
28
  __exportStar(require("./consignment-product-enrichment.constant"), exports);
29
29
  __exportStar(require("./attribute-normalization.constant"), exports);
30
30
  __exportStar(require("./product-image-merge.constant"), exports);
31
+ __exportStar(require("./client-group-actions.constant"), exports);
@@ -0,0 +1,10 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ClientResponsibleAssignmentResultSchema = void 0;
4
+ const zod_1 = require("zod");
5
+ // Итог группового переназначения ответственного.
6
+ exports.ClientResponsibleAssignmentResultSchema = zod_1.z.object({
7
+ // Клиентов, у которых назначение действительно изменилось. Те, у кого ответственный
8
+ // уже такой, в счёт не попадают — им не переписывается и дата назначения.
9
+ updatedCount: zod_1.z.number().int().nonnegative(),
10
+ });
@@ -0,0 +1,12 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ClientResponsibleAssignmentSchema = void 0;
4
+ const zod_1 = require("zod");
5
+ const client_group_actions_constant_1 = require("../../constant/client-group-actions.constant");
6
+ // Кому и за каких клиентов переназначить ответственность.
7
+ exports.ClientResponsibleAssignmentSchema = zod_1.z.object({
8
+ clientUUIDList: zod_1.z.array(zod_1.z.uuid()).min(1).max(client_group_actions_constant_1.CLIENT_GROUP_ACTIONS_LIMITS.MAX_CLIENTS_PER_REQUEST),
9
+ // null — снять ответственного. Поле обязательное: пропуск означал бы «не менять»,
10
+ // а групповое действие без изменения не имеет смысла и скрывал бы опечатку на фронте.
11
+ responsibleUserUUID: zod_1.z.uuid().nullable(),
12
+ });
@@ -19,3 +19,5 @@ __exportStar(require("./client-individual-profile.schema"), exports);
19
19
  __exportStar(require("./client-legal-profile.schema"), exports);
20
20
  __exportStar(require("./client-marking.schema"), exports);
21
21
  __exportStar(require("./client-debt.schema"), exports);
22
+ __exportStar(require("./client-responsible-assignment.schema"), exports);
23
+ __exportStar(require("./client-responsible-assignment-result.schema"), exports);
@@ -14,6 +14,13 @@ const GetClientListRequestSchema = z.object({
14
14
  searchQuery: z.string().optional(),
15
15
  sortByBalance: z.union([z.literal('asc'), z.literal('desc')]).optional(),
16
16
  responsibleUserUUID: z.string().optional(),
17
+ // Клиенты без ответственного. Отдельный флаг, а не responsibleUserUUID со специальным значением:
18
+ // в query всё приходит строкой, и «null» пришлось бы отличать от клиента с таким именем.
19
+ // true — только с ответственным, false — только без него.
20
+ hasResponsible: z
21
+ .string()
22
+ .optional()
23
+ .transform(val => (val === 'true' ? true : val === 'false' ? false : undefined)),
17
24
  hasContract: z
18
25
  .string()
19
26
  .optional()
@@ -0,0 +1,18 @@
1
+ import { z } from 'zod';
2
+ import { ClientResponsibleAssignmentSchema } from '../../../schemas/client/client-responsible-assignment.schema';
3
+ import { ClientResponsibleAssignmentResultSchema } from '../../../schemas/client/client-responsible-assignment-result.schema';
4
+
5
+ const AssignGroupClientResponsibleRequestSchema = ClientResponsibleAssignmentSchema;
6
+
7
+ const AssignGroupClientResponsibleResponseSchema = z.object({
8
+ message: z.string().optional(),
9
+ data: ClientResponsibleAssignmentResultSchema,
10
+ });
11
+
12
+ export namespace AssignGroupClientResponsibleContractCommand {
13
+ export const RequestSchema = AssignGroupClientResponsibleRequestSchema;
14
+ export type Request = z.infer<typeof RequestSchema>;
15
+
16
+ export const ResponseSchema = AssignGroupClientResponsibleResponseSchema;
17
+ export type Response = z.infer<typeof ResponseSchema>;
18
+ }
@@ -19,3 +19,4 @@ export * from './marking/create-client-marking.command';
19
19
  export * from './marking/update-client-marking.command';
20
20
  export * from './marking/delete-client-marking.command';
21
21
  export * from './marking/get-client-marking-by-client-list.command';
22
+ export * from './group/assign-group-client-responsible.command';
@@ -8,11 +8,28 @@ const PriceCorrectionAnalyzeRequestSchema = z
8
8
  .object({
9
9
  productUUIDList: z.array(z.string().uuid()).optional(),
10
10
  consignmentUUID: z.string().uuid().optional(),
11
+
12
+ /**
13
+ * Режим цены — обязателен и без умолчания, как в execute.
14
+ *
15
+ * Раньше analyze этого поля не знал и считал `onlyChanged` по OR обоих режимов: строка
16
+ * попадала в выдачу, если разошлась цена со скидкой ИЛИ без. На клиенте с фиксированной
17
+ * скидкой это выносило в предпросмотр каждую его позицию — цена строки законно ниже
18
+ * каталожной ровно на скидку, и «без скидок» это выглядит расхождением. Execute при этом
19
+ * считает предикат в выбранном режиме, то есть предпросмотр и применение расходились на
20
+ * целую партию.
21
+ */
22
+ withDiscount: z.boolean(),
23
+
11
24
  // Поставка на сотни товаров даёт десятки тысяч позиций, из которых после правки прайса
12
25
  // меняются единицы. По умолчанию отдаём только те, где цена реально расходится; полный
13
26
  // список — режим «показать всё».
14
27
  onlyChanged: z.boolean().optional().default(true),
15
28
 
29
+ // Позиции, которые применить нельзя (статус заказа, заказ в передаточном документе).
30
+ // `true` — скрыть их из выдачи; сколько их всего, видно по `skippedTotal`.
31
+ excludeSkipped: z.boolean().optional().default(false),
32
+
16
33
  // Страница обязательна по смыслу, а не по схеме: строк здесь товары × заказы, то есть
17
34
  // десятки тысяч на партию, и безлимитная выдача кладёт запрос независимо от того, сколько
18
35
  // из неё нарисует таблица. Усечение при этом урезает только предпросмотр — execute в
@@ -34,8 +51,22 @@ const PriceCorrectionAnalyzeResponseSchema = z.object({
34
51
  message: z.string().optional(),
35
52
  data: z.object({
36
53
  items: z.array(PriceCorrectionAnalyzeItemSchema),
37
- // Сколько строк во всём наборе после фильтра `onlyChanged`, а не на странице.
54
+
55
+ /**
56
+ * Размер выдачи, а не страницы: по нему листают. Учитывает ВСЕ фильтры запроса, включая
57
+ * `excludeSkipped`.
58
+ */
38
59
  total: z.number(),
60
+
61
+ /**
62
+ * Сколько строк набора применить нельзя — статус заказа или заказ в передаточном документе.
63
+ *
64
+ * Считается по набору после `onlyChanged`, но ДО `excludeSkipped`: иначе при скрытых
65
+ * непроходных строках это всегда был бы ноль и шапку «столько-то не пройдёт» стало бы не из
66
+ * чего собрать. Отсюда: применимых строк — `total` при `excludeSkipped: true` и
67
+ * `total − skippedTotal` при `false`.
68
+ */
69
+ skippedTotal: z.number(),
39
70
  }),
40
71
  });
41
72
 
@@ -47,7 +47,19 @@ const PriceCorrectionExecuteResponseSchema = z.object({
47
47
  // равно перезапрашивает analyze, чтобы обновить таблицу.
48
48
  results: z.array(PriceCorrectionExecuteResultItemSchema),
49
49
  orders: z.array(PriceCorrectionExecuteOrderItemSchema),
50
+
51
+ /**
52
+ * «Строк в нужной цене после прогона», а не «строк изменено».
53
+ *
54
+ * Применение сходящееся: позиция, уже стоящая в нужной цене, — успех, а не отказ, поэтому
55
+ * повтор запроса и ретрай после таймаута безопасны и дают тот же ответ. Из-за этого при
56
+ * `onlyChanged: false` в счётчик попадают и нетронутые позиции. При `onlyChanged: true`
57
+ * таких строк здесь не будет: они отсеиваются до обработки и в счётчики не идут вовсе.
58
+ */
50
59
  successCount: z.number(),
60
+
61
+ // Строки, которые прогон не применил: статус заказа, заказ в передаточном документе, отказ
62
+ // применения. Каждая из них есть в `results` — с точностью до потолка (см. `isTruncated`).
51
63
  skippedCount: z.number(),
52
64
  // `results` в scope-форме обрезан по лимиту. Полные числа — в счётчиках и в `orders`.
53
65
  isTruncated: z.boolean(),
@@ -0,0 +1,5 @@
1
+ export const CLIENT_GROUP_ACTIONS_LIMITS = {
2
+ // Верхняя граница на размер группы: панель шлёт выделение со страницы списка,
3
+ // а необъявленный предел означал бы неограниченный UPDATE по чужому запросу.
4
+ MAX_CLIENTS_PER_REQUEST: 500,
5
+ } as const;
package/constant/error.ts CHANGED
@@ -149,6 +149,11 @@ export const ERRORS = {
149
149
  CLIENT_FETCH_FAILED: { code: 'CL005', message: 'Error when retrieving a list of clients', httpCode: 500 },
150
150
  CLIENT_ALREADY_EXIST: { code: 'CL006', message: 'Client with this properties already exist', httpCode: 409 },
151
151
  CLIENT_ACCESS_DENIED: { code: 'CL043', message: 'You are not responsible for this client', httpCode: 403 },
152
+ CLIENT_RESPONSIBLE_USER_NOT_ASSIGNABLE: {
153
+ code: 'CL045',
154
+ message: 'The responsible user does not belong to this company or has no panel role',
155
+ httpCode: 404,
156
+ },
152
157
  CLIENT_EMAIL_ALREADY_EXIST: { code: 'CL007', message: 'Client with this email already exist', httpCode: 409 },
153
158
  CLIENT_PHONE_ALREADY_EXIST: { code: 'CL008', message: 'Client with this phone already exist', httpCode: 409 },
154
159
  CLIENT_WITH_SAME_USER_ALREADY_EXIST: { code: 'CL009', message: 'Client with same user already exist', httpCode: 409 },
package/constant/index.ts CHANGED
@@ -12,3 +12,4 @@ export * from './settings.constant';
12
12
  export * from './consignment-product-enrichment.constant';
13
13
  export * from './attribute-normalization.constant';
14
14
  export * from './product-image-merge.constant';
15
+ export * from './client-group-actions.constant';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@floristcloud/api-lib",
3
- "version": "1.2.140",
3
+ "version": "1.2.142",
4
4
  "description": "",
5
5
  "main": "./build/index.js",
6
6
  "scripts": {
@@ -0,0 +1,8 @@
1
+ import { z } from 'zod';
2
+
3
+ // Итог группового переназначения ответственного.
4
+ export const ClientResponsibleAssignmentResultSchema = z.object({
5
+ // Клиентов, у которых назначение действительно изменилось. Те, у кого ответственный
6
+ // уже такой, в счёт не попадают — им не переписывается и дата назначения.
7
+ updatedCount: z.number().int().nonnegative(),
8
+ });
@@ -0,0 +1,10 @@
1
+ import { z } from 'zod';
2
+ import { CLIENT_GROUP_ACTIONS_LIMITS } from '../../constant/client-group-actions.constant';
3
+
4
+ // Кому и за каких клиентов переназначить ответственность.
5
+ export const ClientResponsibleAssignmentSchema = z.object({
6
+ clientUUIDList: z.array(z.uuid()).min(1).max(CLIENT_GROUP_ACTIONS_LIMITS.MAX_CLIENTS_PER_REQUEST),
7
+ // null — снять ответственного. Поле обязательное: пропуск означал бы «не менять»,
8
+ // а групповое действие без изменения не имеет смысла и скрывал бы опечатку на фронте.
9
+ responsibleUserUUID: z.uuid().nullable(),
10
+ });
@@ -3,3 +3,5 @@ export * from './client-individual-profile.schema';
3
3
  export * from './client-legal-profile.schema';
4
4
  export * from './client-marking.schema';
5
5
  export * from './client-debt.schema';
6
+ export * from './client-responsible-assignment.schema';
7
+ export * from './client-responsible-assignment-result.schema';