@floristcloud/api-lib 1.2.96 → 1.2.98

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.
Files changed (117) hide show
  1. package/build/commands/account-deletion-request/initiate-public-account-deletion.command.js +2 -0
  2. package/build/commands/action-log/get-action-log-list-for-client.query.js +1 -1
  3. package/build/commands/action-log/get-action-log-list.query.js +1 -1
  4. package/build/commands/auth/list-mobile-buyer-tenants.command.js +2 -2
  5. package/build/commands/auth/reset-password-by-token.command.js +1 -1
  6. package/build/commands/bank-payment/get-bank-payment-list.query.js +1 -1
  7. package/build/commands/consignment/execute-consignment-product-update.command.js +2 -2
  8. package/build/commands/consignment/get-consignment-list.query.js +1 -1
  9. package/build/commands/discount-rules/remove-consignment-discount.command.js +1 -1
  10. package/build/commands/discount-rules/set-consignment-discount.command.js +1 -1
  11. package/build/commands/employee-schedule/get-employee-schedule-list.query.js +1 -1
  12. package/build/commands/order/get-order-list.query.js +2 -1
  13. package/build/commands/order/group/merge-orders.command.js +1 -1
  14. package/build/commands/order/webshop/get-order-list-for-client.query.js +3 -3
  15. package/build/commands/order-product/group/price-correction-analyze.command.js +1 -1
  16. package/build/commands/order-product/webshop/create-order-product-for-client.command.js +1 -1
  17. package/build/commands/pre-order/group/analyze-copy-pre-orders.command.js +1 -1
  18. package/build/commands/pre-order/group/analyze-create-pre-orders-from-standing-orders.command.js +1 -1
  19. package/build/commands/pre-order/group/group-copy-pre-orders-to-collection.command.js +3 -2
  20. package/build/commands/pre-order/group/group-create-pre-orders-from-standing-orders.command.js +1 -1
  21. package/build/commands/pre-order-collection-item/execute-pre-order-collection-item-update.command.js +2 -2
  22. package/build/commands/product/group/delete-group-product.command.js +2 -3
  23. package/build/commands/product/group/update-group-product-update-batch.command.js +2 -2
  24. package/build/commands/report/export-client-statement.query.js +1 -1
  25. package/build/commands/report/export-inventory-movement.query.js +1 -1
  26. package/build/commands/report/export-inventory-turnover.query.js +1 -1
  27. package/build/commands/report/export-sales-by-client.query.js +2 -2
  28. package/build/commands/report/export-sales-by-position.query.js +2 -2
  29. package/build/commands/report/export-sales-revenue.query.js +1 -1
  30. package/build/commands/report/get-daily-orders-summary.query.js +2 -2
  31. package/build/commands/report/get-report-by-client-weeks.query.js +1 -1
  32. package/build/commands/report/get-report-for-period.query.js +1 -1
  33. package/build/commands/report/get-report-group-by-client.query.js +1 -1
  34. package/build/commands/report/get-report-group-by-position.query.js +1 -1
  35. package/build/commands/report/get-sales-summary.query.js +1 -1
  36. package/build/commands/transaction/export-transactions.command.js +1 -1
  37. package/build/commands/transaction/get-sum-transaction-by-money-account.query.js +1 -1
  38. package/build/commands/transaction/get-transaction-list.query.js +1 -1
  39. package/build/commands/transaction/get-transaction-summary.query.js +1 -1
  40. package/build/commands/transaction/webshop/get-transaction-list-for-client.query.js +1 -1
  41. package/build/commands/user/createUser.command.js +2 -0
  42. package/build/commands/user/createUserByClientId.command.js +3 -1
  43. package/build/commands/user/createUserForCompany.command.js +3 -1
  44. package/build/commands/work-session/export-overtime.query.js +1 -1
  45. package/build/commands/write-off/create-write-off-from-pending.command.js +1 -1
  46. package/build/commands/write-off/get-write-off-list.query.js +1 -1
  47. package/build/commands/write-off/update-write-off-status.command.js +1 -1
  48. package/build/constant/error-i18n-key.js +43 -0
  49. package/build/constant/error.js +113 -14
  50. package/build/constant/index.js +2 -0
  51. package/build/constant/validation-i18n-key.js +39 -0
  52. package/build/constant/validation-i18n-message.js +47 -0
  53. package/build/constant/verbose.js +11 -10
  54. package/build/schemas/api-error.schema.js +32 -0
  55. package/build/schemas/consignment-transfer/accept-consignment-transfer.schema.js +1 -1
  56. package/build/schemas/index.js +1 -0
  57. package/build/schemas/order-service-line/order-service-line.schema.js +1 -1
  58. package/build/schemas/pre-order/pre-order-copy.schema.js +2 -1
  59. package/commands/account-deletion-request/initiate-public-account-deletion.command.ts +2 -0
  60. package/commands/action-log/get-action-log-list-for-client.query.ts +1 -1
  61. package/commands/action-log/get-action-log-list.query.ts +1 -1
  62. package/commands/auth/list-mobile-buyer-tenants.command.ts +2 -2
  63. package/commands/auth/reset-password-by-token.command.ts +1 -1
  64. package/commands/bank-payment/get-bank-payment-list.query.ts +1 -1
  65. package/commands/consignment/execute-consignment-product-update.command.ts +2 -2
  66. package/commands/consignment/get-consignment-list.query.ts +1 -1
  67. package/commands/discount-rules/remove-consignment-discount.command.ts +1 -1
  68. package/commands/discount-rules/set-consignment-discount.command.ts +1 -1
  69. package/commands/employee-schedule/get-employee-schedule-list.query.ts +1 -1
  70. package/commands/order/get-order-list.query.ts +2 -1
  71. package/commands/order/group/merge-orders.command.ts +1 -1
  72. package/commands/order/webshop/get-order-list-for-client.query.ts +3 -3
  73. package/commands/order-product/group/price-correction-analyze.command.ts +1 -1
  74. package/commands/order-product/webshop/create-order-product-for-client.command.ts +1 -1
  75. package/commands/pre-order/group/analyze-copy-pre-orders.command.ts +2 -2
  76. package/commands/pre-order/group/analyze-create-pre-orders-from-standing-orders.command.ts +2 -1
  77. package/commands/pre-order/group/group-copy-pre-orders-to-collection.command.ts +3 -2
  78. package/commands/pre-order/group/group-create-pre-orders-from-standing-orders.command.ts +2 -2
  79. package/commands/pre-order-collection-item/execute-pre-order-collection-item-update.command.ts +2 -2
  80. package/commands/product/group/delete-group-product.command.ts +4 -5
  81. package/commands/product/group/update-group-product-update-batch.command.ts +2 -2
  82. package/commands/report/export-client-statement.query.ts +1 -1
  83. package/commands/report/export-inventory-movement.query.ts +1 -1
  84. package/commands/report/export-inventory-turnover.query.ts +1 -1
  85. package/commands/report/export-sales-by-client.query.ts +2 -2
  86. package/commands/report/export-sales-by-position.query.ts +2 -2
  87. package/commands/report/export-sales-revenue.query.ts +1 -1
  88. package/commands/report/get-daily-orders-summary.query.ts +2 -2
  89. package/commands/report/get-report-by-client-weeks.query.ts +1 -1
  90. package/commands/report/get-report-for-period.query.ts +1 -1
  91. package/commands/report/get-report-group-by-client.query.ts +1 -1
  92. package/commands/report/get-report-group-by-position.query.ts +3 -3
  93. package/commands/report/get-sales-summary.query.ts +1 -1
  94. package/commands/transaction/export-transactions.command.ts +1 -1
  95. package/commands/transaction/get-sum-transaction-by-money-account.query.ts +1 -1
  96. package/commands/transaction/get-transaction-list.query.ts +1 -1
  97. package/commands/transaction/get-transaction-summary.query.ts +1 -1
  98. package/commands/transaction/webshop/get-transaction-list-for-client.query.ts +1 -1
  99. package/commands/user/createUser.command.ts +2 -0
  100. package/commands/user/createUserByClientId.command.ts +3 -1
  101. package/commands/user/createUserForCompany.command.ts +3 -1
  102. package/commands/work-session/export-overtime.query.ts +4 -7
  103. package/commands/write-off/create-write-off-from-pending.command.ts +1 -1
  104. package/commands/write-off/get-write-off-list.query.ts +1 -1
  105. package/commands/write-off/update-write-off-status.command.ts +1 -1
  106. package/constant/error-i18n-key.ts +53 -0
  107. package/constant/error.ts +116 -14
  108. package/constant/index.ts +2 -0
  109. package/constant/validation-i18n-key.ts +38 -0
  110. package/constant/validation-i18n-message.ts +46 -0
  111. package/constant/verbose.ts +12 -11
  112. package/package.json +1 -1
  113. package/schemas/api-error.schema.ts +34 -0
  114. package/schemas/consignment-transfer/accept-consignment-transfer.schema.ts +1 -1
  115. package/schemas/index.ts +1 -0
  116. package/schemas/order-service-line/order-service-line.schema.ts +1 -1
  117. package/schemas/pre-order/pre-order-copy.schema.ts +2 -1
package/constant/error.ts CHANGED
@@ -28,7 +28,7 @@ export const ERRORS = {
28
28
  NOTIFICATION_NOT_UPDATED: { code: 'N003', message: 'Failed to update Notification', httpCode: 500 },
29
29
  NOTIFICATION_FETCH_FAILED: { code: 'N004', message: 'Error when retrieving a notification', httpCode: 500 },
30
30
  NOTIFICATION_MAX_RETRIES_REACHED: {
31
- code: 'N004',
31
+ code: 'N009',
32
32
  message: 'Maximum retry attempts reached for notification',
33
33
  httpCode: 500,
34
34
  },
@@ -83,6 +83,8 @@ export const ERRORS = {
83
83
  SETTINGS_FETCH_FAILED: { code: 'S006', message: 'Error when retrieving a Settings', httpCode: 500 },
84
84
 
85
85
  FORBIDDEN_API: { code: 'A011', message: 'Access denied', httpCode: 403 },
86
+ RESOURCE_ACCESS_DENIED: { code: 'A022', message: 'Resource does not belong to your company', httpCode: 400 },
87
+ RESOURCE_NOT_FOUND: { code: 'A023', message: 'Resource not found', httpCode: 404 },
86
88
  FAILED_TO_DEFINE_ROLE: { code: 'A008', message: 'User role could not be determined', httpCode: 400 },
87
89
  ACCOUNT_WITH_PAYLOAD_NOT_FOUND: { code: 'A016', message: 'Account not be found based on information from the token', httpCode: 404 },
88
90
 
@@ -99,12 +101,14 @@ export const ERRORS = {
99
101
  USER_UPDATE_FAILED: { code: 'U009', message: 'Failed to update user', httpCode: 400 },
100
102
  USER_LIST_FETCH_FAILED: { code: 'U010', message: 'Failed fetching user list', httpCode: 500 },
101
103
  USER_NO_BELONGS_COMPANY: { code: 'U011', message: 'This user does not belongs to the company ', httpCode: 403 },
102
- USER_MISSING_EMAIL_OR_PHONE: { code: 'U012', message: 'Не указан email или телефон ', httpCode: 400 },
104
+ USER_MISSING_EMAIL_OR_PHONE: { code: 'U012', message: 'Email or phone is required', httpCode: 400 },
103
105
  USER_ROLE_MISMATCH_CLIENT: { code: 'U013', message: 'User does not have BUYER role required for client login', httpCode: 403 },
104
106
  USER_ROLE_MISMATCH_EMPLOYEE: { code: 'U014', message: 'User does not have employee role required for employee login', httpCode: 403 },
105
107
  USER_CANNOT_DEACTIVATE_SELF: { code: 'U015', message: 'You cannot deactivate your own account', httpCode: 400 },
106
108
  USER_CANNOT_REMOVE_OWN_ADMIN_ROLE: { code: 'U016', message: 'You cannot remove the ADMIN role from your own account', httpCode: 400 },
107
109
  USER_CANNOT_REMOVE_LAST_ADMIN: { code: 'U017', message: 'The company must keep at least one active administrator', httpCode: 400 },
110
+ USER_EMAIL_REQUIRED_FOR_NOTIFICATION: { code: 'U018', message: 'User email is required for email notification', httpCode: 400 },
111
+ USER_PASSWORD_GENERATION_FAILED: { code: 'U019', message: 'Failed to generate and send password', httpCode: 500 },
108
112
 
109
113
  //AUTH
110
114
  FAILED_TO_UPDATE: { code: 'A010', message: 'User update failed', httpCode: 500 },
@@ -162,7 +166,7 @@ export const ERRORS = {
162
166
  CLIENT_HAS_ORDERS: { code: 'CL025', message: 'Client has orders', httpCode: 400 },
163
167
  CLIENT_IMPORT_FAILED: {
164
168
  code: 'CL024',
165
- message: 'Ошибка при импорте клиентов',
169
+ message: 'Failed to import clients',
166
170
  httpCode: 400,
167
171
  },
168
172
  CLIENT_FILTERS_VALUES_FETCH_FAILED: {
@@ -265,6 +269,12 @@ export const ERRORS = {
265
269
  CONSIGNMENT_IMPORT_TOO_MANY_ROWS: { code: 'CON024', message: 'Too many rows for this import mode', httpCode: 400 },
266
270
  CONSIGNMENT_PRODUCT_UPDATE_SCHEMA_NOT_FOUND: { code: 'CON025', message: 'Update schema not found', httpCode: 404 },
267
271
  CONSIGNMENT_PRODUCT_UPDATE_SCHEMA_NO_HEADERS_MATCHED: { code: 'CON026', message: 'No schema headers matched the file', httpCode: 400 },
272
+ CONSIGNMENT_PRODUCT_UPDATE_NOT_IN_CONSIGNMENT: {
273
+ code: 'CON027',
274
+ message: 'Product does not belong to this consignment',
275
+ httpCode: 400,
276
+ },
277
+ CONSIGNMENT_PRODUCT_UPDATE_ITEM_FAILED: { code: 'CON028', message: 'Product update failed', httpCode: 400 },
268
278
 
269
279
  // CONSIGNMENT-IMPORT-SCHEME
270
280
  CONSIGNMENT_IMPORT_SCHEME_NOT_CREATED: { code: 'CS001', message: 'Failed to create consignment import scheme', httpCode: 500 },
@@ -411,6 +421,9 @@ export const ERRORS = {
411
421
  message: 'Delivery information will be transferred to the target order.',
412
422
  httpCode: 400,
413
423
  },
424
+ ORDER_MERGE_TARGET_IN_SOURCE_LIST: { code: 'O036', message: 'Target order must not be in source list', httpCode: 400 },
425
+ ORDER_INVOICE_NOTIFICATION_INVALID_TYPE: { code: 'O037', message: 'Invalid notification type', httpCode: 400 },
426
+ ORDER_INVOICE_NOTIFICATION_ORDER_UUID_MISSING: { code: 'O038', message: 'Order UUID missing in payload', httpCode: 400 },
414
427
 
415
428
  //SERVICE
416
429
  SERVICE_NOT_CREATED: { code: 'SV001', message: 'Failed to create service', httpCode: 500 },
@@ -520,6 +533,11 @@ export const ERRORS = {
520
533
  message: 'Order product not found in the order',
521
534
  httpCode: 404,
522
535
  },
536
+ ORDER_PRODUCT_MOVE_SAME_ORDER: {
537
+ code: 'OP025',
538
+ message: 'Source and destination orders must differ',
539
+ httpCode: 400,
540
+ },
523
541
 
524
542
  //TRANSACTION
525
543
  TRANSACTION_NOT_CREATED: { code: 'TR001', message: 'Failed to transaction product', httpCode: 500 },
@@ -535,7 +553,7 @@ export const ERRORS = {
535
553
  TRANSACTION_NOT_APPLIED: { code: 'TR011', message: 'Transaction not applied', httpCode: 500 },
536
554
  MONEY_ACCOUNT_REQUIRED: { code: 'TR012', message: 'moneyAccountUUID is required to apply bank payment event', httpCode: 400 },
537
555
  TRANSACTION_CREATE_FAILED: { code: 'TR013', message: 'Failed to create transaction', httpCode: 500 },
538
- TRANSACTION_IMPORT_FAILED: { code: 'TR014', message: 'Ошибка при импорте транзакций', httpCode: 400 },
556
+ TRANSACTION_IMPORT_FAILED: { code: 'TR014', message: 'Failed to import transactions', httpCode: 400 },
539
557
  TRANSACTION_IMPORT_TOO_MANY_ROWS: { code: 'TR015', message: 'Too many rows for transaction import', httpCode: 400 },
540
558
  TRANSACTION_IMPORT_INVALID_FILE_FORMAT: { code: 'TR016', message: 'Invalid file format for transaction import', httpCode: 400 },
541
559
  TRANSACTION_IMPORT_MISSING_REQUIRED_COLUMNS: {
@@ -592,6 +610,13 @@ export const ERRORS = {
592
610
  httpCode: 500,
593
611
  },
594
612
 
613
+ // COMMON (transport-level codes the catch-all HttpExceptionFilter emits for non-business failures)
614
+ COMMON_NO_DATA_RETURNED: { code: 'E900', message: 'No data returned', httpCode: 500 },
615
+ COMMON_UNKNOWN_ERROR: { code: 'E901', message: 'Unknown error', httpCode: 500 },
616
+ COMMON_VALIDATION_FAILED: { code: 'E902', message: 'Validation failed', httpCode: 400 },
617
+ COMMON_UNAUTHORIZED: { code: 'E903', message: 'Unauthorized', httpCode: 401 },
618
+ COMMON_BAD_REQUEST: { code: 'E904', message: 'Bad request', httpCode: 400 },
619
+
595
620
  // EXCEL
596
621
  EXCEL_CREATE_FAILED: { code: 'E001', message: 'Failed to create excel', httpCode: 500 },
597
622
  EXCEL_GET_DATA_BY_BUFFER_FAILED: { code: 'E002', message: 'Failed to get buffer', httpCode: 500 },
@@ -604,6 +629,7 @@ export const ERRORS = {
604
629
  CATEGORY_NOT_DELETED: { code: 'CA011', message: 'Failed to delete category', httpCode: 500 },
605
630
  CATEGORY_NOT_GET_BY_UUID: { code: 'CA012', message: 'Failed to get category by uuid', httpCode: 500 },
606
631
  CATEGORY_FETCH_FAILED: { code: 'CA013', message: 'Error when retrieving a list of categories', httpCode: 500 },
632
+ CATEGORY_NOT_DETERMINED: { code: 'CA019', message: 'Could not determine category for product', httpCode: 400 },
607
633
  CATEGORY_NOT_UPDATED: { code: 'CA014', message: 'Failed to update category', httpCode: 500 },
608
634
  CATEGORY_CREATE_MANY_FAILED: { code: 'CA015', message: 'Failed to create many categories', httpCode: 500 },
609
635
  CATEGORY_USE_IN_PRODUCT: { code: 'CA016', message: 'Category use in product', httpCode: 500 },
@@ -644,16 +670,16 @@ export const ERRORS = {
644
670
  FILE_NOT_SUPPORTED: { code: 'F006', message: 'File not supported', httpCode: 400 },
645
671
  FILE_TOO_LARGE: { code: 'F007', message: 'File size exceeds the allowed limit', httpCode: 413 },
646
672
  FILE_UPLOAD_FAILED: { code: 'F008', message: 'File upload failed', httpCode: 400 },
647
- FILE_S3_FORBIDDEN: { code: 'F007', message: 'File S3 forbidden', httpCode: 403 },
673
+ FILE_S3_FORBIDDEN: { code: 'F009', message: 'File S3 forbidden', httpCode: 403 },
648
674
 
649
675
  //WHATSAPP
650
- WHATSAPP_TEXT_NOT_SENT: { code: 'W001', message: 'Failed to send text message', httpCode: 500 },
651
- WHATSAPP_FILE_NOT_SENT: { code: 'W002', message: 'Failed to send file message', httpCode: 500 },
652
- WHATSAPP_FETCH_FAILED_NOTIFICATIONS: { code: 'W003', message: 'Failed to fetch notifications', httpCode: 500 },
653
- WHATSAPP_PHONE_NOT_FOUND: { code: 'W004', message: 'Phone number not found or invalid', httpCode: 400 },
654
- WHATSAPP_STATUS_CHECK_FAILED: { code: 'W005', message: 'Failed to check WhatsApp message status', httpCode: 500 },
655
- WHATSAPP_MESSAGE_NOT_FOUND: { code: 'W006', message: 'Message not found in notification', httpCode: 400 },
656
- WHATSAPP_CHANNEL_NOT_IN_USE: { code: 'W007', message: 'WhatsApp channel is not in use', httpCode: 410 },
676
+ WHATSAPP_TEXT_NOT_SENT: { code: 'WH001', message: 'Failed to send text message', httpCode: 500 },
677
+ WHATSAPP_FILE_NOT_SENT: { code: 'WH002', message: 'Failed to send file message', httpCode: 500 },
678
+ WHATSAPP_FETCH_FAILED_NOTIFICATIONS: { code: 'WH003', message: 'Failed to fetch notifications', httpCode: 500 },
679
+ WHATSAPP_PHONE_NOT_FOUND: { code: 'WH004', message: 'Phone number not found or invalid', httpCode: 400 },
680
+ WHATSAPP_STATUS_CHECK_FAILED: { code: 'WH005', message: 'Failed to check WhatsApp message status', httpCode: 500 },
681
+ WHATSAPP_MESSAGE_NOT_FOUND: { code: 'WH006', message: 'Message not found in notification', httpCode: 400 },
682
+ WHATSAPP_CHANNEL_NOT_IN_USE: { code: 'WH007', message: 'WhatsApp channel is not in use', httpCode: 410 },
657
683
 
658
684
  //MAX MESSENGER
659
685
  MAX_MESSENGER_TEXT_NOT_SENT: { code: 'MX001', message: 'Failed to send text message via Max Messenger', httpCode: 500 },
@@ -721,7 +747,7 @@ export const ERRORS = {
721
747
  //PRE ORDER
722
748
  PRE_ORDER_NOT_CREATED: { code: 'PO001', message: 'Failed to create pre order', httpCode: 500 },
723
749
  PRE_ORDER_NOT_DELETED: { code: 'PO002', message: 'Failed to delete pre order', httpCode: 500 },
724
- PRE_ORDER_MANY_NOT_DELETED: { code: 'PO002', message: 'Failed to delete pre orders', httpCode: 500 },
750
+ PRE_ORDER_MANY_NOT_DELETED: { code: 'PO036', message: 'Failed to delete pre orders', httpCode: 500 },
725
751
  PRE_ORDER_NOT_UPDATED: { code: 'PO003', message: 'Failed to update pre order', httpCode: 500 },
726
752
  PRE_ORDER_NOT_FOUND: { code: 'PO004', message: 'The pre order with the specified UUID was not found', httpCode: 404 },
727
753
  PRE_ORDER_FETCH_FAILED: { code: 'PO006', message: 'Error when retrieving a list of pre orders', httpCode: 500 },
@@ -780,11 +806,74 @@ export const ERRORS = {
780
806
  httpCode: 400,
781
807
  },
782
808
  PRE_ORDER_INVALID_COLLECTION: {
783
- code: 'PO013',
809
+ code: 'PO037',
784
810
  message: 'Pre order invalid collection',
785
811
  httpCode: 400,
786
812
  },
787
813
 
814
+ // PRE ORDER — standing-order → pre-order conversion per-item warnings
815
+ PRE_ORDER_SO_ITEM_NOT_LINKED_TO_CATALOG: {
816
+ code: 'PO024',
817
+ message: 'Standing-order item is not linked to a STANDING_ORDER_CATALOG item; matching is impossible',
818
+ httpCode: 400,
819
+ },
820
+ PRE_ORDER_SO_ITEM_NO_MATCHES: {
821
+ code: 'PO025',
822
+ message: 'No matches found in the available collections for the catalog item',
823
+ httpCode: 400,
824
+ },
825
+ PRE_ORDER_SO_ITEM_INSUFFICIENT_QUANTITY: {
826
+ code: 'PO026',
827
+ message: 'Insufficient available quantity in collections for the catalog item; item added partially or not added',
828
+ httpCode: 400,
829
+ },
830
+ PRE_ORDER_SO_ITEM_PARTIALLY_ALLOCATED: {
831
+ code: 'PO027',
832
+ message: 'Not enough balance for the catalog item; part of the quantity was left unallocated',
833
+ httpCode: 400,
834
+ },
835
+ PRE_ORDER_SO_ITEM_NOT_ADDED_IN_COLLECTION: {
836
+ code: 'PO028',
837
+ message: 'Standing-order item was not added to the pre-order for this collection because no match was found in this collection',
838
+ httpCode: 400,
839
+ },
840
+ PRE_ORDER_SO_PRODUCT_NOT_CREATED: {
841
+ code: 'PO029',
842
+ message: 'Failed to create pre-order product from standing-order item',
843
+ httpCode: 400,
844
+ },
845
+ PRE_ORDER_SO_CRITICAL_ERROR: {
846
+ code: 'PO030',
847
+ message: 'Critical error during pre-order creation from standing order',
848
+ httpCode: 400,
849
+ },
850
+ PRE_ORDER_SO_NO_PRE_ORDERS_CREATED: {
851
+ code: 'PO031',
852
+ message: 'No pre-orders were created for this standing order: no matching items found in the selected collections',
853
+ httpCode: 400,
854
+ },
855
+ // PRE ORDER — copy pre-order per-item warnings
856
+ PRE_ORDER_COPY_ITEM_NO_MATCHES: {
857
+ code: 'PO032',
858
+ message: 'No matches found in the target collection for the item',
859
+ httpCode: 400,
860
+ },
861
+ PRE_ORDER_COPY_ITEM_INSUFFICIENT_QUANTITY: {
862
+ code: 'PO033',
863
+ message: 'Insufficient balance for the item; part of the quantity was left unallocated',
864
+ httpCode: 400,
865
+ },
866
+ PRE_ORDER_COPY_SOURCE_NOT_FOUND_OR_EMPTY: {
867
+ code: 'PO034',
868
+ message: 'Source pre-order not found or contains no products',
869
+ httpCode: 400,
870
+ },
871
+ PRE_ORDER_COPY_PRODUCT_CREATE_FAILED: {
872
+ code: 'PO035',
873
+ message: 'Failed to create product during pre-order copy',
874
+ httpCode: 400,
875
+ },
876
+
788
877
  //PRE ORDER PRODUCT
789
878
  PRE_ORDER_PRODUCT_NOT_CREATED: { code: 'POP001', message: 'Failed to create pre order product', httpCode: 500 },
790
879
  PRE_ORDER_PRODUCT_NOT_DELETED: { code: 'POP002', message: 'Failed to delete pre order product', httpCode: 500 },
@@ -984,6 +1073,11 @@ export const ERRORS = {
984
1073
  message: 'Missing required columns in pre order collection item import file',
985
1074
  httpCode: 400,
986
1075
  },
1076
+ PRE_ORDER_COLLECTION_ITEM_UPDATE_BATCH_TOO_LARGE: {
1077
+ code: 'POCI028',
1078
+ message: 'Batch size too large',
1079
+ httpCode: 400,
1080
+ },
987
1081
 
988
1082
  // EMPLOYEE SCHEDULE
989
1083
  EMPLOYEE_SCHEDULE_NOT_CREATED: { code: 'ES001', message: 'Failed to create employee schedule', httpCode: 500 },
@@ -1103,6 +1197,9 @@ export const ERRORS = {
1103
1197
 
1104
1198
  NOT_IMPLEMENTED: { code: 'G001', message: 'Not implemented', httpCode: 501 },
1105
1199
 
1200
+ // Neutral 2xx success — lets the frontend localize a success body by code instead of raw text
1201
+ OPERATION_SUCCESS: { code: 'OK001', message: 'Operation completed successfully', httpCode: 200 },
1202
+
1106
1203
  // SESSION
1107
1204
  SESSION_NOT_FOUND: { code: 'SES001', message: 'Session not found', httpCode: 401 },
1108
1205
  SESSION_REVOKED: { code: 'SES002', message: 'Session has been revoked', httpCode: 401 },
@@ -1156,6 +1253,11 @@ export const ERRORS = {
1156
1253
  PUBLIC_ACCOUNT_DELETION_INVALID_CODE: { code: 'ADR009', message: 'Invalid or expired verification code', httpCode: 400 },
1157
1254
  PUBLIC_ACCOUNT_DELETION_INVALID_TOKEN: { code: 'ADR010', message: 'Invalid or expired verification token', httpCode: 400 },
1158
1255
  PUBLIC_ACCOUNT_DELETION_NO_TENANTS_SELECTED: { code: 'ADR011', message: 'No valid tenants selected for deletion', httpCode: 400 },
1256
+ ACCOUNT_DELETION_REQUEST_SUBMITTED: {
1257
+ code: 'ADR012',
1258
+ message: 'If the account exists, a verification code has been sent',
1259
+ httpCode: 200,
1260
+ },
1159
1261
 
1160
1262
  // MOYSKLAD INTEGRATION
1161
1263
  MOYSKLAD_INVALID_TOKEN: { code: 'MS001', message: 'MoySklad token is invalid or has insufficient permissions', httpCode: 400 },
package/constant/index.ts CHANGED
@@ -2,3 +2,5 @@ export * from './error';
2
2
  export * from './verbose';
3
3
  export * from './error-i18n-key';
4
4
  export * from './import.constant';
5
+ export * from './validation-i18n-key';
6
+ export * from './validation-i18n-message';
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Stable i18n tokens for Zod validation messages.
3
+ *
4
+ * The global ZodValidationPipe surfaces a schema's `message` verbatim to the client with no error
5
+ * code, so raw English/Russian prose there is not localizable. Use these dot-notation tokens as the
6
+ * Zod `message` instead — the frontend maps the token to a localized string. The token itself is the
7
+ * stable contract; the English text lives only in the frontend dictionary.
8
+ */
9
+ export const ValidationI18nKey = {
10
+ dateRange: 'validation.dateRange',
11
+ reportPeriodMax: 'validation.reportPeriodMax',
12
+ emailOrPhoneRequired: 'validation.emailOrPhoneRequired',
13
+ allowedRoles: 'validation.allowedRoles',
14
+ statusNotAllowedWebshop: 'validation.statusNotAllowedWebshop',
15
+ targetOrderInList: 'validation.targetOrderInList',
16
+ productListOrConsignment: 'validation.productListOrConsignment',
17
+ consignmentOrProducts: 'validation.consignmentOrProducts',
18
+ rejectionReasonRequired: 'validation.rejectionReasonRequired',
19
+ targetOrNewConsignment: 'validation.targetOrNewConsignment',
20
+ serviceOrNamePrice: 'validation.serviceOrNamePrice',
21
+ quantityPositive: 'validation.quantityPositive',
22
+ nameRequired: 'validation.nameRequired',
23
+ categoryRequired: 'validation.categoryRequired',
24
+ quantityRequired: 'validation.quantityRequired',
25
+ atLeastOneItem: 'validation.atLeastOneItem',
26
+ atLeastOneClient: 'validation.atLeastOneClient',
27
+ fieldRequired: 'validation.fieldRequired',
28
+ phoneFormat: 'validation.phoneFormat',
29
+ emailFormat: 'validation.emailFormat',
30
+ dateFormat: 'validation.dateFormat',
31
+ invalidClientType: 'validation.invalidClientType',
32
+ standingOrderClientNameRequired: 'validation.standingOrderClientNameRequired',
33
+ standingOrderCategoryRequired: 'validation.standingOrderCategoryRequired',
34
+ standingOrderNameRequired: 'validation.standingOrderNameRequired',
35
+ standingOrderQuantityRequired: 'validation.standingOrderQuantityRequired',
36
+ } as const;
37
+
38
+ export type ValidationI18nKeyType = (typeof ValidationI18nKey)[keyof typeof ValidationI18nKey];
@@ -0,0 +1,46 @@
1
+ import { ValidationI18nKey, ValidationI18nKeyType } from './validation-i18n-key';
2
+
3
+ /**
4
+ * English fallback text for every stable Zod validation token (see validation-i18n-key.ts).
5
+ *
6
+ * The global ZodValidationPipe puts the token into an issue's `message`. The catch-all
7
+ * HttpExceptionFilter detects that a message is a token and, using this map, moves the token to the
8
+ * `i18nKey` field while replacing `message` with the EN text below. The frontend localizes off
9
+ * `i18nKey`; `message` is only the human-readable fallback (see api-error.schema.ts).
10
+ *
11
+ * Every token in ValidationI18nKey MUST have an entry here (enforced by the Record type).
12
+ */
13
+ export const VALIDATION_I18N_MESSAGE: Record<ValidationI18nKeyType, string> = {
14
+ [ValidationI18nKey.dateRange]: 'Start date must be before or equal to end date',
15
+ [ValidationI18nKey.reportPeriodMax]: 'The selected period exceeds the maximum allowed range',
16
+ [ValidationI18nKey.emailOrPhoneRequired]: 'Either email or phone is required',
17
+ [ValidationI18nKey.allowedRoles]: 'The specified role is not allowed',
18
+ [ValidationI18nKey.statusNotAllowedWebshop]: 'This status is not allowed in the webshop',
19
+ [ValidationI18nKey.targetOrderInList]: 'The target order must not be included in the source order list',
20
+ [ValidationI18nKey.productListOrConsignment]: 'Either a product list or a consignment must be provided',
21
+ [ValidationI18nKey.consignmentOrProducts]: 'Either a consignment or products must be provided',
22
+ [ValidationI18nKey.rejectionReasonRequired]: 'A rejection reason is required',
23
+ [ValidationI18nKey.targetOrNewConsignment]: 'Either a target consignment or a new consignment must be provided',
24
+ [ValidationI18nKey.serviceOrNamePrice]: 'Either a service or a name and price must be provided',
25
+ [ValidationI18nKey.quantityPositive]: 'Quantity must be a positive number',
26
+ [ValidationI18nKey.nameRequired]: 'Name is required',
27
+ [ValidationI18nKey.categoryRequired]: 'Category is required',
28
+ [ValidationI18nKey.quantityRequired]: 'Quantity is required',
29
+ [ValidationI18nKey.atLeastOneItem]: 'At least one item is required',
30
+ [ValidationI18nKey.atLeastOneClient]: 'At least one client is required',
31
+ [ValidationI18nKey.fieldRequired]: 'This field is required',
32
+ [ValidationI18nKey.phoneFormat]: 'Invalid phone number format',
33
+ [ValidationI18nKey.emailFormat]: 'Invalid email format',
34
+ [ValidationI18nKey.dateFormat]: 'Invalid date format',
35
+ [ValidationI18nKey.invalidClientType]: 'Invalid client type',
36
+ [ValidationI18nKey.standingOrderClientNameRequired]: 'Client name is required',
37
+ [ValidationI18nKey.standingOrderCategoryRequired]: 'Category is required',
38
+ [ValidationI18nKey.standingOrderNameRequired]: 'Name is required',
39
+ [ValidationI18nKey.standingOrderQuantityRequired]: 'Quantity is required',
40
+ };
41
+
42
+ /**
43
+ * A validation `message` is a stable i18n token when it matches this pattern (e.g. `validation.dateRange`).
44
+ * Anything else is a custom Zod message that stays in `message` with no `i18nKey`.
45
+ */
46
+ export const VALIDATION_I18N_TOKEN_PATTERN = /^validation\.[A-Za-z0-9.]+$/;
@@ -1,20 +1,21 @@
1
+ // Success messages: `message` is the EN fallback, the frontend localizes by `code` (same model as ERRORS).
1
2
  export const VERBOSE = {
2
- USER_SUCCESSFULLY_CREATED: { code: 'SM001', message: 'Пользователь успешно зарегистрирован' },
3
+ USER_SUCCESSFULLY_CREATED: { code: 'SM001', message: 'User registered successfully' },
3
4
  EMAIL_VERIFICATION_SEND: {
4
5
  code: 'SM002',
5
- message: 'Подтверждение адреса электронной почти отправлено успешно! Проверьте свой почтовый ящик.',
6
+ message: 'Email verification sent successfully! Check your inbox.',
6
7
  },
7
- EMAIL_VERIFICATION_SUCCESS: { code: 'SM003', message: 'Подтверждение почты прошло успешно!' },
8
- PASSWORD_SUCCESSFULLY_SET: { code: 'SM004', message: 'Пароль пользователя успешно установлен!' },
8
+ EMAIL_VERIFICATION_SUCCESS: { code: 'SM003', message: 'Email verified successfully!' },
9
+ PASSWORD_SUCCESSFULLY_SET: { code: 'SM004', message: 'User password set successfully!' },
9
10
  PASSWORD_SUCCESSFULLY_RESTORED: {
10
11
  code: 'SM005',
11
- message: 'Вам на почту выслано письмо с подтверждением сброса пароля. Проверьте свой почтовый ящик!',
12
+ message: 'A password reset confirmation email has been sent to you. Check your inbox!',
12
13
  },
13
- PASSWORD_SUCCESSFULLY_RESET: { code: 'SM006', message: 'Пароль успешно сброшен' },
14
- CABINET_SUCCESSFULLY_UPDATED: { code: 'SM007', message: 'Кабинет успешно обновлён' },
15
- PROJECT_SUCCESSFULLY_CREATED: { code: 'SM008', message: 'Проект успешно создан.' },
16
- PROJECT_SUCCESSFULLY_UPDATED: { code: 'SM009', message: 'Проект успешно обновлён.' },
14
+ PASSWORD_SUCCESSFULLY_RESET: { code: 'SM006', message: 'Password reset successfully' },
15
+ CABINET_SUCCESSFULLY_UPDATED: { code: 'SM007', message: 'Cabinet updated successfully' },
16
+ PROJECT_SUCCESSFULLY_CREATED: { code: 'SM008', message: 'Project created successfully.' },
17
+ PROJECT_SUCCESSFULLY_UPDATED: { code: 'SM009', message: 'Project updated successfully.' },
17
18
 
18
19
  // SMS GATEWAY
19
- SMS_SUCCESSFULLY_SENT: { code: 'SM010', message: 'SMS сообщение успешно отправлено' },
20
- };
20
+ SMS_SUCCESSFULLY_SENT: { code: 'SM010', message: 'SMS message sent successfully' },
21
+ } as const;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@floristcloud/api-lib",
3
- "version": "1.2.96",
3
+ "version": "1.2.98",
4
4
  "description": "",
5
5
  "main": "./build/index.js",
6
6
  "scripts": {
@@ -0,0 +1,34 @@
1
+ import { z } from 'zod';
2
+
3
+ // Per-field issue of a VALIDATION error (Zod): `path` addresses the offending field.
4
+ // `i18nKey` is the stable token the frontend translates; it is set only when the schema used a
5
+ // registered `validation.*` token as its Zod message (see validation-i18n-key.ts). In that case
6
+ // `message` carries the EN fallback text from VALIDATION_I18N_MESSAGE. For custom Zod messages that
7
+ // are not tokens, `i18nKey` is omitted and `message` holds the raw Zod string as-is.
8
+ export const ApiErrorValidationIssueSchema = z.object({
9
+ path: z.array(z.union([z.string(), z.number()])),
10
+ message: z.string(),
11
+ i18nKey: z.string().optional(),
12
+ });
13
+
14
+ /**
15
+ * Unified HTTP error envelope: every non-2xx response of the API has exactly this shape
16
+ * (enforced by the catch-all HttpExceptionFilter on the backend).
17
+ *
18
+ * - `errorCode` — a code from ERRORS (business) or ApiGenericErrorCodeEnum (validation/transport);
19
+ * the frontend maps it to a localized text, `message` is only the EN fallback.
20
+ * - `errors` — present only when `errorCode` is VALIDATION (per-field issues).
21
+ * - `data` — optional machine-readable payload attached by business errors.
22
+ */
23
+ export const ApiErrorSchema = z.object({
24
+ statusCode: z.number().int(),
25
+ errorCode: z.string(),
26
+ message: z.string(),
27
+ timestamp: z.string(),
28
+ path: z.string(),
29
+ errors: z.array(ApiErrorValidationIssueSchema).optional(),
30
+ data: z.unknown().optional(),
31
+ });
32
+
33
+ export type ApiErrorValidationIssue = z.infer<typeof ApiErrorValidationIssueSchema>;
34
+ export type ApiError = z.infer<typeof ApiErrorSchema>;
@@ -23,7 +23,7 @@ export const AcceptConsignmentTransferRequestSchema = z
23
23
  .min(1),
24
24
  })
25
25
  .refine(data => Boolean(data.targetConsignmentUUID) !== Boolean(data.newConsignment), {
26
- message: 'Provide either targetConsignmentUUID or newConsignment, not both',
26
+ message: 'validation.targetOrNewConsignment',
27
27
  path: ['targetConsignmentUUID'],
28
28
  });
29
29
 
package/schemas/index.ts CHANGED
@@ -67,4 +67,5 @@ export * from './messenger-profile';
67
67
  export * from './error-message.schema';
68
68
  export * from './account-deletion-request/account-deletion-request.schema';
69
69
  export * from './consignment-transfer';
70
+ export * from './api-error.schema';
70
71
  export * from './access-policy';
@@ -28,7 +28,7 @@ export const CreateOrderServiceLineRequestSchema = z
28
28
  comment: z.string().max(1000).optional(),
29
29
  })
30
30
  .refine(data => data.serviceUUID || (data.name && data.price !== undefined), {
31
- message: 'Either serviceUUID or both name and price must be provided',
31
+ message: 'validation.serviceOrNamePrice',
32
32
  });
33
33
 
34
34
  export const UpdateOrderServiceLineRequestSchema = z.object({
@@ -2,6 +2,7 @@ import { z } from 'zod';
2
2
  import { PreOrderWithClientSchema } from './pre-order.schema';
3
3
  import { PreOrderProductExtendedSchema } from '../pre-order-product/pre-order-product.schema';
4
4
  import { PreOrderCollectionItemSchema } from '../pre-order-collection-item/pre-order-collection-item.schema';
5
+ import { ErrorMessageSchema } from '../error-message.schema';
5
6
 
6
7
  export const CopyAnalysisMatchSchema = z.object({
7
8
  collectionItem: PreOrderCollectionItemSchema,
@@ -17,5 +18,5 @@ export const CopyAnalysisMappingSchema = z.object({
17
18
  export const CopyAnalysisSchema = z.object({
18
19
  preOrder: PreOrderWithClientSchema,
19
20
  mappings: z.record(z.string(), CopyAnalysisMappingSchema),
20
- warnings: z.record(z.string(), z.array(z.string())),
21
+ warnings: z.record(z.string(), z.array(ErrorMessageSchema)),
21
22
  });