@floristcloud/api-lib 1.2.128 → 1.2.130
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/build/commands/discount-rules/get-discount-rules-all.query.js +2 -0
- package/build/commands/discount-rules/get-product-discount-price.query.js +56 -0
- package/build/commands/discount-rules/index.js +1 -0
- package/build/enum/discount-rules-mode-type.enum.js +9 -0
- package/build/enum/discount-rules-type.enum.js +1 -0
- package/build/schemas/discount-rules/discount-rules.schema.js +43 -6
- package/build/schemas/product/product.schema.js +1 -1
- package/commands/discount-rules/get-discount-rules-all.query.ts +2 -0
- package/commands/discount-rules/get-product-discount-price.query.ts +59 -0
- package/commands/discount-rules/index.ts +1 -0
- package/enum/discount-rules-mode-type.enum.ts +9 -0
- package/enum/discount-rules-type.enum.ts +1 -0
- package/package.json +1 -1
- package/schemas/discount-rules/discount-rules.schema.ts +46 -5
- package/schemas/product/product.schema.ts +2 -2
|
@@ -9,6 +9,8 @@ const GetDiscountRulesAllRequestSchema = zod_1.z.object({
|
|
|
9
9
|
return val === 'null' ? null : val;
|
|
10
10
|
}, zod_1.z.uuid().nullable().optional()),
|
|
11
11
|
});
|
|
12
|
+
// Только конфигурация правил: экраны настройки правят её, а цену по товару отдаёт
|
|
13
|
+
// `GetProductDiscountPriceContractQuery` — это разные вопросы и разные ответы.
|
|
12
14
|
const GetDiscountRulesAllResponseSchema = zod_1.z.object({
|
|
13
15
|
message: zod_1.z.string().optional(),
|
|
14
16
|
data: schemas_1.DiscountRulesSchema.array(),
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.GetProductDiscountPriceContractQuery = void 0;
|
|
4
|
+
const zod_1 = require("zod");
|
|
5
|
+
const enum_1 = require("../../enum");
|
|
6
|
+
const schemas_1 = require("../../schemas");
|
|
7
|
+
const money_schema_1 = require("../../schemas/money.schema");
|
|
8
|
+
const GetProductDiscountPriceRequestSchema = zod_1.z.object({
|
|
9
|
+
productUUID: zod_1.z.uuid(),
|
|
10
|
+
clientUUID: zod_1.z.preprocess(val => {
|
|
11
|
+
return val === 'null' ? null : val;
|
|
12
|
+
}, zod_1.z.uuid().nullable().optional()),
|
|
13
|
+
});
|
|
14
|
+
/**
|
|
15
|
+
* Цена товара по одному правилу — для показа вариантов.
|
|
16
|
+
*
|
|
17
|
+
* `discountValueData` описывает, чем правило обернулось для этого товара, а не как оно настроено:
|
|
18
|
+
* у правила от себестоимости это готовая цена, и самой наценки здесь нет.
|
|
19
|
+
|
|
20
|
+
*/
|
|
21
|
+
const ProductDiscountPriceItemSchema = zod_1.z.object({
|
|
22
|
+
discountRulesUUID: zod_1.z.string(),
|
|
23
|
+
type: zod_1.z.nativeEnum(enum_1.DiscountRulesTypeEnum),
|
|
24
|
+
discountValueData: schemas_1.discountPriceOutcomeSchema,
|
|
25
|
+
priceWithDiscount: money_schema_1.MoneySchema,
|
|
26
|
+
});
|
|
27
|
+
/**
|
|
28
|
+
* Готовые цены товара для клиента: то, что нужно при работе с товаром, а не при настройке правил.
|
|
29
|
+
*
|
|
30
|
+
* Считает бэк тем же движком, что и для витрины, — панель формулу скидок не повторяет и
|
|
31
|
+
* себестоимость не получает. Настройка правил живёт отдельно, в `GetDiscountRulesAllContractQuery`.
|
|
32
|
+
*
|
|
33
|
+
* `null` в ценах со скидкой означает «скидка неприменима», а не «ноль».
|
|
34
|
+
*/
|
|
35
|
+
const GetProductDiscountPriceResponseSchema = zod_1.z.object({
|
|
36
|
+
message: zod_1.z.string().optional(),
|
|
37
|
+
data: zod_1.z.object({
|
|
38
|
+
productUUID: zod_1.z.string(),
|
|
39
|
+
price: money_schema_1.MoneySchema,
|
|
40
|
+
priceWithBestDiscount: money_schema_1.MoneySchema.nullable(),
|
|
41
|
+
multiplicityOptions: zod_1.z
|
|
42
|
+
.object({
|
|
43
|
+
uuid: zod_1.z.string(),
|
|
44
|
+
optionPrice: money_schema_1.MoneySchema.nullable(),
|
|
45
|
+
optionPriceWithDiscount: money_schema_1.MoneySchema.nullable(),
|
|
46
|
+
isDiscountApplicable: zod_1.z.boolean(),
|
|
47
|
+
})
|
|
48
|
+
.array(),
|
|
49
|
+
discountDataList: ProductDiscountPriceItemSchema.array(),
|
|
50
|
+
}),
|
|
51
|
+
});
|
|
52
|
+
var GetProductDiscountPriceContractQuery;
|
|
53
|
+
(function (GetProductDiscountPriceContractQuery) {
|
|
54
|
+
GetProductDiscountPriceContractQuery.RequestSchema = GetProductDiscountPriceRequestSchema;
|
|
55
|
+
GetProductDiscountPriceContractQuery.ResponseSchema = GetProductDiscountPriceResponseSchema;
|
|
56
|
+
})(GetProductDiscountPriceContractQuery || (exports.GetProductDiscountPriceContractQuery = GetProductDiscountPriceContractQuery = {}));
|
|
@@ -23,6 +23,7 @@ __exportStar(require("./get-discount-rules-extended.query"), exports);
|
|
|
23
23
|
__exportStar(require("./split-quantity-discount-rules.query"), exports);
|
|
24
24
|
__exportStar(require("./split-quantity-discount-rules-for-client.query"), exports);
|
|
25
25
|
__exportStar(require("./get-discount-rules-all.query"), exports);
|
|
26
|
+
__exportStar(require("./get-product-discount-price.query"), exports);
|
|
26
27
|
__exportStar(require("./set-consignment-discount.command"), exports);
|
|
27
28
|
__exportStar(require("./delete-consignment-discount.command"), exports);
|
|
28
29
|
__exportStar(require("./remove-consignment-discount.command"), exports);
|
|
@@ -5,4 +5,13 @@ var DiscountRulesModeTypeEnum;
|
|
|
5
5
|
(function (DiscountRulesModeTypeEnum) {
|
|
6
6
|
DiscountRulesModeTypeEnum["FIXED"] = "FIXED";
|
|
7
7
|
DiscountRulesModeTypeEnum["PERCENT"] = "PERCENT";
|
|
8
|
+
/**
|
|
9
|
+
* Готовая цена, а не величина скидки.
|
|
10
|
+
*
|
|
11
|
+
* Значение вычисляемое: его выставляет правило `COST_PLUS_MARKUP`, посчитав цену от
|
|
12
|
+
* себестоимости товара. Задать его снаружи нельзя — схема ввода правила
|
|
13
|
+
* (`discountRulesModeSchema`) знает только FIXED и PERCENT, а схема выдачи
|
|
14
|
+
* (`discountPriceOutcomeSchema`) — все три.
|
|
15
|
+
*/
|
|
16
|
+
DiscountRulesModeTypeEnum["TARGET_PRICE"] = "TARGET_PRICE";
|
|
8
17
|
})(DiscountRulesModeTypeEnum || (exports.DiscountRulesModeTypeEnum = DiscountRulesModeTypeEnum = {}));
|
|
@@ -8,4 +8,5 @@ var DiscountRulesTypeEnum;
|
|
|
8
8
|
DiscountRulesTypeEnum["QUANTITY_BASED"] = "QUANTITY_BASED";
|
|
9
9
|
DiscountRulesTypeEnum["ITEM_DISCOUNT"] = "ITEM_DISCOUNT";
|
|
10
10
|
DiscountRulesTypeEnum["DISCOUNT_PROHIBITED"] = "DISCOUNT_PROHIBITED";
|
|
11
|
+
DiscountRulesTypeEnum["COST_PLUS_MARKUP"] = "COST_PLUS_MARKUP";
|
|
11
12
|
})(DiscountRulesTypeEnum || (exports.DiscountRulesTypeEnum = DiscountRulesTypeEnum = {}));
|
|
@@ -1,19 +1,39 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.DiscountRulesExtendedSchema = exports.DiscountRulesSplitQuantityForClientSchema = exports.DiscountRulesSplitQuantityResponseSchema = exports.DiscountRulesSplitQuantitySchema = exports.DiscountRulesBaseExtendedSchema = exports.DiscountRulesListSchema = exports.UpdateDiscountRulesSchema = exports.CreateDiscountRulesSchema = exports.DiscountRulesSchema = exports.DiscountRulesBaseSchema = exports.DiscountRulesTypeSchema = exports.discountRulesModeSchema = void 0;
|
|
3
|
+
exports.DiscountRulesExtendedSchema = exports.DiscountRulesSplitQuantityForClientSchema = exports.DiscountRulesSplitQuantityResponseSchema = exports.DiscountRulesSplitQuantitySchema = exports.DiscountRulesBaseExtendedSchema = exports.DiscountRulesListSchema = exports.UpdateDiscountRulesSchema = exports.CreateDiscountRulesSchema = exports.DiscountRulesSchema = exports.DiscountRulesBaseSchema = exports.DiscountRulesTypeSchema = exports.discountPriceOutcomeSchema = exports.discountRulesModeSchema = void 0;
|
|
4
4
|
const zod_1 = require("zod");
|
|
5
5
|
const enum_1 = require("../../enum");
|
|
6
6
|
const client_1 = require("../client");
|
|
7
7
|
const product_schema_1 = require("../product/product.schema");
|
|
8
8
|
const money_schema_1 = require("../money.schema");
|
|
9
|
+
const non_negative_money_schema_1 = require("../non-negative-money.schema");
|
|
9
10
|
const positive_money_schema_1 = require("../positive-money.schema");
|
|
10
11
|
// PERCENT — это процент, а не деньги: остаётся числом 0..100. FIXED — денежная величина, едет строкой.
|
|
11
|
-
|
|
12
|
-
|
|
12
|
+
const discountPercentModeSchema = zod_1.z.object({
|
|
13
|
+
typeDiscount: zod_1.z.literal(enum_1.DiscountRulesModeTypeEnum.PERCENT),
|
|
14
|
+
discountValue: zod_1.z.number().min(0).max(100),
|
|
15
|
+
});
|
|
16
|
+
const discountFixedModeSchema = zod_1.z.object({
|
|
17
|
+
typeDiscount: zod_1.z.literal(enum_1.DiscountRulesModeTypeEnum.FIXED),
|
|
18
|
+
// Строго положительная сумма: минус отсекаем по знаку строки, нули вида "0" / "0.00" — сравнением.
|
|
19
|
+
discountValue: positive_money_schema_1.PositiveMoneySchema,
|
|
20
|
+
});
|
|
21
|
+
exports.discountRulesModeSchema = zod_1.z.discriminatedUnion('typeDiscount', [discountPercentModeSchema, discountFixedModeSchema]);
|
|
22
|
+
/**
|
|
23
|
+
* Итог применения правила к товару — то, что уезжает клиенту в `discountDataList`.
|
|
24
|
+
*
|
|
25
|
+
* От схемы ввода отличается ровно одной веткой: TARGET_PRICE несёт уже посчитанную цену, а не
|
|
26
|
+
* величину скидки. Так работает правило от себестоимости: считать цену на клиенте нечем — там нет
|
|
27
|
+
* ни себестоимости, ни права её видеть. Ветка живёт только в выдаче: задать TARGET_PRICE при
|
|
28
|
+
* создании правила нельзя, `discountRulesModeSchema` его не принимает.
|
|
29
|
+
*/
|
|
30
|
+
exports.discountPriceOutcomeSchema = zod_1.z.discriminatedUnion('typeDiscount', [
|
|
31
|
+
discountPercentModeSchema,
|
|
32
|
+
discountFixedModeSchema,
|
|
13
33
|
zod_1.z.object({
|
|
14
|
-
typeDiscount: zod_1.z.literal(enum_1.DiscountRulesModeTypeEnum.
|
|
15
|
-
//
|
|
16
|
-
|
|
34
|
+
typeDiscount: zod_1.z.literal(enum_1.DiscountRulesModeTypeEnum.TARGET_PRICE),
|
|
35
|
+
// Ноль допустим: себестоимость может быть нулевой, а наценка — нулевой по условию правила.
|
|
36
|
+
targetPrice: non_negative_money_schema_1.NonNegativeMoneySchema,
|
|
17
37
|
}),
|
|
18
38
|
]);
|
|
19
39
|
// Rules schemas other data
|
|
@@ -40,6 +60,19 @@ const DiscountRulesQuantityBasedDataSchema = zod_1.z
|
|
|
40
60
|
.and(exports.discountRulesModeSchema);
|
|
41
61
|
const DiscountRulesItemDiscountDataSchema = exports.discountRulesModeSchema;
|
|
42
62
|
const DiscountRulesDiscountProhibitedDataSchema = zod_1.z.object({}).default({});
|
|
63
|
+
/**
|
|
64
|
+
* Наценка к себестоимости: цена клиента = себестоимость + наценка.
|
|
65
|
+
*
|
|
66
|
+
* Три отличия от режима скидки, и все намеренные:
|
|
67
|
+
* — только вверх, знака у величины нет: продажу ниже себестоимости правилом не задают;
|
|
68
|
+
* — ноль допустим (`markupValue: 0` — продаём по себестоимости), поэтому FIXED берёт
|
|
69
|
+
* `NonNegativeMoneySchema`, а не `PositiveMoneySchema`;
|
|
70
|
+
* — у процента нет верхней границы: наценка в 150 % законна, в отличие от скидки в 150 %.
|
|
71
|
+
*/
|
|
72
|
+
const DiscountRulesCostPlusMarkupDataSchema = zod_1.z.discriminatedUnion('typeMarkup', [
|
|
73
|
+
zod_1.z.object({ typeMarkup: zod_1.z.literal(enum_1.DiscountRulesModeTypeEnum.PERCENT), markupValue: zod_1.z.number().min(0) }),
|
|
74
|
+
zod_1.z.object({ typeMarkup: zod_1.z.literal(enum_1.DiscountRulesModeTypeEnum.FIXED), markupValue: non_negative_money_schema_1.NonNegativeMoneySchema }),
|
|
75
|
+
]);
|
|
43
76
|
exports.DiscountRulesTypeSchema = zod_1.z.discriminatedUnion('type', [
|
|
44
77
|
zod_1.z.object({
|
|
45
78
|
type: zod_1.z.literal(enum_1.DiscountRulesTypeEnum.PERSONAL_DISCOUNT),
|
|
@@ -61,6 +94,10 @@ exports.DiscountRulesTypeSchema = zod_1.z.discriminatedUnion('type', [
|
|
|
61
94
|
type: zod_1.z.literal(enum_1.DiscountRulesTypeEnum.DISCOUNT_PROHIBITED),
|
|
62
95
|
data: DiscountRulesDiscountProhibitedDataSchema,
|
|
63
96
|
}),
|
|
97
|
+
zod_1.z.object({
|
|
98
|
+
type: zod_1.z.literal(enum_1.DiscountRulesTypeEnum.COST_PLUS_MARKUP),
|
|
99
|
+
data: DiscountRulesCostPlusMarkupDataSchema,
|
|
100
|
+
}),
|
|
64
101
|
]);
|
|
65
102
|
exports.DiscountRulesBaseSchema = zod_1.z.object({
|
|
66
103
|
uuid: zod_1.z.string(),
|
|
@@ -95,7 +95,7 @@ exports.ProductExtendedForClientSchema = exports.ProductForClientSchema.merge(zo
|
|
|
95
95
|
.object({
|
|
96
96
|
discountRulesUUID: zod_1.z.string(),
|
|
97
97
|
type: zod_1.z.nativeEnum(enum_1.DiscountRulesTypeEnum),
|
|
98
|
-
discountValueData: discount_rules_schema_1.
|
|
98
|
+
discountValueData: discount_rules_schema_1.discountPriceOutcomeSchema,
|
|
99
99
|
priceWithDiscount: money_schema_1.MoneySchema,
|
|
100
100
|
multipleQuantity: zod_1.z.number().optional(),
|
|
101
101
|
})
|
|
@@ -8,6 +8,8 @@ const GetDiscountRulesAllRequestSchema = z.object({
|
|
|
8
8
|
}, z.uuid().nullable().optional()),
|
|
9
9
|
});
|
|
10
10
|
|
|
11
|
+
// Только конфигурация правил: экраны настройки правят её, а цену по товару отдаёт
|
|
12
|
+
// `GetProductDiscountPriceContractQuery` — это разные вопросы и разные ответы.
|
|
11
13
|
const GetDiscountRulesAllResponseSchema = z.object({
|
|
12
14
|
message: z.string().optional(),
|
|
13
15
|
data: DiscountRulesSchema.array(),
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { DiscountRulesTypeEnum } from '../../enum';
|
|
3
|
+
import { discountPriceOutcomeSchema } from '../../schemas';
|
|
4
|
+
import { MoneySchema } from '../../schemas/money.schema';
|
|
5
|
+
|
|
6
|
+
const GetProductDiscountPriceRequestSchema = z.object({
|
|
7
|
+
productUUID: z.uuid(),
|
|
8
|
+
clientUUID: z.preprocess(val => {
|
|
9
|
+
return val === 'null' ? null : val;
|
|
10
|
+
}, z.uuid().nullable().optional()),
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Цена товара по одному правилу — для показа вариантов.
|
|
15
|
+
*
|
|
16
|
+
* `discountValueData` описывает, чем правило обернулось для этого товара, а не как оно настроено:
|
|
17
|
+
* у правила от себестоимости это готовая цена, и самой наценки здесь нет.
|
|
18
|
+
|
|
19
|
+
*/
|
|
20
|
+
const ProductDiscountPriceItemSchema = z.object({
|
|
21
|
+
discountRulesUUID: z.string(),
|
|
22
|
+
type: z.nativeEnum(DiscountRulesTypeEnum),
|
|
23
|
+
discountValueData: discountPriceOutcomeSchema,
|
|
24
|
+
priceWithDiscount: MoneySchema,
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Готовые цены товара для клиента: то, что нужно при работе с товаром, а не при настройке правил.
|
|
29
|
+
*
|
|
30
|
+
* Считает бэк тем же движком, что и для витрины, — панель формулу скидок не повторяет и
|
|
31
|
+
* себестоимость не получает. Настройка правил живёт отдельно, в `GetDiscountRulesAllContractQuery`.
|
|
32
|
+
*
|
|
33
|
+
* `null` в ценах со скидкой означает «скидка неприменима», а не «ноль».
|
|
34
|
+
*/
|
|
35
|
+
const GetProductDiscountPriceResponseSchema = z.object({
|
|
36
|
+
message: z.string().optional(),
|
|
37
|
+
data: z.object({
|
|
38
|
+
productUUID: z.string(),
|
|
39
|
+
price: MoneySchema,
|
|
40
|
+
priceWithBestDiscount: MoneySchema.nullable(),
|
|
41
|
+
multiplicityOptions: z
|
|
42
|
+
.object({
|
|
43
|
+
uuid: z.string(),
|
|
44
|
+
optionPrice: MoneySchema.nullable(),
|
|
45
|
+
optionPriceWithDiscount: MoneySchema.nullable(),
|
|
46
|
+
isDiscountApplicable: z.boolean(),
|
|
47
|
+
})
|
|
48
|
+
.array(),
|
|
49
|
+
discountDataList: ProductDiscountPriceItemSchema.array(),
|
|
50
|
+
}),
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
export namespace GetProductDiscountPriceContractQuery {
|
|
54
|
+
export const RequestSchema = GetProductDiscountPriceRequestSchema;
|
|
55
|
+
export type Request = z.infer<typeof RequestSchema>;
|
|
56
|
+
|
|
57
|
+
export const ResponseSchema = GetProductDiscountPriceResponseSchema;
|
|
58
|
+
export type Response = z.infer<typeof ResponseSchema>;
|
|
59
|
+
}
|
|
@@ -7,6 +7,7 @@ export * from './get-discount-rules-extended.query';
|
|
|
7
7
|
export * from './split-quantity-discount-rules.query';
|
|
8
8
|
export * from './split-quantity-discount-rules-for-client.query';
|
|
9
9
|
export * from './get-discount-rules-all.query';
|
|
10
|
+
export * from './get-product-discount-price.query';
|
|
10
11
|
export * from './set-consignment-discount.command';
|
|
11
12
|
export * from './delete-consignment-discount.command';
|
|
12
13
|
export * from './remove-consignment-discount.command';
|
|
@@ -1,4 +1,13 @@
|
|
|
1
1
|
export enum DiscountRulesModeTypeEnum {
|
|
2
2
|
FIXED = 'FIXED',
|
|
3
3
|
PERCENT = 'PERCENT',
|
|
4
|
+
/**
|
|
5
|
+
* Готовая цена, а не величина скидки.
|
|
6
|
+
*
|
|
7
|
+
* Значение вычисляемое: его выставляет правило `COST_PLUS_MARKUP`, посчитав цену от
|
|
8
|
+
* себестоимости товара. Задать его снаружи нельзя — схема ввода правила
|
|
9
|
+
* (`discountRulesModeSchema`) знает только FIXED и PERCENT, а схема выдачи
|
|
10
|
+
* (`discountPriceOutcomeSchema`) — все три.
|
|
11
|
+
*/
|
|
12
|
+
TARGET_PRICE = 'TARGET_PRICE',
|
|
4
13
|
}
|
package/package.json
CHANGED
|
@@ -3,15 +3,38 @@ import { DiscountRulesTypeEnum, DiscountRulesApplyTypeEnum, DiscountRulesStatusE
|
|
|
3
3
|
import { ClientSchema } from '../client';
|
|
4
4
|
import { ProductSchema } from '../product/product.schema';
|
|
5
5
|
import { MoneySchema } from '../money.schema';
|
|
6
|
+
import { NonNegativeMoneySchema } from '../non-negative-money.schema';
|
|
6
7
|
import { PositiveMoneySchema } from '../positive-money.schema';
|
|
7
8
|
|
|
8
9
|
// PERCENT — это процент, а не деньги: остаётся числом 0..100. FIXED — денежная величина, едет строкой.
|
|
9
|
-
|
|
10
|
-
|
|
10
|
+
const discountPercentModeSchema = z.object({
|
|
11
|
+
typeDiscount: z.literal(DiscountRulesModeTypeEnum.PERCENT),
|
|
12
|
+
discountValue: z.number().min(0).max(100),
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
const discountFixedModeSchema = z.object({
|
|
16
|
+
typeDiscount: z.literal(DiscountRulesModeTypeEnum.FIXED),
|
|
17
|
+
// Строго положительная сумма: минус отсекаем по знаку строки, нули вида "0" / "0.00" — сравнением.
|
|
18
|
+
discountValue: PositiveMoneySchema,
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
export const discountRulesModeSchema = z.discriminatedUnion('typeDiscount', [discountPercentModeSchema, discountFixedModeSchema]);
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Итог применения правила к товару — то, что уезжает клиенту в `discountDataList`.
|
|
25
|
+
*
|
|
26
|
+
* От схемы ввода отличается ровно одной веткой: TARGET_PRICE несёт уже посчитанную цену, а не
|
|
27
|
+
* величину скидки. Так работает правило от себестоимости: считать цену на клиенте нечем — там нет
|
|
28
|
+
* ни себестоимости, ни права её видеть. Ветка живёт только в выдаче: задать TARGET_PRICE при
|
|
29
|
+
* создании правила нельзя, `discountRulesModeSchema` его не принимает.
|
|
30
|
+
*/
|
|
31
|
+
export const discountPriceOutcomeSchema = z.discriminatedUnion('typeDiscount', [
|
|
32
|
+
discountPercentModeSchema,
|
|
33
|
+
discountFixedModeSchema,
|
|
11
34
|
z.object({
|
|
12
|
-
typeDiscount: z.literal(DiscountRulesModeTypeEnum.
|
|
13
|
-
//
|
|
14
|
-
|
|
35
|
+
typeDiscount: z.literal(DiscountRulesModeTypeEnum.TARGET_PRICE),
|
|
36
|
+
// Ноль допустим: себестоимость может быть нулевой, а наценка — нулевой по условию правила.
|
|
37
|
+
targetPrice: NonNegativeMoneySchema,
|
|
15
38
|
}),
|
|
16
39
|
]);
|
|
17
40
|
|
|
@@ -44,6 +67,20 @@ const DiscountRulesItemDiscountDataSchema = discountRulesModeSchema;
|
|
|
44
67
|
|
|
45
68
|
const DiscountRulesDiscountProhibitedDataSchema = z.object({}).default({});
|
|
46
69
|
|
|
70
|
+
/**
|
|
71
|
+
* Наценка к себестоимости: цена клиента = себестоимость + наценка.
|
|
72
|
+
*
|
|
73
|
+
* Три отличия от режима скидки, и все намеренные:
|
|
74
|
+
* — только вверх, знака у величины нет: продажу ниже себестоимости правилом не задают;
|
|
75
|
+
* — ноль допустим (`markupValue: 0` — продаём по себестоимости), поэтому FIXED берёт
|
|
76
|
+
* `NonNegativeMoneySchema`, а не `PositiveMoneySchema`;
|
|
77
|
+
* — у процента нет верхней границы: наценка в 150 % законна, в отличие от скидки в 150 %.
|
|
78
|
+
*/
|
|
79
|
+
const DiscountRulesCostPlusMarkupDataSchema = z.discriminatedUnion('typeMarkup', [
|
|
80
|
+
z.object({ typeMarkup: z.literal(DiscountRulesModeTypeEnum.PERCENT), markupValue: z.number().min(0) }),
|
|
81
|
+
z.object({ typeMarkup: z.literal(DiscountRulesModeTypeEnum.FIXED), markupValue: NonNegativeMoneySchema }),
|
|
82
|
+
]);
|
|
83
|
+
|
|
47
84
|
export const DiscountRulesTypeSchema = z.discriminatedUnion('type', [
|
|
48
85
|
z.object({
|
|
49
86
|
type: z.literal(DiscountRulesTypeEnum.PERSONAL_DISCOUNT),
|
|
@@ -65,6 +102,10 @@ export const DiscountRulesTypeSchema = z.discriminatedUnion('type', [
|
|
|
65
102
|
type: z.literal(DiscountRulesTypeEnum.DISCOUNT_PROHIBITED),
|
|
66
103
|
data: DiscountRulesDiscountProhibitedDataSchema,
|
|
67
104
|
}),
|
|
105
|
+
z.object({
|
|
106
|
+
type: z.literal(DiscountRulesTypeEnum.COST_PLUS_MARKUP),
|
|
107
|
+
data: DiscountRulesCostPlusMarkupDataSchema,
|
|
108
|
+
}),
|
|
68
109
|
]);
|
|
69
110
|
|
|
70
111
|
export const DiscountRulesBaseSchema = z.object({
|
|
@@ -4,7 +4,7 @@ import { CategorySchema } from '../category/category.schema';
|
|
|
4
4
|
import { TypeSchema } from '../type/type.schema';
|
|
5
5
|
import { ConsignmentSchema } from '../consignment/consignment.schema';
|
|
6
6
|
import { DiscountRulesTypeEnum, ProductMarkEnum, SalesUnitEnum } from '../../enum';
|
|
7
|
-
import {
|
|
7
|
+
import { discountPriceOutcomeSchema } from '../discount-rules/discount-rules.schema';
|
|
8
8
|
import { ProductMultiplicityOptionSchema } from '../..';
|
|
9
9
|
import { ProductMultiplicityOptionForClientSchema } from './product-multiplicity-option-for-client.schema';
|
|
10
10
|
import { MoneySchema } from '../money.schema';
|
|
@@ -102,7 +102,7 @@ export const ProductExtendedForClientSchema = ProductForClientSchema.merge(
|
|
|
102
102
|
.object({
|
|
103
103
|
discountRulesUUID: z.string(),
|
|
104
104
|
type: z.nativeEnum(DiscountRulesTypeEnum),
|
|
105
|
-
discountValueData:
|
|
105
|
+
discountValueData: discountPriceOutcomeSchema,
|
|
106
106
|
priceWithDiscount: MoneySchema,
|
|
107
107
|
multipleQuantity: z.number().optional(),
|
|
108
108
|
})
|