@escapenavigator/utils 2.1.18 → 2.1.19

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.
@@ -58,8 +58,15 @@ const GENERIC_ERROR_CODES = new Set([
58
58
  * lifecycle компонента.
59
59
  */
60
60
  const SKIP_AXIOS_CODES = new Set(['ERR_CANCELED', 'CANCELED']);
61
- /** 304 = успешный ответ при if-none-match (etag). */
62
- const SKIP_HTTP_STATUSES = new Set([304]);
61
+ /**
62
+ * 304 = успешный ответ при if-none-match (etag).
63
+ *
64
+ * 413 = выбранный файл больше лимита multer. Лимит сработал как задумано,
65
+ * пользователь получил внятный отказ и выбирает файл поменьше — о здоровье
66
+ * сервиса это не говорит ничего (ESCAPE-NAVIGATOR-APP-96, симметрично
67
+ * ESCAPE-NAVIGATOR-API-SE на бэке).
68
+ */
69
+ const SKIP_HTTP_STATUSES = new Set([304, 413]);
63
70
  /**
64
71
  * 401/403 на CRM/auth — ожидаемый flow (протухшая сессия, роль пользователя).
65
72
  * На widget/orders репортим как debug: это сигнал для мониторинга (битый
@@ -19,6 +19,10 @@ describe('classifyApiError', () => {
19
19
  const r = (0, classify_api_error_1.classifyApiError)({ ...base, status: 304 });
20
20
  expect(r.shouldReport).toBe(false);
21
21
  });
22
+ it('413 (файл больше лимита) → skip', () => {
23
+ const r = (0, classify_api_error_1.classifyApiError)({ ...base, status: 413 });
24
+ expect(r.shouldReport).toBe(false);
25
+ });
22
26
  it('401/403 на app/auth → skip (ожидаемый session/role flow)', () => {
23
27
  expect((0, classify_api_error_1.classifyApiError)({ ...base, status: 401, app: 'app' }).shouldReport).toBe(false);
24
28
  expect((0, classify_api_error_1.classifyApiError)({ ...base, status: 403, app: 'auth' }).shouldReport).toBe(false);
@@ -0,0 +1 @@
1
+ import 'reflect-metadata';
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ require("reflect-metadata");
4
+ const create_promocode_dto_1 = require("@escapenavigator/types/dist/promocode/create-promocode.dto");
5
+ const class_validator_1 = require("class-validator");
6
+ const serialize_record_1 = require("./serialize-record");
7
+ describe('CreatePromocodeDto.availableDays', () => {
8
+ it('вырезает holiday/eve до integer[], чтобы Postgres не падал 500', () => {
9
+ const dto = (0, serialize_record_1.serializeRecord)(create_promocode_dto_1.CreatePromocodeDto, {
10
+ description: 'Wiedergutmachung',
11
+ type: 'fixed',
12
+ discount: 3000,
13
+ availableDays: [0, 1, 2, 3, 4, 5, 6, 'holiday', 'eve'],
14
+ });
15
+ expect(dto.availableDays).toEqual([0, 1, 2, 3, 4, 5, 6]);
16
+ expect((0, class_validator_1.validateSync)(dto).filter((error) => error.property === 'availableDays')).toEqual([]);
17
+ });
18
+ });
@@ -9,3 +9,10 @@ export declare const PT_FATURA: {
9
9
  readonly nifInvalid: "NIF inválido";
10
10
  readonly address: "Morada";
11
11
  };
12
+ /**
13
+ * Чекбокс и поля NIF только если Moloni / InvoiceXpress уже настроены.
14
+ * `fiscalReady` сам требует PT + ключи провайдера.
15
+ */
16
+ export declare const hasPtFiscalBilling: (profile?: {
17
+ fiscalReady?: boolean | null;
18
+ } | null) => boolean;
package/dist/pt-fatura.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.PT_FATURA = void 0;
3
+ exports.hasPtFiscalBilling = exports.PT_FATURA = void 0;
4
4
  /**
5
5
  * Подписи только для Португалии — не ключи i18n.
6
6
  * «Fatura com NIF» это частник или фирма, не «как компания».
@@ -12,3 +12,9 @@ exports.PT_FATURA = {
12
12
  nifInvalid: 'NIF inválido',
13
13
  address: 'Morada',
14
14
  };
15
+ /**
16
+ * Чекбокс и поля NIF только если Moloni / InvoiceXpress уже настроены.
17
+ * `fiscalReady` сам требует PT + ключи провайдера.
18
+ */
19
+ const hasPtFiscalBilling = (profile) => !!profile?.fiscalReady;
20
+ exports.hasPtFiscalBilling = hasPtFiscalBilling;
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,10 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const pt_fatura_1 = require("./pt-fatura");
4
+ describe('hasPtFiscalBilling', () => {
5
+ it('только при готовой фискальной интеграции', () => {
6
+ expect((0, pt_fatura_1.hasPtFiscalBilling)(undefined)).toBe(false);
7
+ expect((0, pt_fatura_1.hasPtFiscalBilling)({ fiscalReady: false })).toBe(false);
8
+ expect((0, pt_fatura_1.hasPtFiscalBilling)({ fiscalReady: true })).toBe(true);
9
+ });
10
+ });
@@ -5,3 +5,19 @@ export type RolePaymentDeletePermissions = Pick<RoleRO, 'totalAccess' | 'canDele
5
5
  * Владелец (`totalAccess`) — как будто флаг включён.
6
6
  */
7
7
  export declare const canDeletePayments: (role?: RolePaymentDeletePermissions | null) => boolean;
8
+ export type TransactionBookingBinding = {
9
+ order?: {
10
+ id?: number;
11
+ } | null;
12
+ certificatesale?: {
13
+ id?: number;
14
+ } | null;
15
+ orderId?: number | null;
16
+ certificatesaleId?: number | null;
17
+ orderGroupId?: number | null;
18
+ };
19
+ /**
20
+ * Платёж привязан к игре (заказ / группа) или сертификату.
21
+ * Такие платежи из раздела «Финансы» не удаляем — только из карточки брони.
22
+ */
23
+ export declare const isTransactionBoundToBooking: (tx?: TransactionBookingBinding | null) => boolean;
@@ -1,9 +1,19 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.canDeletePayments = void 0;
3
+ exports.isTransactionBoundToBooking = exports.canDeletePayments = void 0;
4
4
  /**
5
5
  * Право удалять платежи в бухгалтерии (мягкое удаление).
6
6
  * Владелец (`totalAccess`) — как будто флаг включён.
7
7
  */
8
8
  const canDeletePayments = (role) => !!role?.totalAccess || !!role?.canDeletePayments;
9
9
  exports.canDeletePayments = canDeletePayments;
10
+ /**
11
+ * Платёж привязан к игре (заказ / группа) или сертификату.
12
+ * Такие платежи из раздела «Финансы» не удаляем — только из карточки брони.
13
+ */
14
+ const isTransactionBoundToBooking = (tx) => !!(tx?.orderId ||
15
+ tx?.order?.id ||
16
+ tx?.certificatesaleId ||
17
+ tx?.certificatesale?.id ||
18
+ tx?.orderGroupId);
19
+ exports.isTransactionBoundToBooking = isTransactionBoundToBooking;
@@ -14,3 +14,18 @@ describe('canDeletePayments', () => {
14
14
  expect((0, role_payment_delete_permissions_1.canDeletePayments)({ totalAccess: true, canDeletePayments: false })).toBe(true);
15
15
  });
16
16
  });
17
+ describe('isTransactionBoundToBooking', () => {
18
+ it('treats standalone and salary payments as unbound', () => {
19
+ expect((0, role_payment_delete_permissions_1.isTransactionBoundToBooking)()).toBe(false);
20
+ expect((0, role_payment_delete_permissions_1.isTransactionBoundToBooking)(null)).toBe(false);
21
+ expect((0, role_payment_delete_permissions_1.isTransactionBoundToBooking)({})).toBe(false);
22
+ expect((0, role_payment_delete_permissions_1.isTransactionBoundToBooking)({ order: null, certificatesale: null })).toBe(false);
23
+ });
24
+ it('detects an order, certificate or group booking', () => {
25
+ expect((0, role_payment_delete_permissions_1.isTransactionBoundToBooking)({ order: { id: 1 } })).toBe(true);
26
+ expect((0, role_payment_delete_permissions_1.isTransactionBoundToBooking)({ orderId: 2 })).toBe(true);
27
+ expect((0, role_payment_delete_permissions_1.isTransactionBoundToBooking)({ certificatesale: { id: 3 } })).toBe(true);
28
+ expect((0, role_payment_delete_permissions_1.isTransactionBoundToBooking)({ certificatesaleId: 4 })).toBe(true);
29
+ expect((0, role_payment_delete_permissions_1.isTransactionBoundToBooking)({ orderGroupId: 5 })).toBe(true);
30
+ });
31
+ });
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const weekday_indexes_1 = require("@escapenavigator/types/dist/shared/weekday-indexes");
4
+ describe('toWeekdayIndexes', () => {
5
+ it('оставляет 0…6 и отбрасывает holiday/eve', () => {
6
+ expect((0, weekday_indexes_1.toWeekdayIndexes)([0, 1, 2, 3, 4, 5, 6, 'holiday', 'eve'])).toEqual([
7
+ 0, 1, 2, 3, 4, 5, 6,
8
+ ]);
9
+ });
10
+ it('приводит строковые индексы дней к number', () => {
11
+ expect((0, weekday_indexes_1.toWeekdayIndexes)(['0', '6'])).toEqual([0, 6]);
12
+ });
13
+ it('пустой или битый ввод даёт []', () => {
14
+ expect((0, weekday_indexes_1.toWeekdayIndexes)(['holiday'])).toEqual([]);
15
+ expect((0, weekday_indexes_1.toWeekdayIndexes)(undefined)).toEqual([]);
16
+ expect((0, weekday_indexes_1.toWeekdayIndexes)('holiday')).toEqual([]);
17
+ });
18
+ });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@escapenavigator/utils",
3
- "version": "2.1.18",
3
+ "version": "2.1.19",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },
@@ -14,7 +14,7 @@
14
14
  "test": "jest"
15
15
  },
16
16
  "dependencies": {
17
- "@escapenavigator/types": "^2.1.17",
17
+ "@escapenavigator/types": "^2.1.18",
18
18
  "axios": "^0.21.4",
19
19
  "class-transformer": "^0.5.1",
20
20
  "class-validator": "^0.13.2",
@@ -29,5 +29,5 @@
29
29
  "ts-jest": "^29.1.1",
30
30
  "typescript": "^5.6"
31
31
  },
32
- "gitHead": "7631d0cb80dab71cb8aa84ca78b631568c9f1cc1"
32
+ "gitHead": "acba2e6aea71867d7e53d75398262592238882f6"
33
33
  }