@escapenavigator/types 1.10.107 → 1.10.108

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.
@@ -2,8 +2,12 @@
2
2
  * Сводный отчёт по продажам сертификатов за выбранный период.
3
3
  *
4
4
  * Все денежные суммы — в минимальных единицах валюты (копейки/центы).
5
- * Базовая фильтрация на бэке: `code != NOT_GENERATED_CODE` (висящие
6
- * корзины не учитываем) + `paidAt` в окне `periods`.
5
+ *
6
+ * Когорта периода = `code != NOT_GENERATED_CODE` + `annul = false` +
7
+ * `paidAt ∈ [start, end)`. ВСЕ агрегаты overview (включая остаток
8
+ * номиналов, количество полностью использованных и аннулированных)
9
+ * считаются по одной и той же когорте — это снимает прежний разнобой,
10
+ * когда `outstandingBalance` суммировался по всей истории профиля.
7
11
  *
8
12
  * Семантика финансовых полей:
9
13
  * - gross — стоимость по прайсу (SUM(total)). Не выручка.
@@ -11,13 +15,19 @@
11
15
  * - discount — сумма ручных скидок (SUM(discountTotal)).
12
16
  * - promocode — сумма промокодов (SUM(promocodeTotal)).
13
17
  * - refunded — реально возвращённые клиенту деньги (SUM(refundedAmount)).
18
+ * - nominalSold — суммарный номинал когорты (SUM(nominal)).
19
+ * - nominalRedeemed — сколько из этого номинала уже потрачено в заказах
20
+ * (SUM(usedAmount)).
21
+ * - outstandingBalance — остаток номиналов когорты у ещё не закрытых
22
+ * сертификатов (SUM(balance) WHERE used = false).
23
+ * - redemptionRate — целое число процентов, nominalRedeemed / nominalSold.
14
24
  */
15
25
  export type CertificatesOverview = {
16
26
  /** Сколько сертификатов выписано (paid) за период. */
17
27
  soldCount: number;
18
- /** Сколько аннулировано в этом же периоде (по annulledAt). */
28
+ /** Сколько из когорты уже аннулировано (annul = true к моменту запроса). */
19
29
  annulledCount: number;
20
- /** Сколько использовано полностью (по fullyUsedAt). */
30
+ /** Сколько из когорты уже полностью погашено (fullyUsedAt IS NOT NULL). */
21
31
  fullyUsedCount: number;
22
32
  /** Сколько ушло в подарок (isGift = true) среди soldCount. */
23
33
  giftCount: number;
@@ -28,8 +38,14 @@ export type CertificatesOverview = {
28
38
  refunded: number;
29
39
  /** Средний чек по cash: cash / soldCount, 0 если нет продаж. */
30
40
  avgCheck: number;
31
- /** Не использованный остаток номиналов: SUM(balance) у не-аннулированных. */
41
+ /** Суммарный номинал по когорте: SUM(nominal). */
42
+ nominalSold: number;
43
+ /** Сколько номинала уже потрачено в заказах: SUM(usedAmount). */
44
+ nominalRedeemed: number;
45
+ /** Остаток номиналов когорты у не закрытых сертификатов: SUM(balance) WHERE used = false. */
32
46
  outstandingBalance: number;
47
+ /** Доля погашения номинала, целое число процентов (0..100). */
48
+ redemptionRate: number;
33
49
  };
34
50
  export type CertificatesDynamicRow = {
35
51
  period: string;
@@ -66,6 +82,52 @@ export type CertificatesByUtmRow = {
66
82
  soldCount: number;
67
83
  cash: number;
68
84
  };
85
+ /**
86
+ * Бакеты «через сколько дней после покупки сертификат…»
87
+ * - d0 — в день покупки
88
+ * - d1_7 — 1..7 дней
89
+ * - d8_30 — 8..30 дней
90
+ * - d31_90 — 31..90 дней
91
+ * - d91_180 — 91..180 дней
92
+ * - d181_365 — 181..365 дней
93
+ * - d_over_365 — больше года
94
+ * - not_yet — ещё не активирован / не погашен полностью
95
+ */
96
+ export type CertificatesVelocityBucket = 'd0' | 'd1_7' | 'd8_30' | 'd31_90' | 'd91_180' | 'd181_365' | 'd_over_365' | 'not_yet';
97
+ export type CertificatesVelocityBucketRow = {
98
+ bucket: CertificatesVelocityBucket;
99
+ /** Сколько сертификатов когорты попало в бакет. */
100
+ count: number;
101
+ };
102
+ /**
103
+ * Скорость использования сертификатов когорты периода.
104
+ *
105
+ * Когорта = `code != NOT_GENERATED_CODE` + `annul = false` +
106
+ * `paidAt ∈ [start, end)`. Источники дат — `firstUsedAt`, `fullyUsedAt`,
107
+ * `expireDate`. Никаких джоинов — считаем по плоской `certificatesales`.
108
+ */
109
+ export type CertificatesRedemptionVelocity = {
110
+ /** Распределение времени до первого применения. */
111
+ firstUseBuckets: CertificatesVelocityBucketRow[];
112
+ /** Распределение времени до полного погашения. */
113
+ fullRedeemBuckets: CertificatesVelocityBucketRow[];
114
+ /** Медианное число дней от покупки до первого применения. */
115
+ medianDaysToFirstUse: number | null;
116
+ /** Медианное число дней от покупки до полного погашения. */
117
+ medianDaysToFullRedeem: number | null;
118
+ /** Активировано в течение 7 дней после покупки. */
119
+ activatedWithin7d: number;
120
+ /** Активировано в течение 30 дней после покупки. */
121
+ activatedWithin30d: number;
122
+ /** Полностью погашено в течение 30 дней после покупки. */
123
+ fullyRedeemedWithin30d: number;
124
+ /** Полностью погашено в течение 90 дней после покупки. */
125
+ fullyRedeemedWithin90d: number;
126
+ /** «Спящие» — куплены больше 90 дней назад и ни разу не применены. */
127
+ dormantOver90d: number;
128
+ /** Сгорели (expireDate < сегодня) и не были полностью использованы. */
129
+ expiredUnused: number;
130
+ };
69
131
  export type CertificatesReportRO = {
70
132
  overview: CertificatesOverview;
71
133
  dynamic: CertificatesDynamicRow[];
@@ -73,4 +135,5 @@ export type CertificatesReportRO = {
73
135
  bySource: CertificatesBySourceRow[];
74
136
  byDelivery: CertificatesByDeliveryRow[];
75
137
  byUtm: CertificatesByUtmRow[];
138
+ redemption: CertificatesRedemptionVelocity;
76
139
  };