@floristcloud/api-lib 1.2.132 → 1.2.133

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.
@@ -0,0 +1,68 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.AnalyzeConsignmentProductEnrichmentContractQuery = void 0;
4
+ const zod_1 = require("zod");
5
+ const query_boolean_helper_1 = require("../../helpers/query-boolean.helper");
6
+ const consignment_product_enrichment_constant_1 = require("../../constant/consignment-product-enrichment.constant");
7
+ const product_enrichment_field_enum_1 = require("../../enum/product-enrichment-field.enum");
8
+ const product_enrichment_field_state_enum_1 = require("../../enum/product-enrichment-field-state.enum");
9
+ const AnalyzeConsignmentProductEnrichmentRequestSchema = zod_1.z.object({
10
+ page: zod_1.z.coerce.number().int().min(1).default(1),
11
+ count: zod_1.z.coerce
12
+ .number()
13
+ .int()
14
+ .min(1)
15
+ .max(consignment_product_enrichment_constant_1.CONSIGNMENT_PRODUCT_ENRICHMENT_LIMITS.MAX_PAGE_SIZE)
16
+ .default(consignment_product_enrichment_constant_1.CONSIGNMENT_PRODUCT_ENRICHMENT_LIMITS.DEFAULT_PAGE_SIZE),
17
+ // Показывать только товары, у которых есть хотя бы одно поле к заполнению или конфликт.
18
+ // По умолчанию false: пользователь видит всю поставку и понимает, почему строк меньше, чем товаров.
19
+ // Не `z.coerce.boolean()`: в query приходит текст, а `Boolean('false') === true` — флаг нельзя
20
+ // было бы выключить явным значением.
21
+ isOnlyChanged: query_boolean_helper_1.queryBooleanSchema,
22
+ });
23
+ const ProductEnrichmentFieldSchema = zod_1.z.object({
24
+ current: zod_1.z.string().nullable(),
25
+ proposed: zod_1.z.string().nullable(),
26
+ state: zod_1.z.nativeEnum(product_enrichment_field_state_enum_1.ProductEnrichmentFieldStateEnum),
27
+ });
28
+ const ProductEnrichmentItemSchema = zod_1.z.object({
29
+ productUUID: zod_1.z.string(),
30
+ productName: zod_1.z.string(),
31
+ article: zod_1.z.string().nullable(),
32
+ size: zod_1.z.string().nullable(),
33
+ categoryName: zod_1.z.string().nullable(),
34
+ imageUUID: zod_1.z.string(),
35
+ imageName: zod_1.z.string(),
36
+ imageUrl: zod_1.z.string(),
37
+ fields: zod_1.z.record(zod_1.z.nativeEnum(product_enrichment_field_enum_1.ProductEnrichmentFieldEnum), ProductEnrichmentFieldSchema),
38
+ });
39
+ const ProductEnrichmentFieldStatsSchema = zod_1.z.object({
40
+ fillable: zod_1.z.number(),
41
+ conflicts: zod_1.z.number(),
42
+ });
43
+ const ProductEnrichmentSummarySchema = zod_1.z.object({
44
+ // Всего товаров в поставке.
45
+ totalProducts: zod_1.z.number(),
46
+ // Из них с привязанной карточкой — только они попадают в таблицу.
47
+ linkedProducts: zod_1.z.number(),
48
+ // Товаров, у которых есть хотя бы одно поле к заполнению.
49
+ fillableProducts: zod_1.z.number(),
50
+ // Товаров, у которых есть хотя бы один конфликт.
51
+ conflictProducts: zod_1.z.number(),
52
+ byField: zod_1.z.record(zod_1.z.nativeEnum(product_enrichment_field_enum_1.ProductEnrichmentFieldEnum), ProductEnrichmentFieldStatsSchema),
53
+ });
54
+ const AnalyzeConsignmentProductEnrichmentResponseSchema = zod_1.z.object({
55
+ data: zod_1.z.object({
56
+ items: zod_1.z.array(ProductEnrichmentItemSchema),
57
+ total: zod_1.z.number(),
58
+ page: zod_1.z.number(),
59
+ count: zod_1.z.number(),
60
+ // Считается по всей поставке, а не по текущей странице: иначе счётчики прыгали бы при листании.
61
+ summary: ProductEnrichmentSummarySchema,
62
+ }),
63
+ });
64
+ var AnalyzeConsignmentProductEnrichmentContractQuery;
65
+ (function (AnalyzeConsignmentProductEnrichmentContractQuery) {
66
+ AnalyzeConsignmentProductEnrichmentContractQuery.RequestSchema = AnalyzeConsignmentProductEnrichmentRequestSchema;
67
+ AnalyzeConsignmentProductEnrichmentContractQuery.ResponseSchema = AnalyzeConsignmentProductEnrichmentResponseSchema;
68
+ })(AnalyzeConsignmentProductEnrichmentContractQuery || (exports.AnalyzeConsignmentProductEnrichmentContractQuery = AnalyzeConsignmentProductEnrichmentContractQuery = {}));
@@ -0,0 +1,40 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ExecuteConsignmentProductEnrichmentContractCommand = void 0;
4
+ const zod_1 = require("zod");
5
+ const error_message_schema_1 = require("../../schemas/error-message.schema");
6
+ const consignment_product_enrichment_constant_1 = require("../../constant/consignment-product-enrichment.constant");
7
+ const product_enrichment_field_enum_1 = require("../../enum/product-enrichment-field.enum");
8
+ const ExecuteConsignmentProductEnrichmentItemSchema = zod_1.z.object({
9
+ productUUID: zod_1.z.string().uuid(),
10
+ // Какие поля переносим из карточки в этот товар. Пустой список — товар пропускается.
11
+ fields: zod_1.z.array(zod_1.z.nativeEnum(product_enrichment_field_enum_1.ProductEnrichmentFieldEnum)).min(1),
12
+ });
13
+ const ExecuteConsignmentProductEnrichmentRequestSchema = zod_1.z.object({
14
+ // Фронт шлёт пачками по EXECUTE_BATCH_SIZE и сам собирает итог: одна поставка может
15
+ // содержать до 1200 товаров, и одним запросом это отправлять не нужно.
16
+ // Повторы `productUUID` допустимы и схлопываются на сервере в объединение полей: товар
17
+ // обновляется и логируется один раз, сколько бы записей о нём ни пришло.
18
+ items: zod_1.z.array(ExecuteConsignmentProductEnrichmentItemSchema).min(1).max(consignment_product_enrichment_constant_1.CONSIGNMENT_PRODUCT_ENRICHMENT_LIMITS.EXECUTE_BATCH_SIZE),
19
+ });
20
+ const ExecuteConsignmentProductEnrichmentResponseSchema = zod_1.z.object({
21
+ data: zod_1.z.object({
22
+ success: zod_1.z.boolean(),
23
+ // Товаров, у которых изменилось хотя бы одно поле.
24
+ successCount: zod_1.z.number(),
25
+ // Товаров, где менять было нечего: значение уже совпадало или карточка опустела с момента разбора.
26
+ skippedCount: zod_1.z.number(),
27
+ // Товаров, которые кто-то изменил между разбором и применением. Отдельно от skipped, потому
28
+ // что это единственный исход, требующий действия: пользователю нужно перечитать разбор.
29
+ conflictedCount: zod_1.z.number(),
30
+ failedCount: zod_1.z.number(),
31
+ errors: zod_1.z.array(error_message_schema_1.ErrorMessageSchema.extend({
32
+ uuid: zod_1.z.string(),
33
+ })),
34
+ }),
35
+ });
36
+ var ExecuteConsignmentProductEnrichmentContractCommand;
37
+ (function (ExecuteConsignmentProductEnrichmentContractCommand) {
38
+ ExecuteConsignmentProductEnrichmentContractCommand.RequestSchema = ExecuteConsignmentProductEnrichmentRequestSchema;
39
+ ExecuteConsignmentProductEnrichmentContractCommand.ResponseSchema = ExecuteConsignmentProductEnrichmentResponseSchema;
40
+ })(ExecuteConsignmentProductEnrichmentContractCommand || (exports.ExecuteConsignmentProductEnrichmentContractCommand = ExecuteConsignmentProductEnrichmentContractCommand = {}));
@@ -29,3 +29,5 @@ __exportStar(require("./get-access-clients-consignment.query"), exports);
29
29
  __exportStar(require("./get-consignment-filters-values.query"), exports);
30
30
  __exportStar(require("./execute-consignment-product-update.command"), exports);
31
31
  __exportStar(require("./determine-consignment-product-images.command"), exports);
32
+ __exportStar(require("./analyze-consignment-product-enrichment.query"), exports);
33
+ __exportStar(require("./execute-consignment-product-enrichment.command"), exports);
@@ -0,0 +1,12 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.CONSIGNMENT_PRODUCT_ENRICHMENT_LIMITS = void 0;
4
+ // Лимиты операции «получить характеристики из номенклатуры».
5
+ // Анализ читает всю поставку целиком (потолок задан лимитами импорта: MAX_ROWS_WITHOUT_IMAGES = 1200),
6
+ // но наружу отдаёт страницами, а применение принимает пачками — чтобы ни ответ, ни запрос не росли
7
+ // вместе с размером поставки.
8
+ exports.CONSIGNMENT_PRODUCT_ENRICHMENT_LIMITS = {
9
+ DEFAULT_PAGE_SIZE: 50,
10
+ MAX_PAGE_SIZE: 200,
11
+ EXECUTE_BATCH_SIZE: 100,
12
+ };
@@ -25,3 +25,4 @@ __exportStar(require("./oksm"), exports);
25
25
  __exportStar(require("./okei"), exports);
26
26
  __exportStar(require("./contact-phone.constant"), exports);
27
27
  __exportStar(require("./settings.constant"), exports);
28
+ __exportStar(require("./consignment-product-enrichment.constant"), exports);
@@ -122,3 +122,5 @@ __exportStar(require("./transfer-document-state.enum"), exports);
122
122
  __exportStar(require("./transfer-document-kind.enum"), exports);
123
123
  __exportStar(require("./transfer-document-item-kind.enum"), exports);
124
124
  __exportStar(require("./write-off-report-date-basis.enum"), exports);
125
+ __exportStar(require("./product-enrichment-field.enum"), exports);
126
+ __exportStar(require("./product-enrichment-field-state.enum"), exports);
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ProductEnrichmentFieldStateEnum = void 0;
4
+ // Состояние одного поля товара относительно привязанной карточки номенклатуры.
5
+ // Определяет и подсказку в интерфейсе («собственные данные» / «из номенклатуры»), и то,
6
+ // отмечен ли чекбокс по умолчанию: предзаполняется только FILLABLE.
7
+ var ProductEnrichmentFieldStateEnum;
8
+ (function (ProductEnrichmentFieldStateEnum) {
9
+ // У товара пусто, в карточке значение есть — это и есть «дополнить».
10
+ ProductEnrichmentFieldStateEnum["FILLABLE"] = "FILLABLE";
11
+ // Оба заполнены и различаются. Показываем, но по умолчанию не отмечаем.
12
+ ProductEnrichmentFieldStateEnum["CONFLICT"] = "CONFLICT";
13
+ // Значения совпадают — брать нечего.
14
+ ProductEnrichmentFieldStateEnum["SAME"] = "SAME";
15
+ // В карточке пусто — источника нет.
16
+ ProductEnrichmentFieldStateEnum["NO_SOURCE"] = "NO_SOURCE";
17
+ })(ProductEnrichmentFieldStateEnum || (exports.ProductEnrichmentFieldStateEnum = ProductEnrichmentFieldStateEnum = {}));
@@ -0,0 +1,14 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.PRODUCT_ENRICHMENT_FIELD_LIST = exports.ProductEnrichmentFieldEnum = void 0;
4
+ // Поля товара, которые можно дополнить из привязанной карточки номенклатуры (ProductImage).
5
+ // Значения совпадают с именами полей Product и ProductImage — это ключи, по которым фронт
6
+ // собирает решения, поэтому переименование значения ломает контракт.
7
+ var ProductEnrichmentFieldEnum;
8
+ (function (ProductEnrichmentFieldEnum) {
9
+ ProductEnrichmentFieldEnum["COLOR"] = "color";
10
+ ProductEnrichmentFieldEnum["COUNTRY"] = "country";
11
+ ProductEnrichmentFieldEnum["GROWER"] = "grower";
12
+ })(ProductEnrichmentFieldEnum || (exports.ProductEnrichmentFieldEnum = ProductEnrichmentFieldEnum = {}));
13
+ const PRODUCT_ENRICHMENT_FIELD_KEYS = Object.keys(ProductEnrichmentFieldEnum);
14
+ exports.PRODUCT_ENRICHMENT_FIELD_LIST = PRODUCT_ENRICHMENT_FIELD_KEYS.map(key => ProductEnrichmentFieldEnum[key]);
@@ -0,0 +1,78 @@
1
+ import { z } from 'zod';
2
+ import { queryBooleanSchema } from '../../helpers/query-boolean.helper';
3
+ import { CONSIGNMENT_PRODUCT_ENRICHMENT_LIMITS } from '../../constant/consignment-product-enrichment.constant';
4
+ import { ProductEnrichmentFieldEnum } from '../../enum/product-enrichment-field.enum';
5
+ import { ProductEnrichmentFieldStateEnum } from '../../enum/product-enrichment-field-state.enum';
6
+
7
+ const AnalyzeConsignmentProductEnrichmentRequestSchema = z.object({
8
+ page: z.coerce.number().int().min(1).default(1),
9
+ count: z.coerce
10
+ .number()
11
+ .int()
12
+ .min(1)
13
+ .max(CONSIGNMENT_PRODUCT_ENRICHMENT_LIMITS.MAX_PAGE_SIZE)
14
+ .default(CONSIGNMENT_PRODUCT_ENRICHMENT_LIMITS.DEFAULT_PAGE_SIZE),
15
+ // Показывать только товары, у которых есть хотя бы одно поле к заполнению или конфликт.
16
+ // По умолчанию false: пользователь видит всю поставку и понимает, почему строк меньше, чем товаров.
17
+ // Не `z.coerce.boolean()`: в query приходит текст, а `Boolean('false') === true` — флаг нельзя
18
+ // было бы выключить явным значением.
19
+ isOnlyChanged: queryBooleanSchema,
20
+ });
21
+
22
+ const ProductEnrichmentFieldSchema = z.object({
23
+ current: z.string().nullable(),
24
+ proposed: z.string().nullable(),
25
+ state: z.nativeEnum(ProductEnrichmentFieldStateEnum),
26
+ });
27
+
28
+ const ProductEnrichmentItemSchema = z.object({
29
+ productUUID: z.string(),
30
+ productName: z.string(),
31
+ article: z.string().nullable(),
32
+ size: z.string().nullable(),
33
+ categoryName: z.string().nullable(),
34
+ imageUUID: z.string(),
35
+ imageName: z.string(),
36
+ imageUrl: z.string(),
37
+ fields: z.record(z.nativeEnum(ProductEnrichmentFieldEnum), ProductEnrichmentFieldSchema),
38
+ });
39
+
40
+ const ProductEnrichmentFieldStatsSchema = z.object({
41
+ fillable: z.number(),
42
+ conflicts: z.number(),
43
+ });
44
+
45
+ const ProductEnrichmentSummarySchema = z.object({
46
+ // Всего товаров в поставке.
47
+ totalProducts: z.number(),
48
+ // Из них с привязанной карточкой — только они попадают в таблицу.
49
+ linkedProducts: z.number(),
50
+ // Товаров, у которых есть хотя бы одно поле к заполнению.
51
+ fillableProducts: z.number(),
52
+ // Товаров, у которых есть хотя бы один конфликт.
53
+ conflictProducts: z.number(),
54
+ byField: z.record(z.nativeEnum(ProductEnrichmentFieldEnum), ProductEnrichmentFieldStatsSchema),
55
+ });
56
+
57
+ const AnalyzeConsignmentProductEnrichmentResponseSchema = z.object({
58
+ data: z.object({
59
+ items: z.array(ProductEnrichmentItemSchema),
60
+ total: z.number(),
61
+ page: z.number(),
62
+ count: z.number(),
63
+ // Считается по всей поставке, а не по текущей странице: иначе счётчики прыгали бы при листании.
64
+ summary: ProductEnrichmentSummarySchema,
65
+ }),
66
+ });
67
+
68
+ export namespace AnalyzeConsignmentProductEnrichmentContractQuery {
69
+ export const RequestSchema = AnalyzeConsignmentProductEnrichmentRequestSchema;
70
+ export type Request = z.infer<typeof RequestSchema>;
71
+
72
+ export const ResponseSchema = AnalyzeConsignmentProductEnrichmentResponseSchema;
73
+ export type Response = z.infer<typeof ResponseSchema>;
74
+
75
+ export type Item = z.infer<typeof ProductEnrichmentItemSchema>;
76
+ export type FieldDiff = z.infer<typeof ProductEnrichmentFieldSchema>;
77
+ export type Summary = z.infer<typeof ProductEnrichmentSummarySchema>;
78
+ }
@@ -0,0 +1,47 @@
1
+ import { z } from 'zod';
2
+ import { ErrorMessageSchema } from '../../schemas/error-message.schema';
3
+ import { CONSIGNMENT_PRODUCT_ENRICHMENT_LIMITS } from '../../constant/consignment-product-enrichment.constant';
4
+ import { ProductEnrichmentFieldEnum } from '../../enum/product-enrichment-field.enum';
5
+
6
+ const ExecuteConsignmentProductEnrichmentItemSchema = z.object({
7
+ productUUID: z.string().uuid(),
8
+ // Какие поля переносим из карточки в этот товар. Пустой список — товар пропускается.
9
+ fields: z.array(z.nativeEnum(ProductEnrichmentFieldEnum)).min(1),
10
+ });
11
+
12
+ const ExecuteConsignmentProductEnrichmentRequestSchema = z.object({
13
+ // Фронт шлёт пачками по EXECUTE_BATCH_SIZE и сам собирает итог: одна поставка может
14
+ // содержать до 1200 товаров, и одним запросом это отправлять не нужно.
15
+ // Повторы `productUUID` допустимы и схлопываются на сервере в объединение полей: товар
16
+ // обновляется и логируется один раз, сколько бы записей о нём ни пришло.
17
+ items: z.array(ExecuteConsignmentProductEnrichmentItemSchema).min(1).max(CONSIGNMENT_PRODUCT_ENRICHMENT_LIMITS.EXECUTE_BATCH_SIZE),
18
+ });
19
+
20
+ const ExecuteConsignmentProductEnrichmentResponseSchema = z.object({
21
+ data: z.object({
22
+ success: z.boolean(),
23
+ // Товаров, у которых изменилось хотя бы одно поле.
24
+ successCount: z.number(),
25
+ // Товаров, где менять было нечего: значение уже совпадало или карточка опустела с момента разбора.
26
+ skippedCount: z.number(),
27
+ // Товаров, которые кто-то изменил между разбором и применением. Отдельно от skipped, потому
28
+ // что это единственный исход, требующий действия: пользователю нужно перечитать разбор.
29
+ conflictedCount: z.number(),
30
+ failedCount: z.number(),
31
+ errors: z.array(
32
+ ErrorMessageSchema.extend({
33
+ uuid: z.string(),
34
+ }),
35
+ ),
36
+ }),
37
+ });
38
+
39
+ export namespace ExecuteConsignmentProductEnrichmentContractCommand {
40
+ export const RequestSchema = ExecuteConsignmentProductEnrichmentRequestSchema;
41
+ export type Request = z.infer<typeof RequestSchema>;
42
+
43
+ export const ResponseSchema = ExecuteConsignmentProductEnrichmentResponseSchema;
44
+ export type Response = z.infer<typeof ResponseSchema>;
45
+
46
+ export type Item = z.infer<typeof ExecuteConsignmentProductEnrichmentItemSchema>;
47
+ }
@@ -13,3 +13,5 @@ export * from './get-access-clients-consignment.query';
13
13
  export * from './get-consignment-filters-values.query';
14
14
  export * from './execute-consignment-product-update.command';
15
15
  export * from './determine-consignment-product-images.command';
16
+ export * from './analyze-consignment-product-enrichment.query';
17
+ export * from './execute-consignment-product-enrichment.command';
@@ -0,0 +1,9 @@
1
+ // Лимиты операции «получить характеристики из номенклатуры».
2
+ // Анализ читает всю поставку целиком (потолок задан лимитами импорта: MAX_ROWS_WITHOUT_IMAGES = 1200),
3
+ // но наружу отдаёт страницами, а применение принимает пачками — чтобы ни ответ, ни запрос не росли
4
+ // вместе с размером поставки.
5
+ export const CONSIGNMENT_PRODUCT_ENRICHMENT_LIMITS = {
6
+ DEFAULT_PAGE_SIZE: 50,
7
+ MAX_PAGE_SIZE: 200,
8
+ EXECUTE_BATCH_SIZE: 100,
9
+ } as const;
package/constant/index.ts CHANGED
@@ -9,3 +9,4 @@ export * from './oksm';
9
9
  export * from './okei';
10
10
  export * from './contact-phone.constant';
11
11
  export * from './settings.constant';
12
+ export * from './consignment-product-enrichment.constant';
package/enum/index.ts CHANGED
@@ -106,3 +106,5 @@ export * from './transfer-document-state.enum';
106
106
  export * from './transfer-document-kind.enum';
107
107
  export * from './transfer-document-item-kind.enum';
108
108
  export * from './write-off-report-date-basis.enum';
109
+ export * from './product-enrichment-field.enum';
110
+ export * from './product-enrichment-field-state.enum';
@@ -0,0 +1,13 @@
1
+ // Состояние одного поля товара относительно привязанной карточки номенклатуры.
2
+ // Определяет и подсказку в интерфейсе («собственные данные» / «из номенклатуры»), и то,
3
+ // отмечен ли чекбокс по умолчанию: предзаполняется только FILLABLE.
4
+ export enum ProductEnrichmentFieldStateEnum {
5
+ // У товара пусто, в карточке значение есть — это и есть «дополнить».
6
+ FILLABLE = 'FILLABLE',
7
+ // Оба заполнены и различаются. Показываем, но по умолчанию не отмечаем.
8
+ CONFLICT = 'CONFLICT',
9
+ // Значения совпадают — брать нечего.
10
+ SAME = 'SAME',
11
+ // В карточке пусто — источника нет.
12
+ NO_SOURCE = 'NO_SOURCE',
13
+ }
@@ -0,0 +1,14 @@
1
+ // Поля товара, которые можно дополнить из привязанной карточки номенклатуры (ProductImage).
2
+ // Значения совпадают с именами полей Product и ProductImage — это ключи, по которым фронт
3
+ // собирает решения, поэтому переименование значения ломает контракт.
4
+ export enum ProductEnrichmentFieldEnum {
5
+ COLOR = 'color',
6
+ COUNTRY = 'country',
7
+ GROWER = 'grower',
8
+ }
9
+
10
+ const PRODUCT_ENRICHMENT_FIELD_KEYS = Object.keys(ProductEnrichmentFieldEnum) as Array<keyof typeof ProductEnrichmentFieldEnum>;
11
+
12
+ export const PRODUCT_ENRICHMENT_FIELD_LIST: readonly ProductEnrichmentFieldEnum[] = PRODUCT_ENRICHMENT_FIELD_KEYS.map(
13
+ key => ProductEnrichmentFieldEnum[key],
14
+ );
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@floristcloud/api-lib",
3
- "version": "1.2.132",
3
+ "version": "1.2.133",
4
4
  "description": "",
5
5
  "main": "./build/index.js",
6
6
  "scripts": {