@floristcloud/api-lib 1.2.108 → 1.2.109
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/report/export-sales-by-client.query.js +3 -0
- package/build/commands/report/export-sales-by-position.query.js +3 -0
- package/build/commands/report/export-sales-revenue.query.js +3 -0
- package/build/commands/report/get-report-group-by-client.query.js +4 -0
- package/build/commands/report/get-sales-by-client.query.js +3 -0
- package/build/commands/report/get-sales-summary.query.js +4 -0
- package/build/constant/index.js +1 -0
- package/build/constant/report.constant.js +9 -0
- package/build/enum/index.js +1 -0
- package/build/enum/report-order-date-basis.enum.js +18 -0
- package/build/schemas/index.js +1 -0
- package/build/schemas/report/report-order-filter.schema.js +28 -0
- package/commands/report/export-sales-by-client.query.ts +3 -0
- package/commands/report/export-sales-by-position.query.ts +3 -0
- package/commands/report/export-sales-revenue.query.ts +3 -0
- package/commands/report/get-report-group-by-client.query.ts +4 -0
- package/commands/report/get-sales-by-client.query.ts +3 -0
- package/commands/report/get-sales-summary.query.ts +4 -0
- package/constant/index.ts +1 -0
- package/constant/report.constant.ts +6 -0
- package/enum/index.ts +1 -0
- package/enum/report-order-date-basis.enum.ts +14 -0
- package/package.json +1 -1
- package/schemas/index.ts +1 -0
- package/schemas/report/report-order-filter.schema.ts +26 -0
|
@@ -3,11 +3,14 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.ExportSalesByClientContractQuery = void 0;
|
|
4
4
|
const zod_1 = require("zod");
|
|
5
5
|
const date_helper_1 = require("../../helpers/date.helper");
|
|
6
|
+
const report_order_filter_schema_1 = require("../../schemas/report/report-order-filter.schema");
|
|
6
7
|
const ExportSalesByClientRequestSchema = zod_1.z
|
|
7
8
|
.object({
|
|
8
9
|
startDate: zod_1.z.coerce.date(),
|
|
9
10
|
endDate: zod_1.z.coerce.date(),
|
|
10
11
|
})
|
|
12
|
+
// dateBasis / excludeClientUUID — те же, что у JSON-эндпоинтов отчётов по заказам.
|
|
13
|
+
.merge(report_order_filter_schema_1.ReportOrderFilterSchema)
|
|
11
14
|
.refine(value => (0, date_helper_1.dateRangeCheck)(value.startDate, value.endDate), {
|
|
12
15
|
message: 'validation.dateRange',
|
|
13
16
|
path: ['endDate', 'startDate'],
|
|
@@ -4,12 +4,15 @@ exports.ExportSalesByPositionContractQuery = void 0;
|
|
|
4
4
|
const zod_1 = require("zod");
|
|
5
5
|
const date_helper_1 = require("../../helpers/date.helper");
|
|
6
6
|
const sales_by_position_group_by_enum_1 = require("../../enum/sales-by-position-group-by.enum");
|
|
7
|
+
const report_order_filter_schema_1 = require("../../schemas/report/report-order-filter.schema");
|
|
7
8
|
const ExportSalesByPositionRequestSchema = zod_1.z
|
|
8
9
|
.object({
|
|
9
10
|
startDate: zod_1.z.coerce.date(),
|
|
10
11
|
endDate: zod_1.z.coerce.date(),
|
|
11
12
|
groupBy: zod_1.z.nativeEnum(sales_by_position_group_by_enum_1.SalesByPositionGroupByEnum).default(sales_by_position_group_by_enum_1.SalesByPositionGroupByEnum.PRODUCT),
|
|
12
13
|
})
|
|
14
|
+
// dateBasis / excludeClientUUID — те же, что у JSON-эндпоинтов отчётов по заказам.
|
|
15
|
+
.merge(report_order_filter_schema_1.ReportOrderFilterSchema)
|
|
13
16
|
.refine(value => (0, date_helper_1.dateRangeCheck)(value.startDate, value.endDate), {
|
|
14
17
|
message: 'validation.dateRange',
|
|
15
18
|
path: ['endDate', 'startDate'],
|
|
@@ -4,12 +4,15 @@ exports.ExportSalesRevenueContractQuery = void 0;
|
|
|
4
4
|
const zod_1 = require("zod");
|
|
5
5
|
const date_helper_1 = require("../../helpers/date.helper");
|
|
6
6
|
const report_period_type_enum_1 = require("../../enum/report-period-type.enum");
|
|
7
|
+
const report_order_filter_schema_1 = require("../../schemas/report/report-order-filter.schema");
|
|
7
8
|
const ExportSalesRevenueRequestSchema = zod_1.z
|
|
8
9
|
.object({
|
|
9
10
|
startDate: zod_1.z.coerce.date().optional(),
|
|
10
11
|
endDate: zod_1.z.coerce.date().optional(),
|
|
11
12
|
periodType: zod_1.z.nativeEnum(report_period_type_enum_1.ReportPeriodTypeEnum).default(report_period_type_enum_1.ReportPeriodTypeEnum.DAY),
|
|
12
13
|
})
|
|
14
|
+
// dateBasis / excludeClientUUID — те же, что у JSON-эндпоинтов отчётов по заказам.
|
|
15
|
+
.merge(report_order_filter_schema_1.ReportOrderFilterSchema)
|
|
13
16
|
.refine(value => {
|
|
14
17
|
const { startDate, endDate } = value;
|
|
15
18
|
if (startDate && endDate) {
|
|
@@ -4,6 +4,7 @@ exports.GetReportGroupByClientContactQuery = void 0;
|
|
|
4
4
|
const zod_1 = require("zod");
|
|
5
5
|
const enum_1 = require("../../enum");
|
|
6
6
|
const date_helper_1 = require("../../helpers/date.helper");
|
|
7
|
+
const report_order_filter_schema_1 = require("../../schemas/report/report-order-filter.schema");
|
|
7
8
|
const GetReportGroupByClientRequestSchema = zod_1.z
|
|
8
9
|
.object({
|
|
9
10
|
// Даты приходят «сырым» днём — раскладку в полуинтервал [start, endExclusive) делает сервис
|
|
@@ -23,6 +24,9 @@ const GetReportGroupByClientRequestSchema = zod_1.z
|
|
|
23
24
|
// Без значения — ограничения нет: панель по-прежнему получает все строки.
|
|
24
25
|
limit: zod_1.z.coerce.number().int().positive().optional().describe('Keep only the top N rows; implies sorting by gross profit desc.'),
|
|
25
26
|
})
|
|
27
|
+
// dateBasis / excludeClientUUID общие с sales/summary: обе цифры живут на одном экране и должны
|
|
28
|
+
// сужаться одинаково.
|
|
29
|
+
.merge(report_order_filter_schema_1.ReportOrderFilterSchema)
|
|
26
30
|
.refine(value => {
|
|
27
31
|
const { startDate, endDate } = value;
|
|
28
32
|
if (startDate && endDate) {
|
|
@@ -6,6 +6,7 @@ const enum_1 = require("../../enum");
|
|
|
6
6
|
const date_helper_1 = require("../../helpers/date.helper");
|
|
7
7
|
const pagination_helper_1 = require("../../helpers/pagination.helper");
|
|
8
8
|
const sales_by_client_row_schema_1 = require("../../schemas/report/sales-by-client-row.schema");
|
|
9
|
+
const report_order_filter_schema_1 = require("../../schemas/report/report-order-filter.schema");
|
|
9
10
|
const GetSalesByClientRequestSchema = zod_1.z
|
|
10
11
|
.object({
|
|
11
12
|
startDate: zod_1.z.coerce.date(),
|
|
@@ -18,6 +19,8 @@ const GetSalesByClientRequestSchema = zod_1.z
|
|
|
18
19
|
page: zod_1.z.coerce.number().int().positive().optional().describe('1-based page number, requires "count".'),
|
|
19
20
|
count: zod_1.z.coerce.number().int().positive().optional().describe('Rows per page. Without it every client row is returned.'),
|
|
20
21
|
})
|
|
22
|
+
// dateBasis / excludeClientUUID — те же, что у JSON-эндпоинтов отчётов по заказам.
|
|
23
|
+
.merge(report_order_filter_schema_1.ReportOrderFilterSchema)
|
|
21
24
|
.refine(value => (0, date_helper_1.dateRangeCheck)(value.startDate, value.endDate), {
|
|
22
25
|
message: 'validation.dateRange',
|
|
23
26
|
path: ['endDate', 'startDate'],
|
|
@@ -4,12 +4,16 @@ exports.GetSalesSummaryContractQuery = void 0;
|
|
|
4
4
|
const zod_1 = require("zod");
|
|
5
5
|
const date_helper_1 = require("../../helpers/date.helper");
|
|
6
6
|
const report_period_type_enum_1 = require("../../enum/report-period-type.enum");
|
|
7
|
+
const report_order_filter_schema_1 = require("../../schemas/report/report-order-filter.schema");
|
|
7
8
|
const GetSalesSummaryRequestSchema = zod_1.z
|
|
8
9
|
.object({
|
|
9
10
|
startDate: zod_1.z.coerce.date().optional(),
|
|
10
11
|
endDate: zod_1.z.coerce.date().optional(),
|
|
11
12
|
periodType: zod_1.z.nativeEnum(report_period_type_enum_1.ReportPeriodTypeEnum).default(report_period_type_enum_1.ReportPeriodTypeEnum.DAY),
|
|
12
13
|
})
|
|
14
|
+
// dateBasis / excludeClientUUID общие с group-client: обе цифры живут на одном экране и должны
|
|
15
|
+
// сужаться одинаково.
|
|
16
|
+
.merge(report_order_filter_schema_1.ReportOrderFilterSchema)
|
|
13
17
|
.refine(value => {
|
|
14
18
|
const { startDate, endDate } = value;
|
|
15
19
|
if (startDate && endDate) {
|
package/build/constant/index.js
CHANGED
|
@@ -20,3 +20,4 @@ __exportStar(require("./error-i18n-key"), exports);
|
|
|
20
20
|
__exportStar(require("./import.constant"), exports);
|
|
21
21
|
__exportStar(require("./validation-i18n-key"), exports);
|
|
22
22
|
__exportStar(require("./validation-i18n-message"), exports);
|
|
23
|
+
__exportStar(require("./report.constant"), exports);
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.REPORT_EXCLUDE_CLIENT_LIMIT = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* Потолок списка исключаемых из отчёта клиентов. Список едет в query-строке и дальше в SQL
|
|
6
|
+
* как `= ANY($n::text[])`, поэтому ограничение защищает и от переполнения URL, и от запроса
|
|
7
|
+
* с массивом в тысячи элементов.
|
|
8
|
+
*/
|
|
9
|
+
exports.REPORT_EXCLUDE_CLIENT_LIMIT = 500;
|
package/build/enum/index.js
CHANGED
|
@@ -114,3 +114,4 @@ __exportStar(require("./cash-flow-item-status.enum"), exports);
|
|
|
114
114
|
__exportStar(require("./payment-invoice-status.enum"), exports);
|
|
115
115
|
__exportStar(require("./order-by.enum"), exports);
|
|
116
116
|
__exportStar(require("./report-sort-by.enum"), exports);
|
|
117
|
+
__exportStar(require("./report-order-date-basis.enum"), exports);
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ReportOrderDateBasisEnum = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* Ось периода для отчётов по заказам — ровно одна дата на отчёт.
|
|
6
|
+
*
|
|
7
|
+
* CREATED_AT — по дате создания заказа (историческое поведение всех отчётов).
|
|
8
|
+
* COMPLETED_AT — по дате отгрузки (завершения); заказ, созданный в июне и отгруженный в июле,
|
|
9
|
+
* попадёт в июль.
|
|
10
|
+
*
|
|
11
|
+
* Дизъюнкции («любая из дат») здесь намеренно нет: заказ, созданный в июне и отгруженный в июле,
|
|
12
|
+
* попал бы в оба месяца, сумма отчётов по месяцам перестала бы сходиться с отчётом за квартал.
|
|
13
|
+
*/
|
|
14
|
+
var ReportOrderDateBasisEnum;
|
|
15
|
+
(function (ReportOrderDateBasisEnum) {
|
|
16
|
+
ReportOrderDateBasisEnum["CREATED_AT"] = "CREATED_AT";
|
|
17
|
+
ReportOrderDateBasisEnum["COMPLETED_AT"] = "COMPLETED_AT";
|
|
18
|
+
})(ReportOrderDateBasisEnum || (exports.ReportOrderDateBasisEnum = ReportOrderDateBasisEnum = {}));
|
package/build/schemas/index.js
CHANGED
|
@@ -93,3 +93,4 @@ __exportStar(require("./account-deletion-request/account-deletion-request.schema
|
|
|
93
93
|
__exportStar(require("./consignment-transfer"), exports);
|
|
94
94
|
__exportStar(require("./api-error.schema"), exports);
|
|
95
95
|
__exportStar(require("./access-policy"), exports);
|
|
96
|
+
__exportStar(require("./report/report-order-filter.schema"), exports);
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ReportOrderFilterSchema = void 0;
|
|
4
|
+
const zod_1 = require("zod");
|
|
5
|
+
const enum_1 = require("../../enum");
|
|
6
|
+
const report_constant_1 = require("../../constant/report.constant");
|
|
7
|
+
/**
|
|
8
|
+
* Общие фильтры отчётов, построенных на заказах: по какой дате заказ попадает в период и каких
|
|
9
|
+
* клиентов из него выкинуть. Схема одна на все такие отчёты — иначе `sales/summary` и
|
|
10
|
+
* `group-client` на одном экране разошлись бы в семантике при первой же правке.
|
|
11
|
+
*
|
|
12
|
+
* `excludeClientUUID` — типовой случай «отгружаем по себестоимости, в прибыли не учитываем».
|
|
13
|
+
* Принимается и CSV (`?excludeClientUUID=uuid1,uuid2`, как в get-notifications-status), и повтор
|
|
14
|
+
* параметра (`?excludeClientUUID=uuid1&excludeClientUUID=uuid2`) — Express отдаёт второй вариант
|
|
15
|
+
* массивом, и требовать от фронта именно CSV незачем.
|
|
16
|
+
*/
|
|
17
|
+
exports.ReportOrderFilterSchema = zod_1.z.object({
|
|
18
|
+
dateBasis: zod_1.z
|
|
19
|
+
.nativeEnum(enum_1.ReportOrderDateBasisEnum)
|
|
20
|
+
.default(enum_1.ReportOrderDateBasisEnum.CREATED_AT)
|
|
21
|
+
.describe('Which order date puts the order into the period. Defaults to the order creation date.'),
|
|
22
|
+
excludeClientUUID: zod_1.z
|
|
23
|
+
.union([zod_1.z.string(), zod_1.z.array(zod_1.z.string())])
|
|
24
|
+
.transform(value => (Array.isArray(value) ? value : value.split(',')).map(item => item.trim()).filter(Boolean))
|
|
25
|
+
.pipe(zod_1.z.array(zod_1.z.string().uuid()).max(report_constant_1.REPORT_EXCLUDE_CLIENT_LIMIT))
|
|
26
|
+
.optional()
|
|
27
|
+
.describe('Clients to drop from the report entirely — their orders, revenue and cost.'),
|
|
28
|
+
});
|
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
import { dateRangeCheck, isStatementPeriodWithinLimit } from '../../helpers/date.helper';
|
|
3
|
+
import { ReportOrderFilterSchema } from '../../schemas/report/report-order-filter.schema';
|
|
3
4
|
|
|
4
5
|
const ExportSalesByClientRequestSchema = z
|
|
5
6
|
.object({
|
|
6
7
|
startDate: z.coerce.date(),
|
|
7
8
|
endDate: z.coerce.date(),
|
|
8
9
|
})
|
|
10
|
+
// dateBasis / excludeClientUUID — те же, что у JSON-эндпоинтов отчётов по заказам.
|
|
11
|
+
.merge(ReportOrderFilterSchema)
|
|
9
12
|
.refine(value => dateRangeCheck(value.startDate, value.endDate), {
|
|
10
13
|
message: 'validation.dateRange',
|
|
11
14
|
path: ['endDate', 'startDate'],
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
import { dateRangeCheck, isStatementPeriodWithinLimit } from '../../helpers/date.helper';
|
|
3
3
|
import { SalesByPositionGroupByEnum } from '../../enum/sales-by-position-group-by.enum';
|
|
4
|
+
import { ReportOrderFilterSchema } from '../../schemas/report/report-order-filter.schema';
|
|
4
5
|
|
|
5
6
|
const ExportSalesByPositionRequestSchema = z
|
|
6
7
|
.object({
|
|
@@ -8,6 +9,8 @@ const ExportSalesByPositionRequestSchema = z
|
|
|
8
9
|
endDate: z.coerce.date(),
|
|
9
10
|
groupBy: z.nativeEnum(SalesByPositionGroupByEnum).default(SalesByPositionGroupByEnum.PRODUCT),
|
|
10
11
|
})
|
|
12
|
+
// dateBasis / excludeClientUUID — те же, что у JSON-эндпоинтов отчётов по заказам.
|
|
13
|
+
.merge(ReportOrderFilterSchema)
|
|
11
14
|
.refine(value => dateRangeCheck(value.startDate, value.endDate), {
|
|
12
15
|
message: 'validation.dateRange',
|
|
13
16
|
path: ['endDate', 'startDate'],
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
import { dateRangeCheck } from '../../helpers/date.helper';
|
|
3
3
|
import { ReportPeriodTypeEnum } from '../../enum/report-period-type.enum';
|
|
4
|
+
import { ReportOrderFilterSchema } from '../../schemas/report/report-order-filter.schema';
|
|
4
5
|
|
|
5
6
|
const ExportSalesRevenueRequestSchema = z
|
|
6
7
|
.object({
|
|
@@ -8,6 +9,8 @@ const ExportSalesRevenueRequestSchema = z
|
|
|
8
9
|
endDate: z.coerce.date().optional(),
|
|
9
10
|
periodType: z.nativeEnum(ReportPeriodTypeEnum).default(ReportPeriodTypeEnum.DAY),
|
|
10
11
|
})
|
|
12
|
+
// dateBasis / excludeClientUUID — те же, что у JSON-эндпоинтов отчётов по заказам.
|
|
13
|
+
.merge(ReportOrderFilterSchema)
|
|
11
14
|
.refine(
|
|
12
15
|
value => {
|
|
13
16
|
const { startDate, endDate } = value;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
import { OrderByEnum, ReportSortByEnum } from '../../enum';
|
|
3
3
|
import { dateRangeCheck } from '../../helpers/date.helper';
|
|
4
|
+
import { ReportOrderFilterSchema } from '../../schemas/report/report-order-filter.schema';
|
|
4
5
|
|
|
5
6
|
const GetReportGroupByClientRequestSchema = z
|
|
6
7
|
.object({
|
|
@@ -21,6 +22,9 @@ const GetReportGroupByClientRequestSchema = z
|
|
|
21
22
|
// Без значения — ограничения нет: панель по-прежнему получает все строки.
|
|
22
23
|
limit: z.coerce.number().int().positive().optional().describe('Keep only the top N rows; implies sorting by gross profit desc.'),
|
|
23
24
|
})
|
|
25
|
+
// dateBasis / excludeClientUUID общие с sales/summary: обе цифры живут на одном экране и должны
|
|
26
|
+
// сужаться одинаково.
|
|
27
|
+
.merge(ReportOrderFilterSchema)
|
|
24
28
|
.refine(
|
|
25
29
|
value => {
|
|
26
30
|
const { startDate, endDate } = value;
|
|
@@ -3,6 +3,7 @@ import { OrderByEnum, ReportSortByEnum } from '../../enum';
|
|
|
3
3
|
import { dateRangeCheck, isStatementPeriodWithinLimit } from '../../helpers/date.helper';
|
|
4
4
|
import { isPageAccompaniedByCount } from '../../helpers/pagination.helper';
|
|
5
5
|
import { SalesByClientRowSchema } from '../../schemas/report/sales-by-client-row.schema';
|
|
6
|
+
import { ReportOrderFilterSchema } from '../../schemas/report/report-order-filter.schema';
|
|
6
7
|
|
|
7
8
|
const GetSalesByClientRequestSchema = z
|
|
8
9
|
.object({
|
|
@@ -16,6 +17,8 @@ const GetSalesByClientRequestSchema = z
|
|
|
16
17
|
page: z.coerce.number().int().positive().optional().describe('1-based page number, requires "count".'),
|
|
17
18
|
count: z.coerce.number().int().positive().optional().describe('Rows per page. Without it every client row is returned.'),
|
|
18
19
|
})
|
|
20
|
+
// dateBasis / excludeClientUUID — те же, что у JSON-эндпоинтов отчётов по заказам.
|
|
21
|
+
.merge(ReportOrderFilterSchema)
|
|
19
22
|
.refine(value => dateRangeCheck(value.startDate, value.endDate), {
|
|
20
23
|
message: 'validation.dateRange',
|
|
21
24
|
path: ['endDate', 'startDate'],
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
import { dateRangeCheck } from '../../helpers/date.helper';
|
|
3
3
|
import { ReportPeriodTypeEnum } from '../../enum/report-period-type.enum';
|
|
4
|
+
import { ReportOrderFilterSchema } from '../../schemas/report/report-order-filter.schema';
|
|
4
5
|
|
|
5
6
|
const GetSalesSummaryRequestSchema = z
|
|
6
7
|
.object({
|
|
@@ -8,6 +9,9 @@ const GetSalesSummaryRequestSchema = z
|
|
|
8
9
|
endDate: z.coerce.date().optional(),
|
|
9
10
|
periodType: z.nativeEnum(ReportPeriodTypeEnum).default(ReportPeriodTypeEnum.DAY),
|
|
10
11
|
})
|
|
12
|
+
// dateBasis / excludeClientUUID общие с group-client: обе цифры живут на одном экране и должны
|
|
13
|
+
// сужаться одинаково.
|
|
14
|
+
.merge(ReportOrderFilterSchema)
|
|
11
15
|
.refine(
|
|
12
16
|
value => {
|
|
13
17
|
const { startDate, endDate } = value;
|
package/constant/index.ts
CHANGED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Потолок списка исключаемых из отчёта клиентов. Список едет в query-строке и дальше в SQL
|
|
3
|
+
* как `= ANY($n::text[])`, поэтому ограничение защищает и от переполнения URL, и от запроса
|
|
4
|
+
* с массивом в тысячи элементов.
|
|
5
|
+
*/
|
|
6
|
+
export const REPORT_EXCLUDE_CLIENT_LIMIT = 500;
|
package/enum/index.ts
CHANGED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Ось периода для отчётов по заказам — ровно одна дата на отчёт.
|
|
3
|
+
*
|
|
4
|
+
* CREATED_AT — по дате создания заказа (историческое поведение всех отчётов).
|
|
5
|
+
* COMPLETED_AT — по дате отгрузки (завершения); заказ, созданный в июне и отгруженный в июле,
|
|
6
|
+
* попадёт в июль.
|
|
7
|
+
*
|
|
8
|
+
* Дизъюнкции («любая из дат») здесь намеренно нет: заказ, созданный в июне и отгруженный в июле,
|
|
9
|
+
* попал бы в оба месяца, сумма отчётов по месяцам перестала бы сходиться с отчётом за квартал.
|
|
10
|
+
*/
|
|
11
|
+
export enum ReportOrderDateBasisEnum {
|
|
12
|
+
CREATED_AT = 'CREATED_AT',
|
|
13
|
+
COMPLETED_AT = 'COMPLETED_AT',
|
|
14
|
+
}
|
package/package.json
CHANGED
package/schemas/index.ts
CHANGED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { ReportOrderDateBasisEnum } from '../../enum';
|
|
3
|
+
import { REPORT_EXCLUDE_CLIENT_LIMIT } from '../../constant/report.constant';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Общие фильтры отчётов, построенных на заказах: по какой дате заказ попадает в период и каких
|
|
7
|
+
* клиентов из него выкинуть. Схема одна на все такие отчёты — иначе `sales/summary` и
|
|
8
|
+
* `group-client` на одном экране разошлись бы в семантике при первой же правке.
|
|
9
|
+
*
|
|
10
|
+
* `excludeClientUUID` — типовой случай «отгружаем по себестоимости, в прибыли не учитываем».
|
|
11
|
+
* Принимается и CSV (`?excludeClientUUID=uuid1,uuid2`, как в get-notifications-status), и повтор
|
|
12
|
+
* параметра (`?excludeClientUUID=uuid1&excludeClientUUID=uuid2`) — Express отдаёт второй вариант
|
|
13
|
+
* массивом, и требовать от фронта именно CSV незачем.
|
|
14
|
+
*/
|
|
15
|
+
export const ReportOrderFilterSchema = z.object({
|
|
16
|
+
dateBasis: z
|
|
17
|
+
.nativeEnum(ReportOrderDateBasisEnum)
|
|
18
|
+
.default(ReportOrderDateBasisEnum.CREATED_AT)
|
|
19
|
+
.describe('Which order date puts the order into the period. Defaults to the order creation date.'),
|
|
20
|
+
excludeClientUUID: z
|
|
21
|
+
.union([z.string(), z.array(z.string())])
|
|
22
|
+
.transform(value => (Array.isArray(value) ? value : value.split(',')).map(item => item.trim()).filter(Boolean))
|
|
23
|
+
.pipe(z.array(z.string().uuid()).max(REPORT_EXCLUDE_CLIENT_LIMIT))
|
|
24
|
+
.optional()
|
|
25
|
+
.describe('Clients to drop from the report entirely — their orders, revenue and cost.'),
|
|
26
|
+
});
|