@floristcloud/api-lib 1.2.107 → 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/client/create-client.command.js +2 -0
- package/build/commands/client/get-client-list.query.js +8 -0
- package/build/commands/client/index.js +1 -0
- package/build/commands/client/update-client-contract-data.command.js +22 -0
- package/build/commands/client/update-client.command.js +2 -0
- package/build/commands/money-account/get-money-account-by-criteria.query.js +7 -2
- package/build/commands/money-account/get-money-account-list.query.js +5 -1
- package/build/commands/report/export-inventory-stock.query.js +4 -17
- package/build/commands/report/export-inventory-turnover.query.js +4 -27
- 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-inventory-stock.query.js +34 -0
- package/build/commands/report/get-inventory-turnover.query.js +43 -0
- package/build/commands/report/get-report-by-client-weeks.query.js +19 -0
- package/build/commands/report/get-report-group-by-client.query.js +25 -2
- package/build/commands/report/get-report-group-by-position.query.js +21 -2
- package/build/commands/report/get-sales-by-client.query.js +48 -0
- package/build/commands/report/get-sales-summary.query.js +4 -0
- package/build/commands/report/index.js +3 -0
- package/build/commands/settings/get-company-profile.query.js +24 -0
- package/build/commands/settings/index.js +1 -0
- package/build/constant/index.js +1 -0
- package/build/constant/report.constant.js +9 -0
- package/build/enum/client-contract-status.enum.js +13 -0
- package/build/enum/index.js +4 -0
- package/build/enum/report-order-date-basis.enum.js +18 -0
- package/build/enum/report-sort-by.enum.js +13 -0
- package/build/helpers/index.js +2 -0
- package/build/helpers/pagination.helper.js +12 -0
- package/build/helpers/query-boolean.helper.js +16 -0
- package/build/schemas/client/client.schema.js +2 -0
- package/build/schemas/index.js +8 -0
- package/build/schemas/money-account/money-account-with-balance.schema.js +13 -0
- package/build/schemas/report/inventory-stock-category-item.schema.js +10 -0
- package/build/schemas/report/inventory-stock-detailed-item.schema.js +14 -0
- package/build/schemas/report/inventory-turnover-category-item.schema.js +15 -0
- package/build/schemas/report/inventory-turnover-detailed-item.schema.js +19 -0
- package/build/schemas/report/report-order-filter.schema.js +28 -0
- package/build/schemas/report/sales-by-client-row.schema.js +45 -0
- package/build/schemas/report/sales-by-client-top-item.schema.js +9 -0
- package/commands/client/create-client.command.ts +2 -0
- package/commands/client/get-client-list.query.ts +8 -0
- package/commands/client/index.ts +1 -0
- package/commands/client/update-client-contract-data.command.ts +24 -0
- package/commands/client/update-client.command.ts +2 -0
- package/commands/money-account/get-money-account-by-criteria.query.ts +10 -3
- package/commands/money-account/get-money-account-list.query.ts +8 -2
- package/commands/report/export-inventory-stock.query.ts +4 -19
- package/commands/report/export-inventory-turnover.query.ts +4 -29
- 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-inventory-stock.query.ts +36 -0
- package/commands/report/get-inventory-turnover.query.ts +45 -0
- package/commands/report/get-report-by-client-weeks.query.ts +20 -1
- package/commands/report/get-report-group-by-client.query.ts +26 -3
- package/commands/report/get-report-group-by-position.query.ts +23 -4
- package/commands/report/get-sales-by-client.query.ts +50 -0
- package/commands/report/get-sales-summary.query.ts +4 -0
- package/commands/report/index.ts +3 -0
- package/commands/settings/get-company-profile.query.ts +24 -0
- package/commands/settings/index.ts +1 -0
- package/constant/index.ts +1 -0
- package/constant/report.constant.ts +6 -0
- package/enum/client-contract-status.enum.ts +9 -0
- package/enum/index.ts +4 -0
- package/enum/report-order-date-basis.enum.ts +14 -0
- package/enum/report-sort-by.enum.ts +9 -0
- package/helpers/index.ts +2 -0
- package/helpers/pagination.helper.ts +9 -0
- package/helpers/query-boolean.helper.ts +14 -0
- package/package.json +1 -1
- package/schemas/client/client.schema.ts +2 -0
- package/schemas/index.ts +8 -0
- package/schemas/money-account/money-account-with-balance.schema.ts +11 -0
- package/schemas/report/inventory-stock-category-item.schema.ts +8 -0
- package/schemas/report/inventory-stock-detailed-item.schema.ts +12 -0
- package/schemas/report/inventory-turnover-category-item.schema.ts +13 -0
- package/schemas/report/inventory-turnover-detailed-item.schema.ts +17 -0
- package/schemas/report/report-order-filter.schema.ts +26 -0
- package/schemas/report/sales-by-client-row.schema.ts +43 -0
- package/schemas/report/sales-by-client-top-item.schema.ts +7 -0
|
@@ -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 = {}));
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ReportSortByEnum = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* Метрика сортировки для отчётов-группировок (по позициям и по клиентам).
|
|
6
|
+
* Значения совпадают с именами полей ответа, чтобы клиент мог сортировать «по тому, что видит».
|
|
7
|
+
*/
|
|
8
|
+
var ReportSortByEnum;
|
|
9
|
+
(function (ReportSortByEnum) {
|
|
10
|
+
ReportSortByEnum["GROSS_PROFIT"] = "grossProfit";
|
|
11
|
+
ReportSortByEnum["TOTAL_SALES"] = "totalSales";
|
|
12
|
+
ReportSortByEnum["SOLD_UNITS"] = "soldUnits";
|
|
13
|
+
})(ReportSortByEnum || (exports.ReportSortByEnum = ReportSortByEnum = {}));
|
package/build/helpers/index.js
CHANGED
|
@@ -15,3 +15,5 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
15
15
|
};
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
17
|
__exportStar(require("./date.helper"), exports);
|
|
18
|
+
__exportStar(require("./pagination.helper"), exports);
|
|
19
|
+
__exportStar(require("./query-boolean.helper"), exports);
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.isPageAccompaniedByCount = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* `page` имеет смысл только вместе с `count`.
|
|
6
|
+
*
|
|
7
|
+
* Раньше `page` без `count` молча игнорировался и отчёт отдавался целиком: агент, листающий
|
|
8
|
+
* страницы, бесконечно получал одну и ту же выдачу и не мог отличить это от «страниц больше нет».
|
|
9
|
+
* Поэтому неполная пара отклоняется валидацией — единообразно во всех постраничных отчётах.
|
|
10
|
+
*/
|
|
11
|
+
const isPageAccompaniedByCount = (value) => value.page === undefined || value.count !== undefined;
|
|
12
|
+
exports.isPageAccompaniedByCount = isPageAccompaniedByCount;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.queryBooleanSchema = void 0;
|
|
4
|
+
const zod_1 = require("zod");
|
|
5
|
+
/**
|
|
6
|
+
* Boolean-флаг, приходящий в query-строке.
|
|
7
|
+
*
|
|
8
|
+
* Не `z.coerce.boolean()`: в query всегда приходит текст, а `Boolean('false') === true` —
|
|
9
|
+
* такой флаг невозможно выключить явным значением. Принимаем `true` / `1` как включение,
|
|
10
|
+
* всё остальное — выключение. По умолчанию флаг выключен, чтобы поведение без параметра не менялось.
|
|
11
|
+
*/
|
|
12
|
+
exports.queryBooleanSchema = zod_1.z
|
|
13
|
+
.union([zod_1.z.boolean(), zod_1.z.string()])
|
|
14
|
+
.optional()
|
|
15
|
+
.default(false)
|
|
16
|
+
.transform(value => (typeof value === 'boolean' ? value : value === 'true' || value === '1'));
|
|
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.ClientExtendedListSchema = exports.ClientExtendedSchema = exports.ClientSchema = void 0;
|
|
4
4
|
const zod_1 = require("zod");
|
|
5
5
|
const client_status_enum_1 = require("../../enum/client-status.enum");
|
|
6
|
+
const client_contract_status_enum_1 = require("../../enum/client-contract-status.enum");
|
|
6
7
|
const client_type_enum_1 = require("../../enum/client-type.enum");
|
|
7
8
|
const user_schema_1 = require("../user/user.schema");
|
|
8
9
|
const client_individual_profile_schema_1 = require("./client-individual-profile.schema");
|
|
@@ -19,6 +20,7 @@ exports.ClientSchema = zod_1.z.object({
|
|
|
19
20
|
isCommon: zod_1.z.boolean(),
|
|
20
21
|
contractNumber: zod_1.z.string().nullable(),
|
|
21
22
|
contractDate: zod_1.z.date().nullable(),
|
|
23
|
+
contractStatus: zod_1.z.nativeEnum(client_contract_status_enum_1.ClientContractStatusEnum),
|
|
22
24
|
address: zod_1.z.string().nullable(),
|
|
23
25
|
city: zod_1.z.string().nullable(),
|
|
24
26
|
code: zod_1.z.string().nullable(),
|
package/build/schemas/index.js
CHANGED
|
@@ -38,6 +38,7 @@ __exportStar(require("./product-image/product-image.schema"), exports);
|
|
|
38
38
|
__exportStar(require("./settings/settings.schema"), exports);
|
|
39
39
|
__exportStar(require("./payment-invoice/payment-invoice.schema"), exports);
|
|
40
40
|
__exportStar(require("./money-account/money-account.schema"), exports);
|
|
41
|
+
__exportStar(require("./money-account/money-account-with-balance.schema"), exports);
|
|
41
42
|
__exportStar(require("./domain/domain.schema"), exports);
|
|
42
43
|
__exportStar(require("./category/category.schema"), exports);
|
|
43
44
|
__exportStar(require("./branch/branch.schema"), exports);
|
|
@@ -68,6 +69,12 @@ __exportStar(require("./consignment/consignment-distribution-validation.schema")
|
|
|
68
69
|
__exportStar(require("./product-image-template/product-image-template.schema"), exports);
|
|
69
70
|
__exportStar(require("./report/client-statement.schema"), exports);
|
|
70
71
|
__exportStar(require("./report/client-by-weeks.schema"), exports);
|
|
72
|
+
__exportStar(require("./report/inventory-stock-category-item.schema"), exports);
|
|
73
|
+
__exportStar(require("./report/inventory-stock-detailed-item.schema"), exports);
|
|
74
|
+
__exportStar(require("./report/inventory-turnover-category-item.schema"), exports);
|
|
75
|
+
__exportStar(require("./report/inventory-turnover-detailed-item.schema"), exports);
|
|
76
|
+
__exportStar(require("./report/sales-by-client-top-item.schema"), exports);
|
|
77
|
+
__exportStar(require("./report/sales-by-client-row.schema"), exports);
|
|
71
78
|
__exportStar(require("./action-log/index"), exports);
|
|
72
79
|
__exportStar(require("./delivery-route/delivery-route.schema"), exports);
|
|
73
80
|
__exportStar(require("./product/product-multiplicity-option.schema"), exports);
|
|
@@ -86,3 +93,4 @@ __exportStar(require("./account-deletion-request/account-deletion-request.schema
|
|
|
86
93
|
__exportStar(require("./consignment-transfer"), exports);
|
|
87
94
|
__exportStar(require("./api-error.schema"), exports);
|
|
88
95
|
__exportStar(require("./access-policy"), exports);
|
|
96
|
+
__exportStar(require("./report/report-order-filter.schema"), exports);
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.MoneyAccountWithBalanceSchema = void 0;
|
|
4
|
+
const zod_1 = require("zod");
|
|
5
|
+
const money_account_schema_1 = require("./money-account.schema");
|
|
6
|
+
/**
|
|
7
|
+
* Денежный счёт в ответах списков. `balance` — текущий остаток счёта (приход минус расход),
|
|
8
|
+
* приходит только при `?withBalance=true`: поле аддитивное, клиенты без этого параметра
|
|
9
|
+
* получают ровно прежнюю форму ответа.
|
|
10
|
+
*/
|
|
11
|
+
exports.MoneyAccountWithBalanceSchema = money_account_schema_1.MoneyAccountSchema.extend({
|
|
12
|
+
balance: zod_1.z.number().optional(),
|
|
13
|
+
});
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.InventoryStockCategoryItemSchema = void 0;
|
|
4
|
+
const zod_1 = require("zod");
|
|
5
|
+
/** Строка отчёта об остатках в разрезе категорий (`detailed=false`). */
|
|
6
|
+
exports.InventoryStockCategoryItemSchema = zod_1.z.object({
|
|
7
|
+
categoryUUID: zod_1.z.string(),
|
|
8
|
+
categoryName: zod_1.z.string(),
|
|
9
|
+
balance: zod_1.z.number(),
|
|
10
|
+
});
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.InventoryStockDetailedItemSchema = void 0;
|
|
4
|
+
const zod_1 = require("zod");
|
|
5
|
+
/** Строка отчёта об остатках с детализацией по name/size/grower (`detailed=true`). */
|
|
6
|
+
exports.InventoryStockDetailedItemSchema = zod_1.z.object({
|
|
7
|
+
categoryUUID: zod_1.z.string(),
|
|
8
|
+
categoryName: zod_1.z.string(),
|
|
9
|
+
name: zod_1.z.string(),
|
|
10
|
+
color: zod_1.z.string().nullable(),
|
|
11
|
+
size: zod_1.z.string().nullable(),
|
|
12
|
+
grower: zod_1.z.string().nullable(),
|
|
13
|
+
balance: zod_1.z.number(),
|
|
14
|
+
});
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.InventoryTurnoverCategoryItemSchema = void 0;
|
|
4
|
+
const zod_1 = require("zod");
|
|
5
|
+
/** Строка отчёта об оборачиваемости в разрезе категорий (`detailed=false`). */
|
|
6
|
+
exports.InventoryTurnoverCategoryItemSchema = zod_1.z.object({
|
|
7
|
+
categoryUUID: zod_1.z.string(),
|
|
8
|
+
categoryName: zod_1.z.string(),
|
|
9
|
+
initialBalance: zod_1.z.number(), // начальный остаток
|
|
10
|
+
receipts: zod_1.z.number(), // приходы
|
|
11
|
+
sales: zod_1.z.number(), // продажи
|
|
12
|
+
currentBalance: zod_1.z.number(), // текущий остаток
|
|
13
|
+
daysInStock: zod_1.z.number(), // дни в наличии на складе
|
|
14
|
+
turnoverRate: zod_1.z.number(), // коэффициент оборачиваемости
|
|
15
|
+
});
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.InventoryTurnoverDetailedItemSchema = void 0;
|
|
4
|
+
const zod_1 = require("zod");
|
|
5
|
+
/** Строка отчёта об оборачиваемости с детализацией по name/size/grower (`detailed=true`). */
|
|
6
|
+
exports.InventoryTurnoverDetailedItemSchema = zod_1.z.object({
|
|
7
|
+
categoryUUID: zod_1.z.string(),
|
|
8
|
+
categoryName: zod_1.z.string(),
|
|
9
|
+
name: zod_1.z.string(),
|
|
10
|
+
color: zod_1.z.string().nullable(),
|
|
11
|
+
size: zod_1.z.string().nullable(),
|
|
12
|
+
grower: zod_1.z.string().nullable(), // производитель
|
|
13
|
+
initialBalance: zod_1.z.number(), // начальный остаток
|
|
14
|
+
receipts: zod_1.z.number(), // приходы
|
|
15
|
+
sales: zod_1.z.number(), // продажи
|
|
16
|
+
currentBalance: zod_1.z.number(), // текущий остаток
|
|
17
|
+
daysInStock: zod_1.z.number(), // дни в наличии на складе
|
|
18
|
+
turnoverRate: zod_1.z.number(), // коэффициент оборачиваемости
|
|
19
|
+
});
|
|
@@ -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
|
+
});
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.SalesByClientRowSchema = void 0;
|
|
4
|
+
const zod_1 = require("zod");
|
|
5
|
+
const sales_by_client_top_item_schema_1 = require("./sales-by-client-top-item.schema");
|
|
6
|
+
/**
|
|
7
|
+
* Строка отчёта «продажи по клиентам» — те же данные, что уходят в Excel из `export/sales/clients`.
|
|
8
|
+
* Опциональные поля отсутствуют в ответе, когда у клиента нет соответствующего значения.
|
|
9
|
+
*/
|
|
10
|
+
exports.SalesByClientRowSchema = zod_1.z.object({
|
|
11
|
+
uuid: zod_1.z.string(),
|
|
12
|
+
clientName: zod_1.z.string(),
|
|
13
|
+
responsibleUserName: zod_1.z.string().optional(),
|
|
14
|
+
totalOrders: zod_1.z.number(),
|
|
15
|
+
soldUnits: zod_1.z.number(),
|
|
16
|
+
soldUnitsByUnit: zod_1.z.object({
|
|
17
|
+
PIECE: zod_1.z.number(),
|
|
18
|
+
PACK: zod_1.z.number(),
|
|
19
|
+
BOX: zod_1.z.number(),
|
|
20
|
+
}),
|
|
21
|
+
totalSales: zod_1.z.number(),
|
|
22
|
+
avgCheck: zod_1.z.number(),
|
|
23
|
+
totalWriteOff: zod_1.z.number(),
|
|
24
|
+
grossProfit: zod_1.z.number(),
|
|
25
|
+
marginality: zod_1.z.number(),
|
|
26
|
+
// Оплаты (INCOME) и предоплаты (PREPAYMENT) клиента за период
|
|
27
|
+
totalPayments: zod_1.z.number(),
|
|
28
|
+
totalPrepayments: zod_1.z.number(),
|
|
29
|
+
// Сумма услуг (order_service_line) за период — отдельно, вне товарных sales/margin
|
|
30
|
+
totalServiceAmount: zod_1.z.number(),
|
|
31
|
+
// Текущий баланс клиента (на момент формирования отчёта)
|
|
32
|
+
balance: zod_1.z.number(),
|
|
33
|
+
lastOrderDate: zod_1.z.coerce.date().optional(),
|
|
34
|
+
// Топ-5 по сумме выручки за период
|
|
35
|
+
topCategories: zod_1.z.array(sales_by_client_top_item_schema_1.SalesByClientTopItemSchema),
|
|
36
|
+
topProducts: zod_1.z.array(sales_by_client_top_item_schema_1.SalesByClientTopItemSchema),
|
|
37
|
+
// Статическая информация о клиенте
|
|
38
|
+
code: zod_1.z.string().optional(),
|
|
39
|
+
city: zod_1.z.string().optional(),
|
|
40
|
+
contactName: zod_1.z.string().optional(),
|
|
41
|
+
phone: zod_1.z.string().optional(),
|
|
42
|
+
clientType: zod_1.z.string().optional(),
|
|
43
|
+
status: zod_1.z.string().optional(),
|
|
44
|
+
group: zod_1.z.string().optional(),
|
|
45
|
+
});
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.SalesByClientTopItemSchema = void 0;
|
|
4
|
+
const zod_1 = require("zod");
|
|
5
|
+
/** Элемент топа (категория или товар) внутри строки отчёта «продажи по клиентам». */
|
|
6
|
+
exports.SalesByClientTopItemSchema = zod_1.z.object({
|
|
7
|
+
name: zod_1.z.string(),
|
|
8
|
+
amount: zod_1.z.number(),
|
|
9
|
+
});
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
import { ClientSchema } from '../../schemas';
|
|
3
3
|
import { ClientStatusEnum } from '../../enum/client-status.enum';
|
|
4
|
+
import { ClientContractStatusEnum } from '../../enum/client-contract-status.enum';
|
|
4
5
|
import { ClientTypeEnum } from '../../enum/client-type.enum';
|
|
5
6
|
|
|
6
7
|
const CreateClientRequestSchema = z.object({
|
|
@@ -13,6 +14,7 @@ const CreateClientRequestSchema = z.object({
|
|
|
13
14
|
isCommon: z.coerce.boolean(),
|
|
14
15
|
contractNumber: z.string().nullable().optional(),
|
|
15
16
|
contractDate: z.coerce.date().nullable().optional(),
|
|
17
|
+
contractStatus: z.nativeEnum(ClientContractStatusEnum).optional(),
|
|
16
18
|
address: z.string().nullable().optional(),
|
|
17
19
|
city: z.string().nullable().optional(),
|
|
18
20
|
code: z.string().nullable().optional(),
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
import { ClientExtendedListSchema } from '../../schemas';
|
|
3
3
|
import { ClientStatusEnum } from '../../enum/client-status.enum';
|
|
4
|
+
import { ClientContractStatusEnum } from '../../enum/client-contract-status.enum';
|
|
4
5
|
import { ClientTypeEnum } from '../../enum/client-type.enum';
|
|
5
6
|
|
|
6
7
|
const GetClientListRequestSchema = z.object({
|
|
@@ -17,6 +18,13 @@ const GetClientListRequestSchema = z.object({
|
|
|
17
18
|
.string()
|
|
18
19
|
.optional()
|
|
19
20
|
.transform(val => (val === 'true' ? true : val === 'false' || val === '' ? false : undefined)),
|
|
21
|
+
contractStatus: z.nativeEnum(ClientContractStatusEnum).optional(),
|
|
22
|
+
// Feeds the "Contracts" tab: a client counts as having a contract record when a number or a date
|
|
23
|
+
// is filled in, or the contract status has been moved off NONE.
|
|
24
|
+
hasContractRecord: z
|
|
25
|
+
.string()
|
|
26
|
+
.optional()
|
|
27
|
+
.transform(val => (val === 'true' ? true : val === 'false' ? false : undefined)),
|
|
20
28
|
});
|
|
21
29
|
|
|
22
30
|
const GetClientListResponseSchema = z.object({
|
package/commands/client/index.ts
CHANGED
|
@@ -4,6 +4,7 @@ export * from './get-client-list.query';
|
|
|
4
4
|
export * from './get-client-debt-list.query';
|
|
5
5
|
export * from './create-client.command';
|
|
6
6
|
export * from './update-client.command';
|
|
7
|
+
export * from './update-client-contract-data.command';
|
|
7
8
|
export * from './delete-client.command';
|
|
8
9
|
export * from './get-client-calculate.query';
|
|
9
10
|
export * from './set-balance-calculate-client.command';
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { ClientSchema } from '../../schemas';
|
|
3
|
+
import { ClientContractStatusEnum } from '../../enum/client-contract-status.enum';
|
|
4
|
+
|
|
5
|
+
// Narrow, partial counterpart of UpdateClientContract: touches only the contract fields, so a
|
|
6
|
+
// one-click status change cannot overwrite the rest of the client with a stale snapshot.
|
|
7
|
+
const UpdateClientContractDataRequestSchema = z.object({
|
|
8
|
+
contractNumber: z.string().nullable().optional(),
|
|
9
|
+
contractDate: z.coerce.date().nullable().optional(),
|
|
10
|
+
contractStatus: z.nativeEnum(ClientContractStatusEnum).optional(),
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
const UpdateClientContractDataResponseSchema = z.object({
|
|
14
|
+
message: z.string().optional(),
|
|
15
|
+
data: ClientSchema.nullable(),
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
export namespace UpdateClientContractDataContractCommand {
|
|
19
|
+
export const RequestSchema = UpdateClientContractDataRequestSchema;
|
|
20
|
+
export type Request = z.infer<typeof RequestSchema>;
|
|
21
|
+
|
|
22
|
+
export const ResponseSchema = UpdateClientContractDataResponseSchema;
|
|
23
|
+
export type Response = z.infer<typeof ResponseSchema>;
|
|
24
|
+
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
import { ClientSchema } from '../../schemas';
|
|
3
3
|
import { ClientStatusEnum } from '../../enum/client-status.enum';
|
|
4
|
+
import { ClientContractStatusEnum } from '../../enum/client-contract-status.enum';
|
|
4
5
|
import { ClientTypeEnum } from '../../enum/client-type.enum';
|
|
5
6
|
|
|
6
7
|
const UpdateClientRequestSchema = z.object({
|
|
@@ -13,6 +14,7 @@ const UpdateClientRequestSchema = z.object({
|
|
|
13
14
|
type: z.nativeEnum(ClientTypeEnum),
|
|
14
15
|
contractNumber: z.string().nullable(),
|
|
15
16
|
contractDate: z.coerce.date().nullable(),
|
|
17
|
+
contractStatus: z.nativeEnum(ClientContractStatusEnum).optional(),
|
|
16
18
|
address: z.string().nullable().optional(),
|
|
17
19
|
city: z.string().nullable().optional(),
|
|
18
20
|
code: z.string().nullable().optional(),
|
|
@@ -1,11 +1,18 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
|
-
import {
|
|
2
|
+
import { MoneyAccountWithBalanceSchema } from '../../schemas';
|
|
3
|
+
import { queryBooleanSchema } from '../../helpers/query-boolean.helper';
|
|
3
4
|
|
|
4
|
-
const GetMoneyAccountByCriteriaRequestSchema = z.object({
|
|
5
|
+
const GetMoneyAccountByCriteriaRequestSchema = z.object({
|
|
6
|
+
// Опционально: посчитать остаток каждого счёта одним агрегатом вместо отдельного
|
|
7
|
+
// GET /transaction/sum/:moneyAccountUUID на каждый счёт. Описание видит и MCP-каталог.
|
|
8
|
+
withBalance: queryBooleanSchema.describe(
|
|
9
|
+
'Pass "true" to include the current balance of every money account, instead of calling transaction/sum per account.',
|
|
10
|
+
),
|
|
11
|
+
});
|
|
5
12
|
|
|
6
13
|
const GetMoneyAccountByCriteriaResponseSchema = z.object({
|
|
7
14
|
message: z.string().optional(),
|
|
8
|
-
data:
|
|
15
|
+
data: MoneyAccountWithBalanceSchema.array(),
|
|
9
16
|
});
|
|
10
17
|
|
|
11
18
|
export namespace GetMoneyAccountByCriteriaContractQuery {
|
|
@@ -1,15 +1,21 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
|
-
import {
|
|
2
|
+
import { MoneyAccountWithBalanceSchema } from '../../schemas';
|
|
3
|
+
import { queryBooleanSchema } from '../../helpers/query-boolean.helper';
|
|
3
4
|
|
|
4
5
|
const GetMoneyAccountListRequestSchema = z.object({
|
|
5
6
|
page: z.string().transform(val => Number(val) || 1),
|
|
6
7
|
count: z.string().transform(val => Number(val) || 10),
|
|
8
|
+
// Опционально: посчитать остаток каждого счёта одним агрегатом вместо отдельного
|
|
9
|
+
// GET /transaction/sum/:moneyAccountUUID на каждый счёт. Описание видит и MCP-каталог.
|
|
10
|
+
withBalance: queryBooleanSchema.describe(
|
|
11
|
+
'Pass "true" to include the current balance of every money account, instead of calling transaction/sum per account.',
|
|
12
|
+
),
|
|
7
13
|
});
|
|
8
14
|
|
|
9
15
|
const GetMoneyAccountListResponseSchema = z.object({
|
|
10
16
|
message: z.string().optional(),
|
|
11
17
|
data: z.object({
|
|
12
|
-
list: z.array(
|
|
18
|
+
list: z.array(MoneyAccountWithBalanceSchema),
|
|
13
19
|
total: z.number(),
|
|
14
20
|
}),
|
|
15
21
|
});
|
|
@@ -1,30 +1,15 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
|
+
import { InventoryStockCategoryItemSchema } from '../../schemas/report/inventory-stock-category-item.schema';
|
|
3
|
+
import { InventoryStockDetailedItemSchema } from '../../schemas/report/inventory-stock-detailed-item.schema';
|
|
2
4
|
|
|
3
5
|
const ExportInventoryStockRequestSchema = z.object({
|
|
4
6
|
categoryUUID: z.uuid().optional(), // Фильтр по категории
|
|
5
7
|
detailed: z.coerce.boolean().optional().default(false), // Флаг для детализации (группировка по name, size, grower)
|
|
6
8
|
});
|
|
7
9
|
|
|
8
|
-
//
|
|
9
|
-
const CategoryStockItemSchema = z.object({
|
|
10
|
-
categoryUUID: z.string(),
|
|
11
|
-
categoryName: z.string(),
|
|
12
|
-
balance: z.number(),
|
|
13
|
-
});
|
|
14
|
-
|
|
15
|
-
// Ответ для детализированного отчета (с группировкой по name, size, grower)
|
|
16
|
-
const DetailedStockItemSchema = z.object({
|
|
17
|
-
categoryUUID: z.string(),
|
|
18
|
-
categoryName: z.string(),
|
|
19
|
-
name: z.string(),
|
|
20
|
-
color: z.string().nullable(),
|
|
21
|
-
size: z.string().nullable(),
|
|
22
|
-
grower: z.string().nullable(),
|
|
23
|
-
balance: z.number(),
|
|
24
|
-
});
|
|
25
|
-
|
|
10
|
+
// Строки живут в schemas/report — их же отдаёт JSON-эндпоинт report/inventory/stock, форма ответа общая.
|
|
26
11
|
const ExportInventoryStockResponseSchema = z.object({
|
|
27
|
-
data: z.array(z.union([
|
|
12
|
+
data: z.array(z.union([InventoryStockCategoryItemSchema, InventoryStockDetailedItemSchema])),
|
|
28
13
|
});
|
|
29
14
|
|
|
30
15
|
export namespace ExportInventoryStockContractQuery {
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
import { dateRangeCheck } from '../../helpers/date.helper';
|
|
3
|
+
import { InventoryTurnoverCategoryItemSchema } from '../../schemas/report/inventory-turnover-category-item.schema';
|
|
4
|
+
import { InventoryTurnoverDetailedItemSchema } from '../../schemas/report/inventory-turnover-detailed-item.schema';
|
|
3
5
|
|
|
4
6
|
const ExportInventoryTurnoverRequestSchema = z
|
|
5
7
|
.object({
|
|
@@ -22,36 +24,9 @@ const ExportInventoryTurnoverRequestSchema = z
|
|
|
22
24
|
},
|
|
23
25
|
);
|
|
24
26
|
|
|
25
|
-
//
|
|
26
|
-
const CategoryTurnoverItemSchema = z.object({
|
|
27
|
-
categoryUUID: z.string(),
|
|
28
|
-
categoryName: z.string(),
|
|
29
|
-
initialBalance: z.number(), // начальный остаток
|
|
30
|
-
receipts: z.number(), // приходы
|
|
31
|
-
sales: z.number(), // продажи
|
|
32
|
-
currentBalance: z.number(), // текущий остаток
|
|
33
|
-
daysInStock: z.number(), // дни в наличии на складе
|
|
34
|
-
turnoverRate: z.number(), // коэффициент оборачиваемости
|
|
35
|
-
});
|
|
36
|
-
|
|
37
|
-
// Ответ для детализированного отчета (с группировкой по name, size, grower)
|
|
38
|
-
const DetailedTurnoverItemSchema = z.object({
|
|
39
|
-
categoryUUID: z.string(),
|
|
40
|
-
categoryName: z.string(),
|
|
41
|
-
name: z.string(),
|
|
42
|
-
color: z.string().nullable(),
|
|
43
|
-
size: z.string().nullable(),
|
|
44
|
-
grower: z.string().nullable(), // производитель
|
|
45
|
-
initialBalance: z.number(), // начальный остаток
|
|
46
|
-
receipts: z.number(), // приходы
|
|
47
|
-
sales: z.number(), // продажи
|
|
48
|
-
currentBalance: z.number(), // текущий остаток
|
|
49
|
-
daysInStock: z.number(), // дни в наличии на складе
|
|
50
|
-
turnoverRate: z.number(), // коэффициент оборачиваемости
|
|
51
|
-
});
|
|
52
|
-
|
|
27
|
+
// Строки живут в schemas/report — их же отдаёт JSON-эндпоинт report/inventory/turnover, форма ответа общая.
|
|
53
28
|
const ExportInventoryTurnoverResponseSchema = z.object({
|
|
54
|
-
data: z.array(z.union([
|
|
29
|
+
data: z.array(z.union([InventoryTurnoverCategoryItemSchema, InventoryTurnoverDetailedItemSchema])),
|
|
55
30
|
});
|
|
56
31
|
|
|
57
32
|
export namespace ExportInventoryTurnoverContractQuery {
|
|
@@ -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;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { isPageAccompaniedByCount } from '../../helpers/pagination.helper';
|
|
3
|
+
import { queryBooleanSchema } from '../../helpers/query-boolean.helper';
|
|
4
|
+
import { InventoryStockCategoryItemSchema } from '../../schemas/report/inventory-stock-category-item.schema';
|
|
5
|
+
import { InventoryStockDetailedItemSchema } from '../../schemas/report/inventory-stock-detailed-item.schema';
|
|
6
|
+
|
|
7
|
+
const GetInventoryStockRequestSchema = z
|
|
8
|
+
.object({
|
|
9
|
+
categoryUUID: z.uuid().optional().describe('Keep only the products of this category.'),
|
|
10
|
+
detailed: queryBooleanSchema.describe('Pass "true" to group rows by product name / size / grower instead of by category only.'),
|
|
11
|
+
// Пагинация по строкам отчёта. Без count лимит не накладывается — отдаём весь отчёт,
|
|
12
|
+
// а page без count отклоняется: иначе листание молча возвращало бы одну и ту же выдачу.
|
|
13
|
+
page: z.coerce.number().int().positive().optional().describe('1-based page number, requires "count".'),
|
|
14
|
+
count: z.coerce.number().int().positive().optional().describe('Rows per page. Without it the whole report is returned.'),
|
|
15
|
+
})
|
|
16
|
+
.refine(isPageAccompaniedByCount, {
|
|
17
|
+
message: 'validation.pageRequiresCount',
|
|
18
|
+
path: ['page'],
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
const GetInventoryStockResponseSchema = z.object({
|
|
22
|
+
message: z.string().optional(),
|
|
23
|
+
data: z.object({
|
|
24
|
+
list: z.array(z.union([InventoryStockCategoryItemSchema, InventoryStockDetailedItemSchema])),
|
|
25
|
+
// Число строк во всём отчёте — не размер страницы.
|
|
26
|
+
total: z.number(),
|
|
27
|
+
}),
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
export namespace GetInventoryStockContractQuery {
|
|
31
|
+
export const RequestSchema = GetInventoryStockRequestSchema;
|
|
32
|
+
export type Request = z.infer<typeof RequestSchema>;
|
|
33
|
+
|
|
34
|
+
export const ResponseSchema = GetInventoryStockResponseSchema;
|
|
35
|
+
export type Response = z.infer<typeof ResponseSchema>;
|
|
36
|
+
}
|