@floristcloud/api-lib 1.2.116 → 1.2.118
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/index.js +1 -0
- package/build/commands/order/get-order-list.query.js +5 -0
- package/build/commands/transfer-document/create-transfer-document.command.js +31 -0
- package/build/commands/transfer-document/delete-transfer-document.command.js +26 -0
- package/build/commands/transfer-document/get-transfer-document-list.query.js +23 -0
- package/build/commands/transfer-document/get-transfer-document.query.js +15 -0
- package/build/commands/transfer-document/index.js +21 -0
- package/build/commands/transfer-document/issue-transfer-document.command.js +17 -0
- package/build/constant/error-i18n-key.js +1 -0
- package/build/constant/error.js +53 -0
- package/build/constant/index.js +2 -0
- package/build/constant/okei.js +16 -0
- package/build/constant/oksm.js +72 -0
- package/build/enum/index.js +4 -0
- package/build/enum/invoice-product-field.enum.js +18 -0
- package/build/enum/transfer-document-item-kind.enum.js +15 -0
- package/build/enum/transfer-document-kind.enum.js +9 -0
- package/build/enum/transfer-document-state.enum.js +8 -0
- package/build/schemas/index.js +2 -0
- package/build/schemas/order/order.schema.js +7 -1
- package/build/schemas/settings/settings.schema.js +37 -0
- package/build/schemas/transfer-document/transfer-document-detailed.schema.js +37 -0
- package/build/schemas/transfer-document/transfer-document.schema.js +42 -0
- package/commands/index.ts +1 -0
- package/commands/order/get-order-list.query.ts +5 -0
- package/commands/transfer-document/create-transfer-document.command.ts +34 -0
- package/commands/transfer-document/delete-transfer-document.command.ts +28 -0
- package/commands/transfer-document/get-transfer-document-list.query.ts +25 -0
- package/commands/transfer-document/get-transfer-document.query.ts +17 -0
- package/commands/transfer-document/index.ts +5 -0
- package/commands/transfer-document/issue-transfer-document.command.ts +19 -0
- package/constant/error-i18n-key.ts +1 -0
- package/constant/error.ts +53 -0
- package/constant/index.ts +2 -0
- package/constant/okei.ts +14 -0
- package/constant/oksm.ts +69 -0
- package/enum/index.ts +4 -0
- package/enum/invoice-product-field.enum.ts +14 -0
- package/enum/transfer-document-item-kind.enum.ts +11 -0
- package/enum/transfer-document-kind.enum.ts +5 -0
- package/enum/transfer-document-state.enum.ts +4 -0
- package/package.json +1 -1
- package/schemas/index.ts +2 -0
- package/schemas/order/order.schema.ts +7 -1
- package/schemas/settings/settings.schema.ts +38 -0
- package/schemas/transfer-document/transfer-document-detailed.schema.ts +36 -0
- package/schemas/transfer-document/transfer-document.schema.ts +41 -0
package/build/commands/index.js
CHANGED
|
@@ -83,3 +83,4 @@ Object.defineProperty(exports, "CreateWsTicketContractCommand", { enumerable: tr
|
|
|
83
83
|
var validate_ws_ticket_s2s_query_1 = require("./session/validate-ws-ticket-s2s.query");
|
|
84
84
|
Object.defineProperty(exports, "ValidateWsTicketS2SContractQuery", { enumerable: true, get: function () { return validate_ws_ticket_s2s_query_1.ValidateWsTicketS2SContractQuery; } });
|
|
85
85
|
__exportStar(require("./consignment-transfer"), exports);
|
|
86
|
+
__exportStar(require("./transfer-document"), exports);
|
|
@@ -4,6 +4,7 @@ exports.GetOrderListContractQuery = void 0;
|
|
|
4
4
|
const zod_1 = require("zod");
|
|
5
5
|
const schemas_1 = require("../../schemas");
|
|
6
6
|
const date_helper_1 = require("../../helpers/date.helper");
|
|
7
|
+
const query_boolean_helper_1 = require("../../helpers/query-boolean.helper");
|
|
7
8
|
const enum_1 = require("../../enum");
|
|
8
9
|
const GetOrderListRequestSchema = zod_1.z
|
|
9
10
|
.object({
|
|
@@ -28,6 +29,10 @@ const GetOrderListRequestSchema = zod_1.z
|
|
|
28
29
|
// Только заказы, ещё не включённые ни в один счёт на оплату — список для пикера при
|
|
29
30
|
// выставлении счёта. Комбинируется с остальными критериями обычным AND.
|
|
30
31
|
withoutPaymentInvoice: zod_1.z.coerce.boolean().optional(),
|
|
32
|
+
// То же для передаточного документа — пикер заказов при выпуске УПД. Здесь `queryBooleanSchema`,
|
|
33
|
+
// а не `z.coerce.boolean()`: в query всегда приходит текст, и `Boolean('false') === true`,
|
|
34
|
+
// то есть флаг соседа невозможно выключить явным значением, только опустив параметр.
|
|
35
|
+
withoutTransferDocument: query_boolean_helper_1.queryBooleanSchema,
|
|
31
36
|
})
|
|
32
37
|
.refine(value => {
|
|
33
38
|
const { startDate, endDate } = value;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.CreateTransferDocumentContractCommand = void 0;
|
|
4
|
+
const zod_1 = require("zod");
|
|
5
|
+
const transfer_document_detailed_schema_1 = require("../../schemas/transfer-document/transfer-document-detailed.schema");
|
|
6
|
+
// Потолок числа заказов в одном документе — защита от абсурдного запроса, а не бизнес-правило.
|
|
7
|
+
// Тот же порядок, что у счёта: сто заказов в одной отгрузке клиенту не встречаются, а документ
|
|
8
|
+
// такого размера ещё собирается и читается.
|
|
9
|
+
const MAX_TRANSFER_DOCUMENT_ORDER_COUNT = 100;
|
|
10
|
+
/**
|
|
11
|
+
* Документ выпускается по отгруженным заказам одного клиента.
|
|
12
|
+
*
|
|
13
|
+
* `documentDate` — дата составления (строка 1 формы). `shipmentDate` — дата передачи (строка [11]);
|
|
14
|
+
* не передана — берём максимальную `completedAt` из заказов, а легаси-заказу без даты её же
|
|
15
|
+
* записываем обратно, иначе заказ и документ разъедутся.
|
|
16
|
+
*/
|
|
17
|
+
const CreateTransferDocumentRequestSchema = zod_1.z.object({
|
|
18
|
+
clientUUID: zod_1.z.uuid(),
|
|
19
|
+
orderUUIDs: zod_1.z.uuid().array().min(1).max(MAX_TRANSFER_DOCUMENT_ORDER_COUNT),
|
|
20
|
+
documentDate: zod_1.z.coerce.date(),
|
|
21
|
+
shipmentDate: zod_1.z.coerce.date().optional(),
|
|
22
|
+
});
|
|
23
|
+
const CreateTransferDocumentResponseSchema = zod_1.z.object({
|
|
24
|
+
message: zod_1.z.string().optional(),
|
|
25
|
+
data: transfer_document_detailed_schema_1.TransferDocumentDetailedSchema,
|
|
26
|
+
});
|
|
27
|
+
var CreateTransferDocumentContractCommand;
|
|
28
|
+
(function (CreateTransferDocumentContractCommand) {
|
|
29
|
+
CreateTransferDocumentContractCommand.RequestSchema = CreateTransferDocumentRequestSchema;
|
|
30
|
+
CreateTransferDocumentContractCommand.ResponseSchema = CreateTransferDocumentResponseSchema;
|
|
31
|
+
})(CreateTransferDocumentContractCommand || (exports.CreateTransferDocumentContractCommand = CreateTransferDocumentContractCommand = {}));
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.DeleteTransferDocumentContractCommand = void 0;
|
|
4
|
+
const zod_1 = require("zod");
|
|
5
|
+
const query_boolean_helper_1 = require("../../helpers/query-boolean.helper");
|
|
6
|
+
/**
|
|
7
|
+
* Удаление документа. Заказы отвязываются и снова становятся редактируемыми, номер сгорает —
|
|
8
|
+
* повтор получит следующий, а не дубль к тому, что уже лежит у контрагента.
|
|
9
|
+
*
|
|
10
|
+
* `force` приходит в query-строке и нужен только для выданного (`ISSUED`) документа: без него
|
|
11
|
+
* такое удаление отклоняется, чтобы фронт успел показать предупреждение.
|
|
12
|
+
*/
|
|
13
|
+
const DeleteTransferDocumentRequestSchema = zod_1.z.object({
|
|
14
|
+
force: query_boolean_helper_1.queryBooleanSchema,
|
|
15
|
+
});
|
|
16
|
+
const DeleteTransferDocumentResponseSchema = zod_1.z.object({
|
|
17
|
+
message: zod_1.z.string().optional(),
|
|
18
|
+
data: zod_1.z.object({
|
|
19
|
+
success: zod_1.z.boolean(),
|
|
20
|
+
}),
|
|
21
|
+
});
|
|
22
|
+
var DeleteTransferDocumentContractCommand;
|
|
23
|
+
(function (DeleteTransferDocumentContractCommand) {
|
|
24
|
+
DeleteTransferDocumentContractCommand.RequestSchema = DeleteTransferDocumentRequestSchema;
|
|
25
|
+
DeleteTransferDocumentContractCommand.ResponseSchema = DeleteTransferDocumentResponseSchema;
|
|
26
|
+
})(DeleteTransferDocumentContractCommand || (exports.DeleteTransferDocumentContractCommand = DeleteTransferDocumentContractCommand = {}));
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.GetTransferDocumentListContractQuery = void 0;
|
|
4
|
+
const zod_1 = require("zod");
|
|
5
|
+
const transfer_document_schema_1 = require("../../schemas/transfer-document/transfer-document.schema");
|
|
6
|
+
const GetTransferDocumentListRequestSchema = zod_1.z.object({
|
|
7
|
+
page: zod_1.z.string().transform(value => Number(value) || 1),
|
|
8
|
+
count: zod_1.z.string().transform(value => Number(value) || 10),
|
|
9
|
+
searchQuery: zod_1.z.string().optional(),
|
|
10
|
+
clientUUID: zod_1.z.uuid().optional(),
|
|
11
|
+
});
|
|
12
|
+
const GetTransferDocumentListResponseSchema = zod_1.z.object({
|
|
13
|
+
message: zod_1.z.string().optional(),
|
|
14
|
+
data: zod_1.z.object({
|
|
15
|
+
list: transfer_document_schema_1.TransferDocumentSchema.array(),
|
|
16
|
+
total: zod_1.z.number(),
|
|
17
|
+
}),
|
|
18
|
+
});
|
|
19
|
+
var GetTransferDocumentListContractQuery;
|
|
20
|
+
(function (GetTransferDocumentListContractQuery) {
|
|
21
|
+
GetTransferDocumentListContractQuery.RequestSchema = GetTransferDocumentListRequestSchema;
|
|
22
|
+
GetTransferDocumentListContractQuery.ResponseSchema = GetTransferDocumentListResponseSchema;
|
|
23
|
+
})(GetTransferDocumentListContractQuery || (exports.GetTransferDocumentListContractQuery = GetTransferDocumentListContractQuery = {}));
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.GetTransferDocumentContractQuery = void 0;
|
|
4
|
+
const zod_1 = require("zod");
|
|
5
|
+
const transfer_document_detailed_schema_1 = require("../../schemas/transfer-document/transfer-document-detailed.schema");
|
|
6
|
+
const GetTransferDocumentRequestSchema = zod_1.z.object({});
|
|
7
|
+
const GetTransferDocumentResponseSchema = zod_1.z.object({
|
|
8
|
+
message: zod_1.z.string().optional(),
|
|
9
|
+
data: transfer_document_detailed_schema_1.TransferDocumentDetailedSchema,
|
|
10
|
+
});
|
|
11
|
+
var GetTransferDocumentContractQuery;
|
|
12
|
+
(function (GetTransferDocumentContractQuery) {
|
|
13
|
+
GetTransferDocumentContractQuery.RequestSchema = GetTransferDocumentRequestSchema;
|
|
14
|
+
GetTransferDocumentContractQuery.ResponseSchema = GetTransferDocumentResponseSchema;
|
|
15
|
+
})(GetTransferDocumentContractQuery || (exports.GetTransferDocumentContractQuery = GetTransferDocumentContractQuery = {}));
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./create-transfer-document.command"), exports);
|
|
18
|
+
__exportStar(require("./get-transfer-document.query"), exports);
|
|
19
|
+
__exportStar(require("./get-transfer-document-list.query"), exports);
|
|
20
|
+
__exportStar(require("./issue-transfer-document.command"), exports);
|
|
21
|
+
__exportStar(require("./delete-transfer-document.command"), exports);
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.IssueTransferDocumentContractCommand = void 0;
|
|
4
|
+
const zod_1 = require("zod");
|
|
5
|
+
const transfer_document_detailed_schema_1 = require("../../schemas/transfer-document/transfer-document-detailed.schema");
|
|
6
|
+
// Перевод документа в состояние ISSUED — «передан контрагенту». Дальше он удаляется только
|
|
7
|
+
// с явным подтверждением: восстановить его нельзя, а номер сгорает.
|
|
8
|
+
const IssueTransferDocumentRequestSchema = zod_1.z.object({});
|
|
9
|
+
const IssueTransferDocumentResponseSchema = zod_1.z.object({
|
|
10
|
+
message: zod_1.z.string().optional(),
|
|
11
|
+
data: transfer_document_detailed_schema_1.TransferDocumentDetailedSchema,
|
|
12
|
+
});
|
|
13
|
+
var IssueTransferDocumentContractCommand;
|
|
14
|
+
(function (IssueTransferDocumentContractCommand) {
|
|
15
|
+
IssueTransferDocumentContractCommand.RequestSchema = IssueTransferDocumentRequestSchema;
|
|
16
|
+
IssueTransferDocumentContractCommand.ResponseSchema = IssueTransferDocumentResponseSchema;
|
|
17
|
+
})(IssueTransferDocumentContractCommand || (exports.IssueTransferDocumentContractCommand = IssueTransferDocumentContractCommand = {}));
|
|
@@ -11,6 +11,7 @@ exports.ErrorI18nKey = {
|
|
|
11
11
|
mergeOrderHasWriteOffs: 'mergeOrder.hasWriteOffs',
|
|
12
12
|
mergeOrderHasDistribution: 'mergeOrder.hasDistribution',
|
|
13
13
|
mergeOrderHasPaymentInvoice: 'mergeOrder.hasPaymentInvoice',
|
|
14
|
+
mergeOrderHasTransferDocument: 'mergeOrder.hasTransferDocument',
|
|
14
15
|
mergeOrderPaymentsTransfer: 'mergeOrder.paymentsTransfer',
|
|
15
16
|
mergeOrderDeliveryMerge: 'mergeOrder.deliveryMerge',
|
|
16
17
|
mergeOrderDeliveryTransfer: 'mergeOrder.deliveryTransfer',
|
package/build/constant/error.js
CHANGED
|
@@ -395,6 +395,13 @@ exports.ERRORS = {
|
|
|
395
395
|
message: 'Order not deleted, the order is included in a payment invoice',
|
|
396
396
|
httpCode: 409,
|
|
397
397
|
},
|
|
398
|
+
// Отказ общий для удаления заказа и для вывода его из COMPLETED, поэтому формулировка
|
|
399
|
+
// без привязки к действию: «not deleted» вводило бы в заблуждение при смене статуса.
|
|
400
|
+
ORDER_IN_TRANSFER_DOCUMENT: {
|
|
401
|
+
code: 'O059',
|
|
402
|
+
message: 'The order is included in a transfer document and cannot be changed or deleted',
|
|
403
|
+
httpCode: 409,
|
|
404
|
+
},
|
|
398
405
|
ORDER_SPLIT_NOT_COMPLETELY_ERROR: { code: 'O019', message: 'Error splitting orders, not all orders were split', httpCode: 500 },
|
|
399
406
|
ORDER_TOTAL_COST_NEGATIVE: { code: 'O020', message: 'Order total cost is negative', httpCode: 400 },
|
|
400
407
|
ORDER_SUBTOTAL_NEGATIVE: { code: 'O021', message: 'Order subtotal is negative', httpCode: 400 },
|
|
@@ -409,6 +416,7 @@ exports.ERRORS = {
|
|
|
409
416
|
ORDER_MERGE_HAS_WRITE_OFFS: { code: 'O031', message: 'Order has write-offs', httpCode: 400 },
|
|
410
417
|
ORDER_MERGE_HAS_DISTRIBUTION: { code: 'O032', message: 'Order has products with distribution', httpCode: 400 },
|
|
411
418
|
ORDER_MERGE_HAS_PAYMENT_INVOICE: { code: 'O040', message: 'Order is included in a payment invoice', httpCode: 400 },
|
|
419
|
+
ORDER_MERGE_HAS_TRANSFER_DOCUMENT: { code: 'O060', message: 'Order is included in a transfer document', httpCode: 400 },
|
|
412
420
|
ORDER_MERGE_BALANCE_STATUS_NOT_ALLOWED: {
|
|
413
421
|
code: 'O033',
|
|
414
422
|
message: 'Order status is balance affecting, merge not allowed',
|
|
@@ -1451,4 +1459,49 @@ exports.ERRORS = {
|
|
|
1451
1459
|
message: 'Failed to assign cash flow item to transactions',
|
|
1452
1460
|
httpCode: 500,
|
|
1453
1461
|
},
|
|
1462
|
+
TRANSFER_DOCUMENT_CREATE_FAILED: { code: 'TDOC001', message: 'Failed to create transfer document', httpCode: 500 },
|
|
1463
|
+
TRANSFER_DOCUMENT_NOT_FOUND: { code: 'TDOC002', message: 'Transfer document not found', httpCode: 404 },
|
|
1464
|
+
TRANSFER_DOCUMENT_FETCH_FAILED: { code: 'TDOC003', message: 'Failed to fetch transfer documents', httpCode: 500 },
|
|
1465
|
+
TRANSFER_DOCUMENT_DELETE_FAILED: { code: 'TDOC004', message: 'Failed to delete transfer document', httpCode: 500 },
|
|
1466
|
+
TRANSFER_DOCUMENT_ORDERS_REQUIRED: { code: 'TDOC005', message: 'At least one order is required', httpCode: 400 },
|
|
1467
|
+
TRANSFER_DOCUMENT_ORDERS_NOT_FOUND: {
|
|
1468
|
+
code: 'TDOC006',
|
|
1469
|
+
message: 'Some of the requested orders were not found for this client',
|
|
1470
|
+
httpCode: 404,
|
|
1471
|
+
},
|
|
1472
|
+
TRANSFER_DOCUMENT_ORDER_NOT_COMPLETED: {
|
|
1473
|
+
code: 'TDOC007',
|
|
1474
|
+
message: 'A transfer document can only be issued for completed orders',
|
|
1475
|
+
httpCode: 409,
|
|
1476
|
+
},
|
|
1477
|
+
TRANSFER_DOCUMENT_ORDER_ALREADY_ISSUED: {
|
|
1478
|
+
code: 'TDOC008',
|
|
1479
|
+
message: 'Some of the requested orders are already included in another transfer document',
|
|
1480
|
+
httpCode: 409,
|
|
1481
|
+
},
|
|
1482
|
+
TRANSFER_DOCUMENT_AMOUNT_INVALID: { code: 'TDOC009', message: 'Transfer document amount must be greater than zero', httpCode: 400 },
|
|
1483
|
+
TRANSFER_DOCUMENT_EXPORT_FAILED: { code: 'TDOC010', message: 'Failed to build transfer document file', httpCode: 500 },
|
|
1484
|
+
TRANSFER_DOCUMENT_VAT_NOT_SUPPORTED: {
|
|
1485
|
+
code: 'TDOC011',
|
|
1486
|
+
message: 'Transfer documents are only issued as an act (status 2); VAT payers are not supported yet',
|
|
1487
|
+
httpCode: 409,
|
|
1488
|
+
},
|
|
1489
|
+
// Реквизиты сторон проверяем до выпуска: движок считает пустое значение штатным и напечатал бы
|
|
1490
|
+
// документ без «Продавца», ИНН и подписи — недействительный, и компания узнала бы об этом
|
|
1491
|
+
// от контрагента. `errorData` перечисляет незаполненные поля, чтобы UI назвал их поимённо.
|
|
1492
|
+
TRANSFER_DOCUMENT_SELLER_REQUISITES_MISSING: {
|
|
1493
|
+
code: 'TDOC012',
|
|
1494
|
+
message: 'Seller requisites are not filled in company settings',
|
|
1495
|
+
httpCode: 400,
|
|
1496
|
+
},
|
|
1497
|
+
TRANSFER_DOCUMENT_BUYER_REQUISITES_MISSING: {
|
|
1498
|
+
code: 'TDOC014',
|
|
1499
|
+
message: 'Buyer requisites are not filled in the client legal profile',
|
|
1500
|
+
httpCode: 400,
|
|
1501
|
+
},
|
|
1502
|
+
TRANSFER_DOCUMENT_NUMBER_START_DECREASED: {
|
|
1503
|
+
code: 'TDOC013',
|
|
1504
|
+
message: 'Transfer document number start cannot be decreased',
|
|
1505
|
+
httpCode: 400,
|
|
1506
|
+
},
|
|
1454
1507
|
};
|
package/build/constant/index.js
CHANGED
|
@@ -21,5 +21,7 @@ __exportStar(require("./import.constant"), exports);
|
|
|
21
21
|
__exportStar(require("./validation-i18n-key"), exports);
|
|
22
22
|
__exportStar(require("./validation-i18n-message"), exports);
|
|
23
23
|
__exportStar(require("./report.constant"), exports);
|
|
24
|
+
__exportStar(require("./oksm"), exports);
|
|
25
|
+
__exportStar(require("./okei"), exports);
|
|
24
26
|
__exportStar(require("./contact-phone.constant"), exports);
|
|
25
27
|
__exportStar(require("./settings.constant"), exports);
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.OKEI_BY_SALES_UNIT = void 0;
|
|
4
|
+
const sales_unit_enum_1 = require("../enum/sales-unit.enum");
|
|
5
|
+
/**
|
|
6
|
+
* ОКЕИ (ОК 015-94) — общероссийский классификатор единиц измерения. Код идёт в графу 2 УПД,
|
|
7
|
+
* условное национальное обозначение — в графу 2а.
|
|
8
|
+
*
|
|
9
|
+
* Услуги и доставка печатаются как «шт»: отдельной единицы для услуги в ОКЕИ нет, а оставлять
|
|
10
|
+
* графы пустыми при статусе 1 нельзя.
|
|
11
|
+
*/
|
|
12
|
+
exports.OKEI_BY_SALES_UNIT = {
|
|
13
|
+
[sales_unit_enum_1.SalesUnitEnum.PIECE]: { code: '796', name: 'шт' },
|
|
14
|
+
[sales_unit_enum_1.SalesUnitEnum.PACK]: { code: '778', name: 'упак' },
|
|
15
|
+
[sales_unit_enum_1.SalesUnitEnum.BOX]: { code: '812', name: 'ящик' },
|
|
16
|
+
};
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.OKSM = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* ОКСМ (ОК 025-2001) — общероссийский классификатор стран мира. Цифровой код идёт в графу 10
|
|
6
|
+
* УПД, краткое наименование — в графу 10а. Коды совпадают с ISO 3166-1 numeric.
|
|
7
|
+
*
|
|
8
|
+
* Список неполный намеренно: здесь страны происхождения, реально встречающиеся у цветочного опта,
|
|
9
|
+
* плюс основные торговые партнёры. Новая страна добавляется сюда, её написания — в OKSM_ALIAS.
|
|
10
|
+
*/
|
|
11
|
+
exports.OKSM = [
|
|
12
|
+
{ code: '643', name: 'Россия', alpha2: 'RU' },
|
|
13
|
+
{ code: '528', name: 'Нидерланды', alpha2: 'NL' },
|
|
14
|
+
{ code: '218', name: 'Эквадор', alpha2: 'EC' },
|
|
15
|
+
{ code: '170', name: 'Колумбия', alpha2: 'CO' },
|
|
16
|
+
{ code: '404', name: 'Кения', alpha2: 'KE' },
|
|
17
|
+
{ code: '231', name: 'Эфиопия', alpha2: 'ET' },
|
|
18
|
+
{ code: '834', name: 'Танзания', alpha2: 'TZ' },
|
|
19
|
+
{ code: '800', name: 'Уганда', alpha2: 'UG' },
|
|
20
|
+
{ code: '716', name: 'Зимбабве', alpha2: 'ZW' },
|
|
21
|
+
{ code: '710', name: 'Южная Африка', alpha2: 'ZA' },
|
|
22
|
+
{ code: '376', name: 'Израиль', alpha2: 'IL' },
|
|
23
|
+
{ code: '380', name: 'Италия', alpha2: 'IT' },
|
|
24
|
+
{ code: '792', name: 'Турция', alpha2: 'TR' },
|
|
25
|
+
{ code: '156', name: 'Китай', alpha2: 'CN' },
|
|
26
|
+
{ code: '764', name: 'Таиланд', alpha2: 'TH' },
|
|
27
|
+
{ code: '704', name: 'Вьетнам', alpha2: 'VN' },
|
|
28
|
+
{ code: '356', name: 'Индия', alpha2: 'IN' },
|
|
29
|
+
{ code: '144', name: 'Шри-Ланка', alpha2: 'LK' },
|
|
30
|
+
{ code: '458', name: 'Малайзия', alpha2: 'MY' },
|
|
31
|
+
{ code: '360', name: 'Индонезия', alpha2: 'ID' },
|
|
32
|
+
{ code: '188', name: 'Коста-Рика', alpha2: 'CR' },
|
|
33
|
+
{ code: '484', name: 'Мексика', alpha2: 'MX' },
|
|
34
|
+
{ code: '076', name: 'Бразилия', alpha2: 'BR' },
|
|
35
|
+
{ code: '604', name: 'Перу', alpha2: 'PE' },
|
|
36
|
+
{ code: '152', name: 'Чили', alpha2: 'CL' },
|
|
37
|
+
{ code: '840', name: 'Соединённые Штаты', alpha2: 'US' },
|
|
38
|
+
{ code: '554', name: 'Новая Зеландия', alpha2: 'NZ' },
|
|
39
|
+
{ code: '036', name: 'Австралия', alpha2: 'AU' },
|
|
40
|
+
{ code: '276', name: 'Германия', alpha2: 'DE' },
|
|
41
|
+
{ code: '616', name: 'Польша', alpha2: 'PL' },
|
|
42
|
+
{ code: '056', name: 'Бельгия', alpha2: 'BE' },
|
|
43
|
+
{ code: '250', name: 'Франция', alpha2: 'FR' },
|
|
44
|
+
{ code: '724', name: 'Испания', alpha2: 'ES' },
|
|
45
|
+
{ code: '620', name: 'Португалия', alpha2: 'PT' },
|
|
46
|
+
{ code: '208', name: 'Дания', alpha2: 'DK' },
|
|
47
|
+
{ code: '246', name: 'Финляндия', alpha2: 'FI' },
|
|
48
|
+
{ code: '752', name: 'Швеция', alpha2: 'SE' },
|
|
49
|
+
{ code: '578', name: 'Норвегия', alpha2: 'NO' },
|
|
50
|
+
{ code: '826', name: 'Соединённое Королевство', alpha2: 'GB' },
|
|
51
|
+
{ code: '756', name: 'Швейцария', alpha2: 'CH' },
|
|
52
|
+
{ code: '040', name: 'Австрия', alpha2: 'AT' },
|
|
53
|
+
{ code: '203', name: 'Чехия', alpha2: 'CZ' },
|
|
54
|
+
{ code: '440', name: 'Литва', alpha2: 'LT' },
|
|
55
|
+
{ code: '428', name: 'Латвия', alpha2: 'LV' },
|
|
56
|
+
{ code: '233', name: 'Эстония', alpha2: 'EE' },
|
|
57
|
+
{ code: '112', name: 'Беларусь', alpha2: 'BY' },
|
|
58
|
+
{ code: '398', name: 'Казахстан', alpha2: 'KZ' },
|
|
59
|
+
{ code: '860', name: 'Узбекистан', alpha2: 'UZ' },
|
|
60
|
+
{ code: '051', name: 'Армения', alpha2: 'AM' },
|
|
61
|
+
{ code: '031', name: 'Азербайджан', alpha2: 'AZ' },
|
|
62
|
+
{ code: '268', name: 'Грузия', alpha2: 'GE' },
|
|
63
|
+
{ code: '498', name: 'Молдова', alpha2: 'MD' },
|
|
64
|
+
{ code: '804', name: 'Украина', alpha2: 'UA' },
|
|
65
|
+
{ code: '818', name: 'Египет', alpha2: 'EG' },
|
|
66
|
+
{ code: '504', name: 'Марокко', alpha2: 'MA' },
|
|
67
|
+
{ code: '788', name: 'Тунис', alpha2: 'TN' },
|
|
68
|
+
{ code: '784', name: 'Объединённые Арабские Эмираты', alpha2: 'AE' },
|
|
69
|
+
{ code: '364', name: 'Иран', alpha2: 'IR' },
|
|
70
|
+
{ code: '392', name: 'Япония', alpha2: 'JP' },
|
|
71
|
+
{ code: '410', name: 'Республика Корея', alpha2: 'KR' },
|
|
72
|
+
];
|
package/build/enum/index.js
CHANGED
|
@@ -116,4 +116,8 @@ __exportStar(require("./payment-invoice-status.enum"), exports);
|
|
|
116
116
|
__exportStar(require("./order-by.enum"), exports);
|
|
117
117
|
__exportStar(require("./report-sort-by.enum"), exports);
|
|
118
118
|
__exportStar(require("./report-order-date-basis.enum"), exports);
|
|
119
|
+
__exportStar(require("./invoice-product-field.enum"), exports);
|
|
120
|
+
__exportStar(require("./transfer-document-state.enum"), exports);
|
|
121
|
+
__exportStar(require("./transfer-document-kind.enum"), exports);
|
|
122
|
+
__exportStar(require("./transfer-document-item-kind.enum"), exports);
|
|
119
123
|
__exportStar(require("./write-off-report-date-basis.enum"), exports);
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.InvoiceProductFieldEnum = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* Поля товара, из которых собирается его наименование в документах (накладная, УПД).
|
|
6
|
+
* Порядок значений в настройке = порядок элементов в строке.
|
|
7
|
+
*/
|
|
8
|
+
var InvoiceProductFieldEnum;
|
|
9
|
+
(function (InvoiceProductFieldEnum) {
|
|
10
|
+
InvoiceProductFieldEnum["CATEGORY"] = "CATEGORY";
|
|
11
|
+
InvoiceProductFieldEnum["NAME"] = "NAME";
|
|
12
|
+
InvoiceProductFieldEnum["GROWER"] = "GROWER";
|
|
13
|
+
InvoiceProductFieldEnum["SIZE"] = "SIZE";
|
|
14
|
+
InvoiceProductFieldEnum["SIZE2"] = "SIZE2";
|
|
15
|
+
InvoiceProductFieldEnum["COLOR"] = "COLOR";
|
|
16
|
+
InvoiceProductFieldEnum["COUNTRY"] = "COUNTRY";
|
|
17
|
+
InvoiceProductFieldEnum["ARTICLE"] = "ARTICLE";
|
|
18
|
+
})(InvoiceProductFieldEnum || (exports.InvoiceProductFieldEnum = InvoiceProductFieldEnum = {}));
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.TransferDocumentItemKindEnum = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* Природа строки табличной части УПД.
|
|
6
|
+
*
|
|
7
|
+
* По ней билдер понимает, где ставить прочерки в графах страны происхождения и номера ДТ:
|
|
8
|
+
* у услуги и доставки их нет.
|
|
9
|
+
*/
|
|
10
|
+
var TransferDocumentItemKindEnum;
|
|
11
|
+
(function (TransferDocumentItemKindEnum) {
|
|
12
|
+
TransferDocumentItemKindEnum["PRODUCT"] = "PRODUCT";
|
|
13
|
+
TransferDocumentItemKindEnum["SERVICE"] = "SERVICE";
|
|
14
|
+
TransferDocumentItemKindEnum["DELIVERY"] = "DELIVERY";
|
|
15
|
+
})(TransferDocumentItemKindEnum || (exports.TransferDocumentItemKindEnum = TransferDocumentItemKindEnum = {}));
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.TransferDocumentKindEnum = void 0;
|
|
4
|
+
var TransferDocumentKindEnum;
|
|
5
|
+
(function (TransferDocumentKindEnum) {
|
|
6
|
+
TransferDocumentKindEnum["PRIMARY"] = "PRIMARY";
|
|
7
|
+
TransferDocumentKindEnum["REVISION"] = "REVISION";
|
|
8
|
+
TransferDocumentKindEnum["CORRECTION"] = "CORRECTION";
|
|
9
|
+
})(TransferDocumentKindEnum || (exports.TransferDocumentKindEnum = TransferDocumentKindEnum = {}));
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.TransferDocumentStateEnum = void 0;
|
|
4
|
+
var TransferDocumentStateEnum;
|
|
5
|
+
(function (TransferDocumentStateEnum) {
|
|
6
|
+
TransferDocumentStateEnum["DRAFT"] = "DRAFT";
|
|
7
|
+
TransferDocumentStateEnum["ISSUED"] = "ISSUED";
|
|
8
|
+
})(TransferDocumentStateEnum || (exports.TransferDocumentStateEnum = TransferDocumentStateEnum = {}));
|
package/build/schemas/index.js
CHANGED
|
@@ -97,3 +97,5 @@ __exportStar(require("./money.schema"), exports);
|
|
|
97
97
|
__exportStar(require("./non-negative-money.schema"), exports);
|
|
98
98
|
__exportStar(require("./positive-money.schema"), exports);
|
|
99
99
|
__exportStar(require("./report/report-order-filter.schema"), exports);
|
|
100
|
+
__exportStar(require("./transfer-document/transfer-document.schema"), exports);
|
|
101
|
+
__exportStar(require("./transfer-document/transfer-document-detailed.schema"), exports);
|
|
@@ -36,17 +36,23 @@ exports.OrderSchema = zod_1.z.object({
|
|
|
36
36
|
// Счёт на оплату, в который включён заказ. Сам счёт (номер, файл, статус оплаты) читается
|
|
37
37
|
// отдельным запросом GET /payment-invoice/:uuid — здесь только ссылка, чтобы не утяжелять список заказов.
|
|
38
38
|
paymentInvoiceUUID: zod_1.z.uuid().nullable(),
|
|
39
|
+
// Передаточный документ (УПД), в который включён заказ. Тем же приёмом, что и счёт: здесь только
|
|
40
|
+
// ссылка, документ читается через GET /transfer-document/:uuid. Непустое значение означает, что
|
|
41
|
+
// заказ заморожен — состав, статус, доставка, дата отгрузки и скидка ему уже недоступны.
|
|
42
|
+
transferDocumentUUID: zod_1.z.uuid().nullable(),
|
|
39
43
|
completedAt: zod_1.z.date().nullable(),
|
|
40
44
|
paymentDueAt: zod_1.z.date().nullable(),
|
|
41
45
|
createdAt: zod_1.z.date(),
|
|
42
46
|
updatedAt: zod_1.z.date(),
|
|
43
47
|
deletedAt: zod_1.z.date().nullable(),
|
|
44
48
|
});
|
|
45
|
-
// Витрина клиента не показывает внутреннюю кухню
|
|
49
|
+
// Витрина клиента не показывает внутреннюю кухню документов, поэтому ссылки на счёт и на УПД
|
|
50
|
+
// сюда не попадают.
|
|
46
51
|
exports.OrderForClientSchema = exports.OrderSchema.omit({
|
|
47
52
|
comment: true,
|
|
48
53
|
tag: true,
|
|
49
54
|
paymentInvoiceUUID: true,
|
|
55
|
+
transferDocumentUUID: true,
|
|
50
56
|
});
|
|
51
57
|
exports.OrderExtendedSchema = exports.OrderSchema.extend({
|
|
52
58
|
client: client_1.ClientSchema,
|
|
@@ -97,6 +97,18 @@ exports.SettingsSchema = zod_1.z.object({
|
|
|
97
97
|
bankBic: zod_1.z.string().nullable(),
|
|
98
98
|
correspondentAccount: zod_1.z.string().nullable(),
|
|
99
99
|
invoiceNumberPrefix: zod_1.z.string(),
|
|
100
|
+
kpp: zod_1.z.string().nullable(),
|
|
101
|
+
ogrn: zod_1.z.string().nullable(),
|
|
102
|
+
signatoryName: zod_1.z.string().nullable(),
|
|
103
|
+
signatoryPosition: zod_1.z.string().nullable(),
|
|
104
|
+
accountantName: zod_1.z.string().nullable(),
|
|
105
|
+
responsibleName: zod_1.z.string().nullable(),
|
|
106
|
+
responsiblePosition: zod_1.z.string().nullable(),
|
|
107
|
+
shipperName: zod_1.z.string().nullable(),
|
|
108
|
+
shipperAddress: zod_1.z.string().nullable(),
|
|
109
|
+
transferDocumentStatus: zod_1.z.number().int().nullable(),
|
|
110
|
+
transferDocumentNumberStart: zod_1.z.number().int().positive().nullable(),
|
|
111
|
+
invoiceProductFields: zod_1.z.array(zod_1.z.nativeEnum(enum_1.InvoiceProductFieldEnum)).nullable(),
|
|
100
112
|
isShowPriceAnonymous: zod_1.z.boolean(),
|
|
101
113
|
orderExpirationWarningMin: zod_1.z.number().nullable(),
|
|
102
114
|
orderExpirationMin: zod_1.z.number().nullable(),
|
|
@@ -179,6 +191,18 @@ exports.CreateSettingsSchema = zod_1.z.object({
|
|
|
179
191
|
bankBic: zod_1.z.string().nullable().optional(),
|
|
180
192
|
correspondentAccount: zod_1.z.string().nullable().optional(),
|
|
181
193
|
invoiceNumberPrefix: zod_1.z.string().optional(),
|
|
194
|
+
kpp: zod_1.z.string().nullable().optional(),
|
|
195
|
+
ogrn: zod_1.z.string().nullable().optional(),
|
|
196
|
+
signatoryName: zod_1.z.string().nullable().optional(),
|
|
197
|
+
signatoryPosition: zod_1.z.string().nullable().optional(),
|
|
198
|
+
accountantName: zod_1.z.string().nullable().optional(),
|
|
199
|
+
responsibleName: zod_1.z.string().nullable().optional(),
|
|
200
|
+
responsiblePosition: zod_1.z.string().nullable().optional(),
|
|
201
|
+
shipperName: zod_1.z.string().nullable().optional(),
|
|
202
|
+
shipperAddress: zod_1.z.string().nullable().optional(),
|
|
203
|
+
transferDocumentStatus: zod_1.z.number().int().nullable().optional(),
|
|
204
|
+
transferDocumentNumberStart: zod_1.z.number().int().positive().nullable().optional(),
|
|
205
|
+
invoiceProductFields: zod_1.z.array(zod_1.z.nativeEnum(enum_1.InvoiceProductFieldEnum)).nullable().optional(),
|
|
182
206
|
orderExpirationWarningMin: zod_1.z.coerce.number().nullable().optional(),
|
|
183
207
|
orderExpirationMin: zod_1.z.coerce.number().nullable().optional(),
|
|
184
208
|
paymentGraceDaysAfterCompletion: zod_1.z.coerce.number().nullable().optional(),
|
|
@@ -249,6 +273,19 @@ exports.UpdateSettingsRequestSchema = zod_1.z.object({
|
|
|
249
273
|
bankBic: zod_1.z.string().optional().nullable(),
|
|
250
274
|
correspondentAccount: zod_1.z.string().optional().nullable(),
|
|
251
275
|
invoiceNumberPrefix: zod_1.z.string().optional(),
|
|
276
|
+
kpp: zod_1.z.string().optional().nullable(),
|
|
277
|
+
ogrn: zod_1.z.string().optional().nullable(),
|
|
278
|
+
signatoryName: zod_1.z.string().optional().nullable(),
|
|
279
|
+
signatoryPosition: zod_1.z.string().optional().nullable(),
|
|
280
|
+
accountantName: zod_1.z.string().optional().nullable(),
|
|
281
|
+
responsibleName: zod_1.z.string().optional().nullable(),
|
|
282
|
+
responsiblePosition: zod_1.z.string().optional().nullable(),
|
|
283
|
+
shipperName: zod_1.z.string().optional().nullable(),
|
|
284
|
+
shipperAddress: zod_1.z.string().optional().nullable(),
|
|
285
|
+
transferDocumentStatus: zod_1.z.number().int().optional().nullable(),
|
|
286
|
+
// Понижать нельзя — это дало бы дубли к уже выданным документам; проверка в обработчике.
|
|
287
|
+
transferDocumentNumberStart: zod_1.z.number().int().positive().optional().nullable(),
|
|
288
|
+
invoiceProductFields: zod_1.z.array(zod_1.z.nativeEnum(enum_1.InvoiceProductFieldEnum)).optional().nullable(),
|
|
252
289
|
isShowPriceAnonymous: zod_1.z.coerce.boolean().optional(),
|
|
253
290
|
orderExpirationWarningMin: zod_1.z.coerce.number().nullable().optional(),
|
|
254
291
|
orderExpirationMin: zod_1.z.coerce.number().nullable().optional(),
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.TransferDocumentDetailedSchema = void 0;
|
|
4
|
+
const zod_1 = require("zod");
|
|
5
|
+
const transfer_document_item_kind_enum_1 = require("../../enum/transfer-document-item-kind.enum");
|
|
6
|
+
const money_schema_1 = require("../money.schema");
|
|
7
|
+
const transfer_document_schema_1 = require("./transfer-document.schema");
|
|
8
|
+
// Строка табличной части — снимок графы в графу на момент выпуска. Значения уже готовы к печати:
|
|
9
|
+
// пересчитывать их из заказа нельзя, выданная первичка обязана воспроизводиться неизменной.
|
|
10
|
+
const TransferDocumentItemSchema = zod_1.z.object({
|
|
11
|
+
kind: zod_1.z.nativeEnum(transfer_document_item_kind_enum_1.TransferDocumentItemKindEnum),
|
|
12
|
+
orderUUID: zod_1.z.string(),
|
|
13
|
+
orderId: zod_1.z.number(),
|
|
14
|
+
// Графа А — код товара; графы 2 / 2а — код и обозначение ОКЕИ.
|
|
15
|
+
code: zod_1.z.string().nullable(),
|
|
16
|
+
name: zod_1.z.string(),
|
|
17
|
+
unitCode: zod_1.z.string().nullable(),
|
|
18
|
+
unitName: zod_1.z.string().nullable(),
|
|
19
|
+
quantity: zod_1.z.number(),
|
|
20
|
+
priceWithoutVat: money_schema_1.MoneySchema,
|
|
21
|
+
amountWithoutVat: money_schema_1.MoneySchema,
|
|
22
|
+
// null — «Без НДС»: прочерк в графе 8. Ноль значил бы «ставка есть, налог нулевой».
|
|
23
|
+
vatRate: zod_1.z.number().nullable(),
|
|
24
|
+
vatAmount: money_schema_1.MoneySchema.nullable(),
|
|
25
|
+
amountWithVat: money_schema_1.MoneySchema,
|
|
26
|
+
// Графы 10 / 10а / 11. Пусто у услуг и доставки, а также когда страну не удалось определить.
|
|
27
|
+
countryCode: zod_1.z.string().nullable(),
|
|
28
|
+
countryName: zod_1.z.string().nullable(),
|
|
29
|
+
customsDeclarationNumber: zod_1.z.string().nullable(),
|
|
30
|
+
});
|
|
31
|
+
/** Документ вместе с табличной частью — карточка и ответ на создание. */
|
|
32
|
+
exports.TransferDocumentDetailedSchema = transfer_document_schema_1.TransferDocumentSchema.extend({
|
|
33
|
+
items: TransferDocumentItemSchema.array(),
|
|
34
|
+
// Позиции, у которых не определилась страна происхождения: документ выпущен, графы 10/10а
|
|
35
|
+
// напечатаны прочерком, а UI показывает, какие карточки товара стоит поправить.
|
|
36
|
+
warnings: zod_1.z.string().array(),
|
|
37
|
+
});
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.TransferDocumentSchema = void 0;
|
|
4
|
+
const zod_1 = require("zod");
|
|
5
|
+
const transfer_document_state_enum_1 = require("../../enum/transfer-document-state.enum");
|
|
6
|
+
const money_schema_1 = require("../money.schema");
|
|
7
|
+
// Заказы, вошедшие в документ. Список короткий — документ выпускается по одной отгрузке клиенту,
|
|
8
|
+
// поэтому он есть и в строке списка: по нему UI показывает, какие заказы уже закрыты первичкой.
|
|
9
|
+
const TransferDocumentOrderSchema = zod_1.z.object({
|
|
10
|
+
orderUUID: zod_1.z.string(),
|
|
11
|
+
orderId: zod_1.z.number(),
|
|
12
|
+
completedAt: zod_1.z.coerce.date().nullable(),
|
|
13
|
+
});
|
|
14
|
+
/**
|
|
15
|
+
* Документ без табличной части — форма списка.
|
|
16
|
+
*
|
|
17
|
+
* Позиции сюда не входят намеренно: в УПД их столько же, сколько строк в заказах,
|
|
18
|
+
* и страница списка из двадцати документов везла бы тысячи строк. За позициями —
|
|
19
|
+
* `TransferDocumentDetailedSchema` на карточке.
|
|
20
|
+
*/
|
|
21
|
+
exports.TransferDocumentSchema = zod_1.z.object({
|
|
22
|
+
uuid: zod_1.z.string(),
|
|
23
|
+
// Номер с ведущими нулями — `01887`, ровно как он напечатан в документе.
|
|
24
|
+
number: zod_1.z.string(),
|
|
25
|
+
documentDate: zod_1.z.coerce.date(),
|
|
26
|
+
shipmentDate: zod_1.z.coerce.date(),
|
|
27
|
+
// 1 — счёт-фактура + передаточный документ, 2 — только передаточный документ (акт).
|
|
28
|
+
// В MVP выпускается только 2.
|
|
29
|
+
documentStatus: zod_1.z.number(),
|
|
30
|
+
state: zod_1.z.nativeEnum(transfer_document_state_enum_1.TransferDocumentStateEnum),
|
|
31
|
+
amount: money_schema_1.MoneySchema,
|
|
32
|
+
amountWithoutVat: money_schema_1.MoneySchema,
|
|
33
|
+
vatAmount: money_schema_1.MoneySchema,
|
|
34
|
+
clientUUID: zod_1.z.string(),
|
|
35
|
+
// Имя покупателя, напечатанное в документе (строка 6 формы). Может отличаться от текущего
|
|
36
|
+
// имени в карточке клиента: у юрлица печатается `fullCompanyName`, а карточку с тех пор
|
|
37
|
+
// могли переименовать. Список называет контрагента так же, как переданная ему бумага.
|
|
38
|
+
buyerName: zod_1.z.string(),
|
|
39
|
+
orders: TransferDocumentOrderSchema.array(),
|
|
40
|
+
fileUrl: zod_1.z.string().nullable(),
|
|
41
|
+
createdAt: zod_1.z.coerce.date(),
|
|
42
|
+
});
|
package/commands/index.ts
CHANGED
|
@@ -60,3 +60,4 @@ export { ValidateSessionS2SContractQuery } from './session/validate-session-s2s.
|
|
|
60
60
|
export { CreateWsTicketContractCommand } from './session/create-ws-ticket.command';
|
|
61
61
|
export { ValidateWsTicketS2SContractQuery } from './session/validate-ws-ticket-s2s.query';
|
|
62
62
|
export * from './consignment-transfer';
|
|
63
|
+
export * from './transfer-document';
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
import { OrderExtendedSchema } from '../../schemas';
|
|
3
3
|
import { dateRangeCheck } from '../../helpers/date.helper';
|
|
4
|
+
import { queryBooleanSchema } from '../../helpers/query-boolean.helper';
|
|
4
5
|
import { OrderStatusEnum, OrderTypeEnum } from '../../enum';
|
|
5
6
|
|
|
6
7
|
const GetOrderListRequestSchema = z
|
|
@@ -26,6 +27,10 @@ const GetOrderListRequestSchema = z
|
|
|
26
27
|
// Только заказы, ещё не включённые ни в один счёт на оплату — список для пикера при
|
|
27
28
|
// выставлении счёта. Комбинируется с остальными критериями обычным AND.
|
|
28
29
|
withoutPaymentInvoice: z.coerce.boolean().optional(),
|
|
30
|
+
// То же для передаточного документа — пикер заказов при выпуске УПД. Здесь `queryBooleanSchema`,
|
|
31
|
+
// а не `z.coerce.boolean()`: в query всегда приходит текст, и `Boolean('false') === true`,
|
|
32
|
+
// то есть флаг соседа невозможно выключить явным значением, только опустив параметр.
|
|
33
|
+
withoutTransferDocument: queryBooleanSchema,
|
|
29
34
|
})
|
|
30
35
|
.refine(
|
|
31
36
|
value => {
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { TransferDocumentDetailedSchema } from '../../schemas/transfer-document/transfer-document-detailed.schema';
|
|
3
|
+
|
|
4
|
+
// Потолок числа заказов в одном документе — защита от абсурдного запроса, а не бизнес-правило.
|
|
5
|
+
// Тот же порядок, что у счёта: сто заказов в одной отгрузке клиенту не встречаются, а документ
|
|
6
|
+
// такого размера ещё собирается и читается.
|
|
7
|
+
const MAX_TRANSFER_DOCUMENT_ORDER_COUNT = 100;
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Документ выпускается по отгруженным заказам одного клиента.
|
|
11
|
+
*
|
|
12
|
+
* `documentDate` — дата составления (строка 1 формы). `shipmentDate` — дата передачи (строка [11]);
|
|
13
|
+
* не передана — берём максимальную `completedAt` из заказов, а легаси-заказу без даты её же
|
|
14
|
+
* записываем обратно, иначе заказ и документ разъедутся.
|
|
15
|
+
*/
|
|
16
|
+
const CreateTransferDocumentRequestSchema = z.object({
|
|
17
|
+
clientUUID: z.uuid(),
|
|
18
|
+
orderUUIDs: z.uuid().array().min(1).max(MAX_TRANSFER_DOCUMENT_ORDER_COUNT),
|
|
19
|
+
documentDate: z.coerce.date(),
|
|
20
|
+
shipmentDate: z.coerce.date().optional(),
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
const CreateTransferDocumentResponseSchema = z.object({
|
|
24
|
+
message: z.string().optional(),
|
|
25
|
+
data: TransferDocumentDetailedSchema,
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
export namespace CreateTransferDocumentContractCommand {
|
|
29
|
+
export const RequestSchema = CreateTransferDocumentRequestSchema;
|
|
30
|
+
export type Request = z.infer<typeof RequestSchema>;
|
|
31
|
+
|
|
32
|
+
export const ResponseSchema = CreateTransferDocumentResponseSchema;
|
|
33
|
+
export type Response = z.infer<typeof ResponseSchema>;
|
|
34
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { queryBooleanSchema } from '../../helpers/query-boolean.helper';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Удаление документа. Заказы отвязываются и снова становятся редактируемыми, номер сгорает —
|
|
6
|
+
* повтор получит следующий, а не дубль к тому, что уже лежит у контрагента.
|
|
7
|
+
*
|
|
8
|
+
* `force` приходит в query-строке и нужен только для выданного (`ISSUED`) документа: без него
|
|
9
|
+
* такое удаление отклоняется, чтобы фронт успел показать предупреждение.
|
|
10
|
+
*/
|
|
11
|
+
const DeleteTransferDocumentRequestSchema = z.object({
|
|
12
|
+
force: queryBooleanSchema,
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
const DeleteTransferDocumentResponseSchema = z.object({
|
|
16
|
+
message: z.string().optional(),
|
|
17
|
+
data: z.object({
|
|
18
|
+
success: z.boolean(),
|
|
19
|
+
}),
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
export namespace DeleteTransferDocumentContractCommand {
|
|
23
|
+
export const RequestSchema = DeleteTransferDocumentRequestSchema;
|
|
24
|
+
export type Request = z.infer<typeof RequestSchema>;
|
|
25
|
+
|
|
26
|
+
export const ResponseSchema = DeleteTransferDocumentResponseSchema;
|
|
27
|
+
export type Response = z.infer<typeof ResponseSchema>;
|
|
28
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { TransferDocumentSchema } from '../../schemas/transfer-document/transfer-document.schema';
|
|
3
|
+
|
|
4
|
+
const GetTransferDocumentListRequestSchema = z.object({
|
|
5
|
+
page: z.string().transform(value => Number(value) || 1),
|
|
6
|
+
count: z.string().transform(value => Number(value) || 10),
|
|
7
|
+
searchQuery: z.string().optional(),
|
|
8
|
+
clientUUID: z.uuid().optional(),
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
const GetTransferDocumentListResponseSchema = z.object({
|
|
12
|
+
message: z.string().optional(),
|
|
13
|
+
data: z.object({
|
|
14
|
+
list: TransferDocumentSchema.array(),
|
|
15
|
+
total: z.number(),
|
|
16
|
+
}),
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
export namespace GetTransferDocumentListContractQuery {
|
|
20
|
+
export const RequestSchema = GetTransferDocumentListRequestSchema;
|
|
21
|
+
export type Request = z.infer<typeof RequestSchema>;
|
|
22
|
+
|
|
23
|
+
export const ResponseSchema = GetTransferDocumentListResponseSchema;
|
|
24
|
+
export type Response = z.infer<typeof ResponseSchema>;
|
|
25
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { TransferDocumentDetailedSchema } from '../../schemas/transfer-document/transfer-document-detailed.schema';
|
|
3
|
+
|
|
4
|
+
const GetTransferDocumentRequestSchema = z.object({});
|
|
5
|
+
|
|
6
|
+
const GetTransferDocumentResponseSchema = z.object({
|
|
7
|
+
message: z.string().optional(),
|
|
8
|
+
data: TransferDocumentDetailedSchema,
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
export namespace GetTransferDocumentContractQuery {
|
|
12
|
+
export const RequestSchema = GetTransferDocumentRequestSchema;
|
|
13
|
+
export type Request = z.infer<typeof RequestSchema>;
|
|
14
|
+
|
|
15
|
+
export const ResponseSchema = GetTransferDocumentResponseSchema;
|
|
16
|
+
export type Response = z.infer<typeof ResponseSchema>;
|
|
17
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { TransferDocumentDetailedSchema } from '../../schemas/transfer-document/transfer-document-detailed.schema';
|
|
3
|
+
|
|
4
|
+
// Перевод документа в состояние ISSUED — «передан контрагенту». Дальше он удаляется только
|
|
5
|
+
// с явным подтверждением: восстановить его нельзя, а номер сгорает.
|
|
6
|
+
const IssueTransferDocumentRequestSchema = z.object({});
|
|
7
|
+
|
|
8
|
+
const IssueTransferDocumentResponseSchema = z.object({
|
|
9
|
+
message: z.string().optional(),
|
|
10
|
+
data: TransferDocumentDetailedSchema,
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
export namespace IssueTransferDocumentContractCommand {
|
|
14
|
+
export const RequestSchema = IssueTransferDocumentRequestSchema;
|
|
15
|
+
export type Request = z.infer<typeof RequestSchema>;
|
|
16
|
+
|
|
17
|
+
export const ResponseSchema = IssueTransferDocumentResponseSchema;
|
|
18
|
+
export type Response = z.infer<typeof ResponseSchema>;
|
|
19
|
+
}
|
|
@@ -8,6 +8,7 @@ export const ErrorI18nKey = {
|
|
|
8
8
|
mergeOrderHasWriteOffs: 'mergeOrder.hasWriteOffs',
|
|
9
9
|
mergeOrderHasDistribution: 'mergeOrder.hasDistribution',
|
|
10
10
|
mergeOrderHasPaymentInvoice: 'mergeOrder.hasPaymentInvoice',
|
|
11
|
+
mergeOrderHasTransferDocument: 'mergeOrder.hasTransferDocument',
|
|
11
12
|
mergeOrderPaymentsTransfer: 'mergeOrder.paymentsTransfer',
|
|
12
13
|
mergeOrderDeliveryMerge: 'mergeOrder.deliveryMerge',
|
|
13
14
|
mergeOrderDeliveryTransfer: 'mergeOrder.deliveryTransfer',
|
package/constant/error.ts
CHANGED
|
@@ -409,6 +409,13 @@ export const ERRORS = {
|
|
|
409
409
|
message: 'Order not deleted, the order is included in a payment invoice',
|
|
410
410
|
httpCode: 409,
|
|
411
411
|
},
|
|
412
|
+
// Отказ общий для удаления заказа и для вывода его из COMPLETED, поэтому формулировка
|
|
413
|
+
// без привязки к действию: «not deleted» вводило бы в заблуждение при смене статуса.
|
|
414
|
+
ORDER_IN_TRANSFER_DOCUMENT: {
|
|
415
|
+
code: 'O059',
|
|
416
|
+
message: 'The order is included in a transfer document and cannot be changed or deleted',
|
|
417
|
+
httpCode: 409,
|
|
418
|
+
},
|
|
412
419
|
ORDER_SPLIT_NOT_COMPLETELY_ERROR: { code: 'O019', message: 'Error splitting orders, not all orders were split', httpCode: 500 },
|
|
413
420
|
ORDER_TOTAL_COST_NEGATIVE: { code: 'O020', message: 'Order total cost is negative', httpCode: 400 },
|
|
414
421
|
ORDER_SUBTOTAL_NEGATIVE: { code: 'O021', message: 'Order subtotal is negative', httpCode: 400 },
|
|
@@ -423,6 +430,7 @@ export const ERRORS = {
|
|
|
423
430
|
ORDER_MERGE_HAS_WRITE_OFFS: { code: 'O031', message: 'Order has write-offs', httpCode: 400 },
|
|
424
431
|
ORDER_MERGE_HAS_DISTRIBUTION: { code: 'O032', message: 'Order has products with distribution', httpCode: 400 },
|
|
425
432
|
ORDER_MERGE_HAS_PAYMENT_INVOICE: { code: 'O040', message: 'Order is included in a payment invoice', httpCode: 400 },
|
|
433
|
+
ORDER_MERGE_HAS_TRANSFER_DOCUMENT: { code: 'O060', message: 'Order is included in a transfer document', httpCode: 400 },
|
|
426
434
|
ORDER_MERGE_BALANCE_STATUS_NOT_ALLOWED: {
|
|
427
435
|
code: 'O033',
|
|
428
436
|
message: 'Order status is balance affecting, merge not allowed',
|
|
@@ -1519,4 +1527,49 @@ export const ERRORS = {
|
|
|
1519
1527
|
message: 'Failed to assign cash flow item to transactions',
|
|
1520
1528
|
httpCode: 500,
|
|
1521
1529
|
},
|
|
1530
|
+
TRANSFER_DOCUMENT_CREATE_FAILED: { code: 'TDOC001', message: 'Failed to create transfer document', httpCode: 500 },
|
|
1531
|
+
TRANSFER_DOCUMENT_NOT_FOUND: { code: 'TDOC002', message: 'Transfer document not found', httpCode: 404 },
|
|
1532
|
+
TRANSFER_DOCUMENT_FETCH_FAILED: { code: 'TDOC003', message: 'Failed to fetch transfer documents', httpCode: 500 },
|
|
1533
|
+
TRANSFER_DOCUMENT_DELETE_FAILED: { code: 'TDOC004', message: 'Failed to delete transfer document', httpCode: 500 },
|
|
1534
|
+
TRANSFER_DOCUMENT_ORDERS_REQUIRED: { code: 'TDOC005', message: 'At least one order is required', httpCode: 400 },
|
|
1535
|
+
TRANSFER_DOCUMENT_ORDERS_NOT_FOUND: {
|
|
1536
|
+
code: 'TDOC006',
|
|
1537
|
+
message: 'Some of the requested orders were not found for this client',
|
|
1538
|
+
httpCode: 404,
|
|
1539
|
+
},
|
|
1540
|
+
TRANSFER_DOCUMENT_ORDER_NOT_COMPLETED: {
|
|
1541
|
+
code: 'TDOC007',
|
|
1542
|
+
message: 'A transfer document can only be issued for completed orders',
|
|
1543
|
+
httpCode: 409,
|
|
1544
|
+
},
|
|
1545
|
+
TRANSFER_DOCUMENT_ORDER_ALREADY_ISSUED: {
|
|
1546
|
+
code: 'TDOC008',
|
|
1547
|
+
message: 'Some of the requested orders are already included in another transfer document',
|
|
1548
|
+
httpCode: 409,
|
|
1549
|
+
},
|
|
1550
|
+
TRANSFER_DOCUMENT_AMOUNT_INVALID: { code: 'TDOC009', message: 'Transfer document amount must be greater than zero', httpCode: 400 },
|
|
1551
|
+
TRANSFER_DOCUMENT_EXPORT_FAILED: { code: 'TDOC010', message: 'Failed to build transfer document file', httpCode: 500 },
|
|
1552
|
+
TRANSFER_DOCUMENT_VAT_NOT_SUPPORTED: {
|
|
1553
|
+
code: 'TDOC011',
|
|
1554
|
+
message: 'Transfer documents are only issued as an act (status 2); VAT payers are not supported yet',
|
|
1555
|
+
httpCode: 409,
|
|
1556
|
+
},
|
|
1557
|
+
// Реквизиты сторон проверяем до выпуска: движок считает пустое значение штатным и напечатал бы
|
|
1558
|
+
// документ без «Продавца», ИНН и подписи — недействительный, и компания узнала бы об этом
|
|
1559
|
+
// от контрагента. `errorData` перечисляет незаполненные поля, чтобы UI назвал их поимённо.
|
|
1560
|
+
TRANSFER_DOCUMENT_SELLER_REQUISITES_MISSING: {
|
|
1561
|
+
code: 'TDOC012',
|
|
1562
|
+
message: 'Seller requisites are not filled in company settings',
|
|
1563
|
+
httpCode: 400,
|
|
1564
|
+
},
|
|
1565
|
+
TRANSFER_DOCUMENT_BUYER_REQUISITES_MISSING: {
|
|
1566
|
+
code: 'TDOC014',
|
|
1567
|
+
message: 'Buyer requisites are not filled in the client legal profile',
|
|
1568
|
+
httpCode: 400,
|
|
1569
|
+
},
|
|
1570
|
+
TRANSFER_DOCUMENT_NUMBER_START_DECREASED: {
|
|
1571
|
+
code: 'TDOC013',
|
|
1572
|
+
message: 'Transfer document number start cannot be decreased',
|
|
1573
|
+
httpCode: 400,
|
|
1574
|
+
},
|
|
1522
1575
|
} as const;
|
package/constant/index.ts
CHANGED
|
@@ -5,5 +5,7 @@ export * from './import.constant';
|
|
|
5
5
|
export * from './validation-i18n-key';
|
|
6
6
|
export * from './validation-i18n-message';
|
|
7
7
|
export * from './report.constant';
|
|
8
|
+
export * from './oksm';
|
|
9
|
+
export * from './okei';
|
|
8
10
|
export * from './contact-phone.constant';
|
|
9
11
|
export * from './settings.constant';
|
package/constant/okei.ts
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { SalesUnitEnum } from '../enum/sales-unit.enum';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* ОКЕИ (ОК 015-94) — общероссийский классификатор единиц измерения. Код идёт в графу 2 УПД,
|
|
5
|
+
* условное национальное обозначение — в графу 2а.
|
|
6
|
+
*
|
|
7
|
+
* Услуги и доставка печатаются как «шт»: отдельной единицы для услуги в ОКЕИ нет, а оставлять
|
|
8
|
+
* графы пустыми при статусе 1 нельзя.
|
|
9
|
+
*/
|
|
10
|
+
export const OKEI_BY_SALES_UNIT: Readonly<Record<SalesUnitEnum, { code: string; name: string }>> = {
|
|
11
|
+
[SalesUnitEnum.PIECE]: { code: '796', name: 'шт' },
|
|
12
|
+
[SalesUnitEnum.PACK]: { code: '778', name: 'упак' },
|
|
13
|
+
[SalesUnitEnum.BOX]: { code: '812', name: 'ящик' },
|
|
14
|
+
};
|
package/constant/oksm.ts
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ОКСМ (ОК 025-2001) — общероссийский классификатор стран мира. Цифровой код идёт в графу 10
|
|
3
|
+
* УПД, краткое наименование — в графу 10а. Коды совпадают с ISO 3166-1 numeric.
|
|
4
|
+
*
|
|
5
|
+
* Список неполный намеренно: здесь страны происхождения, реально встречающиеся у цветочного опта,
|
|
6
|
+
* плюс основные торговые партнёры. Новая страна добавляется сюда, её написания — в OKSM_ALIAS.
|
|
7
|
+
*/
|
|
8
|
+
export const OKSM = [
|
|
9
|
+
{ code: '643', name: 'Россия', alpha2: 'RU' },
|
|
10
|
+
{ code: '528', name: 'Нидерланды', alpha2: 'NL' },
|
|
11
|
+
{ code: '218', name: 'Эквадор', alpha2: 'EC' },
|
|
12
|
+
{ code: '170', name: 'Колумбия', alpha2: 'CO' },
|
|
13
|
+
{ code: '404', name: 'Кения', alpha2: 'KE' },
|
|
14
|
+
{ code: '231', name: 'Эфиопия', alpha2: 'ET' },
|
|
15
|
+
{ code: '834', name: 'Танзания', alpha2: 'TZ' },
|
|
16
|
+
{ code: '800', name: 'Уганда', alpha2: 'UG' },
|
|
17
|
+
{ code: '716', name: 'Зимбабве', alpha2: 'ZW' },
|
|
18
|
+
{ code: '710', name: 'Южная Африка', alpha2: 'ZA' },
|
|
19
|
+
{ code: '376', name: 'Израиль', alpha2: 'IL' },
|
|
20
|
+
{ code: '380', name: 'Италия', alpha2: 'IT' },
|
|
21
|
+
{ code: '792', name: 'Турция', alpha2: 'TR' },
|
|
22
|
+
{ code: '156', name: 'Китай', alpha2: 'CN' },
|
|
23
|
+
{ code: '764', name: 'Таиланд', alpha2: 'TH' },
|
|
24
|
+
{ code: '704', name: 'Вьетнам', alpha2: 'VN' },
|
|
25
|
+
{ code: '356', name: 'Индия', alpha2: 'IN' },
|
|
26
|
+
{ code: '144', name: 'Шри-Ланка', alpha2: 'LK' },
|
|
27
|
+
{ code: '458', name: 'Малайзия', alpha2: 'MY' },
|
|
28
|
+
{ code: '360', name: 'Индонезия', alpha2: 'ID' },
|
|
29
|
+
{ code: '188', name: 'Коста-Рика', alpha2: 'CR' },
|
|
30
|
+
{ code: '484', name: 'Мексика', alpha2: 'MX' },
|
|
31
|
+
{ code: '076', name: 'Бразилия', alpha2: 'BR' },
|
|
32
|
+
{ code: '604', name: 'Перу', alpha2: 'PE' },
|
|
33
|
+
{ code: '152', name: 'Чили', alpha2: 'CL' },
|
|
34
|
+
{ code: '840', name: 'Соединённые Штаты', alpha2: 'US' },
|
|
35
|
+
{ code: '554', name: 'Новая Зеландия', alpha2: 'NZ' },
|
|
36
|
+
{ code: '036', name: 'Австралия', alpha2: 'AU' },
|
|
37
|
+
{ code: '276', name: 'Германия', alpha2: 'DE' },
|
|
38
|
+
{ code: '616', name: 'Польша', alpha2: 'PL' },
|
|
39
|
+
{ code: '056', name: 'Бельгия', alpha2: 'BE' },
|
|
40
|
+
{ code: '250', name: 'Франция', alpha2: 'FR' },
|
|
41
|
+
{ code: '724', name: 'Испания', alpha2: 'ES' },
|
|
42
|
+
{ code: '620', name: 'Португалия', alpha2: 'PT' },
|
|
43
|
+
{ code: '208', name: 'Дания', alpha2: 'DK' },
|
|
44
|
+
{ code: '246', name: 'Финляндия', alpha2: 'FI' },
|
|
45
|
+
{ code: '752', name: 'Швеция', alpha2: 'SE' },
|
|
46
|
+
{ code: '578', name: 'Норвегия', alpha2: 'NO' },
|
|
47
|
+
{ code: '826', name: 'Соединённое Королевство', alpha2: 'GB' },
|
|
48
|
+
{ code: '756', name: 'Швейцария', alpha2: 'CH' },
|
|
49
|
+
{ code: '040', name: 'Австрия', alpha2: 'AT' },
|
|
50
|
+
{ code: '203', name: 'Чехия', alpha2: 'CZ' },
|
|
51
|
+
{ code: '440', name: 'Литва', alpha2: 'LT' },
|
|
52
|
+
{ code: '428', name: 'Латвия', alpha2: 'LV' },
|
|
53
|
+
{ code: '233', name: 'Эстония', alpha2: 'EE' },
|
|
54
|
+
{ code: '112', name: 'Беларусь', alpha2: 'BY' },
|
|
55
|
+
{ code: '398', name: 'Казахстан', alpha2: 'KZ' },
|
|
56
|
+
{ code: '860', name: 'Узбекистан', alpha2: 'UZ' },
|
|
57
|
+
{ code: '051', name: 'Армения', alpha2: 'AM' },
|
|
58
|
+
{ code: '031', name: 'Азербайджан', alpha2: 'AZ' },
|
|
59
|
+
{ code: '268', name: 'Грузия', alpha2: 'GE' },
|
|
60
|
+
{ code: '498', name: 'Молдова', alpha2: 'MD' },
|
|
61
|
+
{ code: '804', name: 'Украина', alpha2: 'UA' },
|
|
62
|
+
{ code: '818', name: 'Египет', alpha2: 'EG' },
|
|
63
|
+
{ code: '504', name: 'Марокко', alpha2: 'MA' },
|
|
64
|
+
{ code: '788', name: 'Тунис', alpha2: 'TN' },
|
|
65
|
+
{ code: '784', name: 'Объединённые Арабские Эмираты', alpha2: 'AE' },
|
|
66
|
+
{ code: '364', name: 'Иран', alpha2: 'IR' },
|
|
67
|
+
{ code: '392', name: 'Япония', alpha2: 'JP' },
|
|
68
|
+
{ code: '410', name: 'Республика Корея', alpha2: 'KR' },
|
|
69
|
+
] as const;
|
package/enum/index.ts
CHANGED
|
@@ -100,4 +100,8 @@ export * from './payment-invoice-status.enum';
|
|
|
100
100
|
export * from './order-by.enum';
|
|
101
101
|
export * from './report-sort-by.enum';
|
|
102
102
|
export * from './report-order-date-basis.enum';
|
|
103
|
+
export * from './invoice-product-field.enum';
|
|
104
|
+
export * from './transfer-document-state.enum';
|
|
105
|
+
export * from './transfer-document-kind.enum';
|
|
106
|
+
export * from './transfer-document-item-kind.enum';
|
|
103
107
|
export * from './write-off-report-date-basis.enum';
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Поля товара, из которых собирается его наименование в документах (накладная, УПД).
|
|
3
|
+
* Порядок значений в настройке = порядок элементов в строке.
|
|
4
|
+
*/
|
|
5
|
+
export enum InvoiceProductFieldEnum {
|
|
6
|
+
CATEGORY = 'CATEGORY',
|
|
7
|
+
NAME = 'NAME',
|
|
8
|
+
GROWER = 'GROWER',
|
|
9
|
+
SIZE = 'SIZE',
|
|
10
|
+
SIZE2 = 'SIZE2',
|
|
11
|
+
COLOR = 'COLOR',
|
|
12
|
+
COUNTRY = 'COUNTRY',
|
|
13
|
+
ARTICLE = 'ARTICLE',
|
|
14
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Природа строки табличной части УПД.
|
|
3
|
+
*
|
|
4
|
+
* По ней билдер понимает, где ставить прочерки в графах страны происхождения и номера ДТ:
|
|
5
|
+
* у услуги и доставки их нет.
|
|
6
|
+
*/
|
|
7
|
+
export enum TransferDocumentItemKindEnum {
|
|
8
|
+
PRODUCT = 'PRODUCT',
|
|
9
|
+
SERVICE = 'SERVICE',
|
|
10
|
+
DELIVERY = 'DELIVERY',
|
|
11
|
+
}
|
package/package.json
CHANGED
package/schemas/index.ts
CHANGED
|
@@ -81,3 +81,5 @@ export * from './money.schema';
|
|
|
81
81
|
export * from './non-negative-money.schema';
|
|
82
82
|
export * from './positive-money.schema';
|
|
83
83
|
export * from './report/report-order-filter.schema';
|
|
84
|
+
export * from './transfer-document/transfer-document.schema';
|
|
85
|
+
export * from './transfer-document/transfer-document-detailed.schema';
|
|
@@ -38,6 +38,10 @@ export const OrderSchema = z.object({
|
|
|
38
38
|
// Счёт на оплату, в который включён заказ. Сам счёт (номер, файл, статус оплаты) читается
|
|
39
39
|
// отдельным запросом GET /payment-invoice/:uuid — здесь только ссылка, чтобы не утяжелять список заказов.
|
|
40
40
|
paymentInvoiceUUID: z.uuid().nullable(),
|
|
41
|
+
// Передаточный документ (УПД), в который включён заказ. Тем же приёмом, что и счёт: здесь только
|
|
42
|
+
// ссылка, документ читается через GET /transfer-document/:uuid. Непустое значение означает, что
|
|
43
|
+
// заказ заморожен — состав, статус, доставка, дата отгрузки и скидка ему уже недоступны.
|
|
44
|
+
transferDocumentUUID: z.uuid().nullable(),
|
|
41
45
|
|
|
42
46
|
completedAt: z.date().nullable(),
|
|
43
47
|
paymentDueAt: z.date().nullable(),
|
|
@@ -47,11 +51,13 @@ export const OrderSchema = z.object({
|
|
|
47
51
|
deletedAt: z.date().nullable(),
|
|
48
52
|
});
|
|
49
53
|
|
|
50
|
-
// Витрина клиента не показывает внутреннюю кухню
|
|
54
|
+
// Витрина клиента не показывает внутреннюю кухню документов, поэтому ссылки на счёт и на УПД
|
|
55
|
+
// сюда не попадают.
|
|
51
56
|
export const OrderForClientSchema = OrderSchema.omit({
|
|
52
57
|
comment: true,
|
|
53
58
|
tag: true,
|
|
54
59
|
paymentInvoiceUUID: true,
|
|
60
|
+
transferDocumentUUID: true,
|
|
55
61
|
});
|
|
56
62
|
|
|
57
63
|
export const OrderExtendedSchema = OrderSchema.extend({
|
|
@@ -4,6 +4,7 @@ import {
|
|
|
4
4
|
ChatNoManagerModeEnum,
|
|
5
5
|
ContactMessengerEnum,
|
|
6
6
|
DiscountPriceRoundingEnum,
|
|
7
|
+
InvoiceProductFieldEnum,
|
|
7
8
|
LanguageEnum,
|
|
8
9
|
WebshopModeEnum,
|
|
9
10
|
} from '../../enum';
|
|
@@ -117,6 +118,18 @@ export const SettingsSchema = z.object({
|
|
|
117
118
|
bankBic: z.string().nullable(),
|
|
118
119
|
correspondentAccount: z.string().nullable(),
|
|
119
120
|
invoiceNumberPrefix: z.string(),
|
|
121
|
+
kpp: z.string().nullable(),
|
|
122
|
+
ogrn: z.string().nullable(),
|
|
123
|
+
signatoryName: z.string().nullable(),
|
|
124
|
+
signatoryPosition: z.string().nullable(),
|
|
125
|
+
accountantName: z.string().nullable(),
|
|
126
|
+
responsibleName: z.string().nullable(),
|
|
127
|
+
responsiblePosition: z.string().nullable(),
|
|
128
|
+
shipperName: z.string().nullable(),
|
|
129
|
+
shipperAddress: z.string().nullable(),
|
|
130
|
+
transferDocumentStatus: z.number().int().nullable(),
|
|
131
|
+
transferDocumentNumberStart: z.number().int().positive().nullable(),
|
|
132
|
+
invoiceProductFields: z.array(z.nativeEnum(InvoiceProductFieldEnum)).nullable(),
|
|
120
133
|
isShowPriceAnonymous: z.boolean(),
|
|
121
134
|
orderExpirationWarningMin: z.number().nullable(),
|
|
122
135
|
orderExpirationMin: z.number().nullable(),
|
|
@@ -201,6 +214,18 @@ export const CreateSettingsSchema = z.object({
|
|
|
201
214
|
bankBic: z.string().nullable().optional(),
|
|
202
215
|
correspondentAccount: z.string().nullable().optional(),
|
|
203
216
|
invoiceNumberPrefix: z.string().optional(),
|
|
217
|
+
kpp: z.string().nullable().optional(),
|
|
218
|
+
ogrn: z.string().nullable().optional(),
|
|
219
|
+
signatoryName: z.string().nullable().optional(),
|
|
220
|
+
signatoryPosition: z.string().nullable().optional(),
|
|
221
|
+
accountantName: z.string().nullable().optional(),
|
|
222
|
+
responsibleName: z.string().nullable().optional(),
|
|
223
|
+
responsiblePosition: z.string().nullable().optional(),
|
|
224
|
+
shipperName: z.string().nullable().optional(),
|
|
225
|
+
shipperAddress: z.string().nullable().optional(),
|
|
226
|
+
transferDocumentStatus: z.number().int().nullable().optional(),
|
|
227
|
+
transferDocumentNumberStart: z.number().int().positive().nullable().optional(),
|
|
228
|
+
invoiceProductFields: z.array(z.nativeEnum(InvoiceProductFieldEnum)).nullable().optional(),
|
|
204
229
|
orderExpirationWarningMin: z.coerce.number().nullable().optional(),
|
|
205
230
|
orderExpirationMin: z.coerce.number().nullable().optional(),
|
|
206
231
|
paymentGraceDaysAfterCompletion: z.coerce.number().nullable().optional(),
|
|
@@ -274,6 +299,19 @@ export const UpdateSettingsRequestSchema = z.object({
|
|
|
274
299
|
bankBic: z.string().optional().nullable(),
|
|
275
300
|
correspondentAccount: z.string().optional().nullable(),
|
|
276
301
|
invoiceNumberPrefix: z.string().optional(),
|
|
302
|
+
kpp: z.string().optional().nullable(),
|
|
303
|
+
ogrn: z.string().optional().nullable(),
|
|
304
|
+
signatoryName: z.string().optional().nullable(),
|
|
305
|
+
signatoryPosition: z.string().optional().nullable(),
|
|
306
|
+
accountantName: z.string().optional().nullable(),
|
|
307
|
+
responsibleName: z.string().optional().nullable(),
|
|
308
|
+
responsiblePosition: z.string().optional().nullable(),
|
|
309
|
+
shipperName: z.string().optional().nullable(),
|
|
310
|
+
shipperAddress: z.string().optional().nullable(),
|
|
311
|
+
transferDocumentStatus: z.number().int().optional().nullable(),
|
|
312
|
+
// Понижать нельзя — это дало бы дубли к уже выданным документам; проверка в обработчике.
|
|
313
|
+
transferDocumentNumberStart: z.number().int().positive().optional().nullable(),
|
|
314
|
+
invoiceProductFields: z.array(z.nativeEnum(InvoiceProductFieldEnum)).optional().nullable(),
|
|
277
315
|
isShowPriceAnonymous: z.coerce.boolean().optional(),
|
|
278
316
|
orderExpirationWarningMin: z.coerce.number().nullable().optional(),
|
|
279
317
|
orderExpirationMin: z.coerce.number().nullable().optional(),
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { TransferDocumentItemKindEnum } from '../../enum/transfer-document-item-kind.enum';
|
|
3
|
+
import { MoneySchema } from '../money.schema';
|
|
4
|
+
import { TransferDocumentSchema } from './transfer-document.schema';
|
|
5
|
+
|
|
6
|
+
// Строка табличной части — снимок графы в графу на момент выпуска. Значения уже готовы к печати:
|
|
7
|
+
// пересчитывать их из заказа нельзя, выданная первичка обязана воспроизводиться неизменной.
|
|
8
|
+
const TransferDocumentItemSchema = z.object({
|
|
9
|
+
kind: z.nativeEnum(TransferDocumentItemKindEnum),
|
|
10
|
+
orderUUID: z.string(),
|
|
11
|
+
orderId: z.number(),
|
|
12
|
+
// Графа А — код товара; графы 2 / 2а — код и обозначение ОКЕИ.
|
|
13
|
+
code: z.string().nullable(),
|
|
14
|
+
name: z.string(),
|
|
15
|
+
unitCode: z.string().nullable(),
|
|
16
|
+
unitName: z.string().nullable(),
|
|
17
|
+
quantity: z.number(),
|
|
18
|
+
priceWithoutVat: MoneySchema,
|
|
19
|
+
amountWithoutVat: MoneySchema,
|
|
20
|
+
// null — «Без НДС»: прочерк в графе 8. Ноль значил бы «ставка есть, налог нулевой».
|
|
21
|
+
vatRate: z.number().nullable(),
|
|
22
|
+
vatAmount: MoneySchema.nullable(),
|
|
23
|
+
amountWithVat: MoneySchema,
|
|
24
|
+
// Графы 10 / 10а / 11. Пусто у услуг и доставки, а также когда страну не удалось определить.
|
|
25
|
+
countryCode: z.string().nullable(),
|
|
26
|
+
countryName: z.string().nullable(),
|
|
27
|
+
customsDeclarationNumber: z.string().nullable(),
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
/** Документ вместе с табличной частью — карточка и ответ на создание. */
|
|
31
|
+
export const TransferDocumentDetailedSchema = TransferDocumentSchema.extend({
|
|
32
|
+
items: TransferDocumentItemSchema.array(),
|
|
33
|
+
// Позиции, у которых не определилась страна происхождения: документ выпущен, графы 10/10а
|
|
34
|
+
// напечатаны прочерком, а UI показывает, какие карточки товара стоит поправить.
|
|
35
|
+
warnings: z.string().array(),
|
|
36
|
+
});
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { TransferDocumentStateEnum } from '../../enum/transfer-document-state.enum';
|
|
3
|
+
import { MoneySchema } from '../money.schema';
|
|
4
|
+
|
|
5
|
+
// Заказы, вошедшие в документ. Список короткий — документ выпускается по одной отгрузке клиенту,
|
|
6
|
+
// поэтому он есть и в строке списка: по нему UI показывает, какие заказы уже закрыты первичкой.
|
|
7
|
+
const TransferDocumentOrderSchema = z.object({
|
|
8
|
+
orderUUID: z.string(),
|
|
9
|
+
orderId: z.number(),
|
|
10
|
+
completedAt: z.coerce.date().nullable(),
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Документ без табличной части — форма списка.
|
|
15
|
+
*
|
|
16
|
+
* Позиции сюда не входят намеренно: в УПД их столько же, сколько строк в заказах,
|
|
17
|
+
* и страница списка из двадцати документов везла бы тысячи строк. За позициями —
|
|
18
|
+
* `TransferDocumentDetailedSchema` на карточке.
|
|
19
|
+
*/
|
|
20
|
+
export const TransferDocumentSchema = z.object({
|
|
21
|
+
uuid: z.string(),
|
|
22
|
+
// Номер с ведущими нулями — `01887`, ровно как он напечатан в документе.
|
|
23
|
+
number: z.string(),
|
|
24
|
+
documentDate: z.coerce.date(),
|
|
25
|
+
shipmentDate: z.coerce.date(),
|
|
26
|
+
// 1 — счёт-фактура + передаточный документ, 2 — только передаточный документ (акт).
|
|
27
|
+
// В MVP выпускается только 2.
|
|
28
|
+
documentStatus: z.number(),
|
|
29
|
+
state: z.nativeEnum(TransferDocumentStateEnum),
|
|
30
|
+
amount: MoneySchema,
|
|
31
|
+
amountWithoutVat: MoneySchema,
|
|
32
|
+
vatAmount: MoneySchema,
|
|
33
|
+
clientUUID: z.string(),
|
|
34
|
+
// Имя покупателя, напечатанное в документе (строка 6 формы). Может отличаться от текущего
|
|
35
|
+
// имени в карточке клиента: у юрлица печатается `fullCompanyName`, а карточку с тех пор
|
|
36
|
+
// могли переименовать. Список называет контрагента так же, как переданная ему бумага.
|
|
37
|
+
buyerName: z.string(),
|
|
38
|
+
orders: TransferDocumentOrderSchema.array(),
|
|
39
|
+
fileUrl: z.string().nullable(),
|
|
40
|
+
createdAt: z.coerce.date(),
|
|
41
|
+
});
|