@mamindom/contracts 1.0.129 → 1.0.131

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.
@@ -10,6 +10,27 @@ import { Observable } from "rxjs";
10
10
 
11
11
  export const protobufPackage = "notification.v1";
12
12
 
13
+ export enum CampaignStatusEnum {
14
+ CAMPAIGN_STATUS_UNSPECIFIED = 0,
15
+ DRAFT = 1,
16
+ SCHEDULED = 2,
17
+ RUNNING = 3,
18
+ COMPLETED = 4,
19
+ CANCELLED = 5,
20
+ CAMPAIGN_FAILED = 6,
21
+ UNRECOGNIZED = -1,
22
+ }
23
+
24
+ export enum CampaignRecipientStatusEnum {
25
+ CAMPAIGN_RECIPIENT_UNSPECIFIED = 0,
26
+ RECIPIENT_PENDING = 1,
27
+ RECIPIENT_SENT = 2,
28
+ RECIPIENT_FAILED = 3,
29
+ RECIPIENT_SKIPPED_OPT_OUT = 4,
30
+ RECIPIENT_SKIPPED_NO_CONTACT = 5,
31
+ UNRECOGNIZED = -1,
32
+ }
33
+
13
34
  export enum NotificationChannel {
14
35
  NOTIFICATION_CHANNEL_UNSPECIFIED = 0,
15
36
  EMAIL = 1,
@@ -59,6 +80,210 @@ export enum TelegramTopic {
59
80
  UNRECOGNIZED = -1,
60
81
  }
61
82
 
83
+ /**
84
+ * SendToCustomer — викликається з gateway після того, як клієнтський контакт
85
+ * (email/phone) вже резолвнений і опційно згенерований персональний купон.
86
+ */
87
+ export interface SendToCustomerRequest {
88
+ /** userId з auth-service — пишемо в NotificationLog.user_id для зведень. */
89
+ userId: string;
90
+ channel: NotificationChannel;
91
+ /** Recipient — email або phone, заздалегідь визначені gateway з акаунта. */
92
+ recipient: string;
93
+ /** Шлях 1: templateId — рендеримо існуючий шаблон з variables. */
94
+ templateId?:
95
+ | string
96
+ | undefined;
97
+ /**
98
+ * Шлях 2: ad-hoc контент. Якщо template_id порожній — використовуємо ці поля.
99
+ * body_html — для EMAIL (буде обгорнутий брендингом).
100
+ * body_text — для SMS (plain text) або текстова версія email.
101
+ */
102
+ customSubject?: string | undefined;
103
+ customBodyHtml?: string | undefined;
104
+ customBodyText?:
105
+ | string
106
+ | undefined;
107
+ /** JSON з placeholders для Handlebars: { "coupon_code": "...", ... } */
108
+ variablesJson: string;
109
+ /** Locale для пошуку версії шаблону + надсилання branding-обгортки. */
110
+ locale?: NotificationLocale | undefined;
111
+ }
112
+
113
+ export interface SendToCustomerResponse {
114
+ ok: boolean;
115
+ errorMessage: string;
116
+ /** id запису в NotificationLog (для трекінгу в /notifications/logs). */
117
+ logId: string;
118
+ }
119
+
120
+ export interface EnqueueRecipientsRequest {
121
+ campaignId: string;
122
+ recipients: CampaignResolvedRecipient[];
123
+ }
124
+
125
+ export interface CampaignResolvedRecipient {
126
+ userId: string;
127
+ /** email або phone */
128
+ recipient: string;
129
+ /**
130
+ * true → у клієнта promotions=false. dispatcher позначить SKIPPED_OPT_OUT
131
+ * якщо respect_opt_out=true для кампанії.
132
+ */
133
+ optOut: boolean;
134
+ /**
135
+ * Унікальний код, згенерований gateway через CouponsService.CreateCoupon.
136
+ * Підставляється у шаблон як {{coupon_code}}.
137
+ */
138
+ couponCode?: string | undefined;
139
+ }
140
+
141
+ export interface EnqueueRecipientsResponse {
142
+ enqueued: number;
143
+ }
144
+
145
+ export interface ListCampaignsRequest {
146
+ status?: CampaignStatusEnum | undefined;
147
+ page?: number | undefined;
148
+ limit?: number | undefined;
149
+ }
150
+
151
+ export interface ListCampaignsResponse {
152
+ items: Campaign[];
153
+ total: number;
154
+ }
155
+
156
+ export interface GetCampaignRequest {
157
+ id: string;
158
+ }
159
+
160
+ export interface DeleteCampaignRequest {
161
+ id: string;
162
+ }
163
+
164
+ export interface DeleteCampaignResponse {
165
+ ok: boolean;
166
+ }
167
+
168
+ export interface StartCampaignRequest {
169
+ id: string;
170
+ /** ISO date; якщо порожньо → запустити одразу. */
171
+ scheduledAt?: string | undefined;
172
+ }
173
+
174
+ export interface CancelCampaignRequest {
175
+ id: string;
176
+ }
177
+
178
+ export interface CreateCampaignRequest {
179
+ name: string;
180
+ channel: NotificationChannel;
181
+ templateId?: string | undefined;
182
+ customSubject?: string | undefined;
183
+ customBodyHtml?: string | undefined;
184
+ customBodyText?:
185
+ | string
186
+ | undefined;
187
+ /** JSON segment spec. */
188
+ segmentJson: string;
189
+ /** JSON coupon spec — null/empty для кампаній без купонів. */
190
+ couponSpecJson?: string | undefined;
191
+ respectOptOut: boolean;
192
+ locale?: NotificationLocale | undefined;
193
+ createdById: string;
194
+ }
195
+
196
+ export interface UpdateCampaignRequest {
197
+ id: string;
198
+ /** Можна оновлювати тільки DRAFT — гілки нижче опційні. */
199
+ name?: string | undefined;
200
+ channel?: NotificationChannel | undefined;
201
+ templateId?: string | undefined;
202
+ customSubject?: string | undefined;
203
+ customBodyHtml?: string | undefined;
204
+ customBodyText?: string | undefined;
205
+ segmentJson?: string | undefined;
206
+ couponSpecJson?: string | undefined;
207
+ respectOptOut?: boolean | undefined;
208
+ locale?: NotificationLocale | undefined;
209
+ }
210
+
211
+ export interface CampaignResponse {
212
+ ok: boolean;
213
+ errorMessage: string;
214
+ campaign: Campaign | undefined;
215
+ }
216
+
217
+ export interface Campaign {
218
+ id: string;
219
+ name: string;
220
+ channel: NotificationChannel;
221
+ templateId?: string | undefined;
222
+ customSubject?: string | undefined;
223
+ customBodyHtml?: string | undefined;
224
+ customBodyText?: string | undefined;
225
+ locale: NotificationLocale;
226
+ segmentJson: string;
227
+ couponSpecJson?: string | undefined;
228
+ respectOptOut: boolean;
229
+ status: CampaignStatusEnum;
230
+ scheduledAt?: string | undefined;
231
+ startedAt?: string | undefined;
232
+ completedAt?: string | undefined;
233
+ totalRecipients: number;
234
+ sentCount: number;
235
+ failedCount: number;
236
+ skippedOptOutCount: number;
237
+ createdById: string;
238
+ createdAt: string;
239
+ updatedAt: string;
240
+ }
241
+
242
+ export interface PreviewSegmentRequest {
243
+ segmentJson: string;
244
+ /** потрібно для перевірки наявності email/phone */
245
+ channel: NotificationChannel;
246
+ }
247
+
248
+ export interface PreviewSegmentResponse {
249
+ totalCount: number;
250
+ /** Перші 10 для UI; решта — за необхідності окремим запитом. */
251
+ sample: PreviewSegmentSample[];
252
+ }
253
+
254
+ export interface PreviewSegmentSample {
255
+ userId: string;
256
+ firstName: string;
257
+ lastName: string;
258
+ email: string;
259
+ phone: string;
260
+ }
261
+
262
+ export interface ListRecipientsRequest {
263
+ campaignId: string;
264
+ status?: CampaignRecipientStatusEnum | undefined;
265
+ page?: number | undefined;
266
+ limit?: number | undefined;
267
+ }
268
+
269
+ export interface ListRecipientsResponse {
270
+ items: CampaignRecipient[];
271
+ total: number;
272
+ }
273
+
274
+ export interface CampaignRecipient {
275
+ id: string;
276
+ campaignId: string;
277
+ userId: string;
278
+ recipient: string;
279
+ status: CampaignRecipientStatusEnum;
280
+ couponCode?: string | undefined;
281
+ notificationLogId?: string | undefined;
282
+ errorMessage?: string | undefined;
283
+ sentAt?: string | undefined;
284
+ createdAt: string;
285
+ }
286
+
62
287
  export interface BrandingEmpty {
63
288
  }
64
289
 
@@ -82,6 +307,8 @@ export interface BrandingProfile {
82
307
  resolvedBrandName: string;
83
308
  resolvedBrandUrl: string;
84
309
  resolvedSupportEmail: string;
310
+ /** Кастомний HTML-хедер (замість дефолтного логотип-блоку). Порожньо → default. */
311
+ headerHtml: string;
85
312
  }
86
313
 
87
314
  export interface UpdateBrandingRequest {
@@ -92,6 +319,7 @@ export interface UpdateBrandingRequest {
92
319
  supportEmail?: string | undefined;
93
320
  footerHtml?: string | undefined;
94
321
  actorId: string;
322
+ headerHtml?: string | undefined;
95
323
  }
96
324
 
97
325
  export interface NotificationTemplate {
@@ -203,7 +431,14 @@ export interface RenderPreviewRequest {
203
431
  bodyHtml: string;
204
432
  /** JSON-stringified variables { "order.number": "MD-2026-0001", ... } */
205
433
  variablesJson: string;
206
- subject?: string | undefined;
434
+ subject?:
435
+ | string
436
+ | undefined;
437
+ /**
438
+ * JSON-stringified branding override (header/footer/logo/brand…) для live-
439
+ * превʼю незбережених змін на сторінці брендингу. Порожньо → беремо з БД.
440
+ */
441
+ brandingJson?: string | undefined;
207
442
  }
208
443
 
209
444
  export interface RenderPreviewResponse {
@@ -330,6 +565,10 @@ export interface NotificationTemplateServiceClient {
330
565
  renderPreview(request: RenderPreviewRequest): Observable<RenderPreviewResponse>;
331
566
 
332
567
  sendTest(request: SendTestRequest): Observable<SendTestResponse>;
568
+
569
+ /** Реальна відправка клієнту з адмінки — або по шаблону, або ad-hoc body. */
570
+
571
+ sendToCustomer(request: SendToCustomerRequest): Observable<SendToCustomerResponse>;
333
572
  }
334
573
 
335
574
  export interface NotificationTemplateServiceController {
@@ -364,6 +603,12 @@ export interface NotificationTemplateServiceController {
364
603
  ): Promise<RenderPreviewResponse> | Observable<RenderPreviewResponse> | RenderPreviewResponse;
365
604
 
366
605
  sendTest(request: SendTestRequest): Promise<SendTestResponse> | Observable<SendTestResponse> | SendTestResponse;
606
+
607
+ /** Реальна відправка клієнту з адмінки — або по шаблону, або ad-hoc body. */
608
+
609
+ sendToCustomer(
610
+ request: SendToCustomerRequest,
611
+ ): Promise<SendToCustomerResponse> | Observable<SendToCustomerResponse> | SendToCustomerResponse;
367
612
  }
368
613
 
369
614
  export function NotificationTemplateServiceControllerMethods() {
@@ -378,6 +623,7 @@ export function NotificationTemplateServiceControllerMethods() {
378
623
  "restoreVersion",
379
624
  "renderPreview",
380
625
  "sendTest",
626
+ "sendToCustomer",
381
627
  ];
382
628
  for (const method of grpcMethods) {
383
629
  const descriptor: any = Reflect.getOwnPropertyDescriptor(constructor.prototype, method);
@@ -461,6 +707,118 @@ export function TelegramChatsServiceControllerMethods() {
461
707
 
462
708
  export const TELEGRAM_CHATS_SERVICE_NAME = "TelegramChatsService";
463
709
 
710
+ /** Маркетингові кампанії: створення, запуск, статистика. */
711
+
712
+ export interface CampaignsServiceClient {
713
+ listCampaigns(request: ListCampaignsRequest): Observable<ListCampaignsResponse>;
714
+
715
+ getCampaign(request: GetCampaignRequest): Observable<CampaignResponse>;
716
+
717
+ createCampaign(request: CreateCampaignRequest): Observable<CampaignResponse>;
718
+
719
+ updateCampaign(request: UpdateCampaignRequest): Observable<CampaignResponse>;
720
+
721
+ deleteCampaign(request: DeleteCampaignRequest): Observable<DeleteCampaignResponse>;
722
+
723
+ startCampaign(request: StartCampaignRequest): Observable<CampaignResponse>;
724
+
725
+ cancelCampaign(request: CancelCampaignRequest): Observable<CampaignResponse>;
726
+
727
+ /** Превью сегменту — повертає кількість + перші N клієнтів, БЕЗ створення кампанії. */
728
+
729
+ previewSegment(request: PreviewSegmentRequest): Observable<PreviewSegmentResponse>;
730
+
731
+ /** Список отримувачів конкретної кампанії з їхніми статусами. */
732
+
733
+ listRecipients(request: ListRecipientsRequest): Observable<ListRecipientsResponse>;
734
+
735
+ /**
736
+ * Викликається з gateway після того, як сегмент резолвнено клієнтами —
737
+ * передається список {userId, recipient}, нотифікація розкладає у чергу.
738
+ */
739
+
740
+ enqueueRecipients(request: EnqueueRecipientsRequest): Observable<EnqueueRecipientsResponse>;
741
+ }
742
+
743
+ /** Маркетингові кампанії: створення, запуск, статистика. */
744
+
745
+ export interface CampaignsServiceController {
746
+ listCampaigns(
747
+ request: ListCampaignsRequest,
748
+ ): Promise<ListCampaignsResponse> | Observable<ListCampaignsResponse> | ListCampaignsResponse;
749
+
750
+ getCampaign(request: GetCampaignRequest): Promise<CampaignResponse> | Observable<CampaignResponse> | CampaignResponse;
751
+
752
+ createCampaign(
753
+ request: CreateCampaignRequest,
754
+ ): Promise<CampaignResponse> | Observable<CampaignResponse> | CampaignResponse;
755
+
756
+ updateCampaign(
757
+ request: UpdateCampaignRequest,
758
+ ): Promise<CampaignResponse> | Observable<CampaignResponse> | CampaignResponse;
759
+
760
+ deleteCampaign(
761
+ request: DeleteCampaignRequest,
762
+ ): Promise<DeleteCampaignResponse> | Observable<DeleteCampaignResponse> | DeleteCampaignResponse;
763
+
764
+ startCampaign(
765
+ request: StartCampaignRequest,
766
+ ): Promise<CampaignResponse> | Observable<CampaignResponse> | CampaignResponse;
767
+
768
+ cancelCampaign(
769
+ request: CancelCampaignRequest,
770
+ ): Promise<CampaignResponse> | Observable<CampaignResponse> | CampaignResponse;
771
+
772
+ /** Превью сегменту — повертає кількість + перші N клієнтів, БЕЗ створення кампанії. */
773
+
774
+ previewSegment(
775
+ request: PreviewSegmentRequest,
776
+ ): Promise<PreviewSegmentResponse> | Observable<PreviewSegmentResponse> | PreviewSegmentResponse;
777
+
778
+ /** Список отримувачів конкретної кампанії з їхніми статусами. */
779
+
780
+ listRecipients(
781
+ request: ListRecipientsRequest,
782
+ ): Promise<ListRecipientsResponse> | Observable<ListRecipientsResponse> | ListRecipientsResponse;
783
+
784
+ /**
785
+ * Викликається з gateway після того, як сегмент резолвнено клієнтами —
786
+ * передається список {userId, recipient}, нотифікація розкладає у чергу.
787
+ */
788
+
789
+ enqueueRecipients(
790
+ request: EnqueueRecipientsRequest,
791
+ ): Promise<EnqueueRecipientsResponse> | Observable<EnqueueRecipientsResponse> | EnqueueRecipientsResponse;
792
+ }
793
+
794
+ export function CampaignsServiceControllerMethods() {
795
+ return function (constructor: Function) {
796
+ const grpcMethods: string[] = [
797
+ "listCampaigns",
798
+ "getCampaign",
799
+ "createCampaign",
800
+ "updateCampaign",
801
+ "deleteCampaign",
802
+ "startCampaign",
803
+ "cancelCampaign",
804
+ "previewSegment",
805
+ "listRecipients",
806
+ "enqueueRecipients",
807
+ ];
808
+ for (const method of grpcMethods) {
809
+ const descriptor: any = Reflect.getOwnPropertyDescriptor(constructor.prototype, method);
810
+ GrpcMethod("CampaignsService", method)(constructor.prototype[method], method, descriptor);
811
+ }
812
+ const grpcStreamMethods: string[] = [];
813
+ for (const method of grpcStreamMethods) {
814
+ const descriptor: any = Reflect.getOwnPropertyDescriptor(constructor.prototype, method);
815
+ GrpcStreamMethod("CampaignsService", method)(constructor.prototype[method], method, descriptor);
816
+ }
817
+ };
818
+ }
819
+
820
+ export const CAMPAIGNS_SERVICE_NAME = "CampaignsService";
821
+
464
822
  /** Брендинг email-шаблонів — singleton редагується адміном. */
465
823
 
466
824
  export interface BrandingServiceClient {
package/gen/order.ts CHANGED
@@ -10,6 +10,23 @@ import { Observable } from "rxjs";
10
10
 
11
11
  export const protobufPackage = "order.v1";
12
12
 
13
+ export interface AggregateByCustomersRequest {
14
+ userIds: string[];
15
+ }
16
+
17
+ export interface CustomerOrderAggregate {
18
+ userId: string;
19
+ ordersCount: number;
20
+ /** Decimal у вигляді рядка ('1234.56') — щоб не втратити точність на gRPC border. */
21
+ totalSum: string;
22
+ /** ISO-рядок, відсутній якщо клієнт ще не робив замовлень. */
23
+ lastOrderAt?: string | undefined;
24
+ }
25
+
26
+ export interface AggregateByCustomersResponse {
27
+ items: CustomerOrderAggregate[];
28
+ }
29
+
13
30
  export interface OrderItem {
14
31
  id: string;
15
32
  productId: string;
@@ -325,6 +342,10 @@ export interface OrderServiceClient {
325
342
  reorderOrder(request: ReorderOrderRequest): Observable<ReorderResponse>;
326
343
 
327
344
  listHistory(request: ListHistoryRequest): Observable<ListHistoryResponse>;
345
+
346
+ /** CRM-агрегація для експорту клієнтів — повертає count/sum/last для кожного userId. */
347
+
348
+ aggregateByCustomers(request: AggregateByCustomersRequest): Observable<AggregateByCustomersResponse>;
328
349
  }
329
350
 
330
351
  export interface OrderServiceController {
@@ -371,6 +392,12 @@ export interface OrderServiceController {
371
392
  listHistory(
372
393
  request: ListHistoryRequest,
373
394
  ): Promise<ListHistoryResponse> | Observable<ListHistoryResponse> | ListHistoryResponse;
395
+
396
+ /** CRM-агрегація для експорту клієнтів — повертає count/sum/last для кожного userId. */
397
+
398
+ aggregateByCustomers(
399
+ request: AggregateByCustomersRequest,
400
+ ): Promise<AggregateByCustomersResponse> | Observable<AggregateByCustomersResponse> | AggregateByCustomersResponse;
374
401
  }
375
402
 
376
403
  export function OrderServiceControllerMethods() {
@@ -392,6 +419,7 @@ export function OrderServiceControllerMethods() {
392
419
  "setTrackingNumber",
393
420
  "reorderOrder",
394
421
  "listHistory",
422
+ "aggregateByCustomers",
395
423
  ];
396
424
  for (const method of grpcMethods) {
397
425
  const descriptor: any = Reflect.getOwnPropertyDescriptor(constructor.prototype, method);
package/gen/users.ts CHANGED
@@ -62,6 +62,21 @@ export interface User {
62
62
  bonuses: number;
63
63
  email?: string | undefined;
64
64
  phone?: string | undefined;
65
+ internalNote?: string | undefined;
66
+ }
67
+
68
+ export interface AdminUpdateCustomerRequest {
69
+ id: string;
70
+ firstName?: string | undefined;
71
+ lastName?:
72
+ | string
73
+ | undefined;
74
+ /** internal_note редагується тут окремо, бо це CRM-поле — не видиме клієнту. */
75
+ internalNote?: string | undefined;
76
+ }
77
+
78
+ export interface AdminUpdateCustomerResponse {
79
+ user: User | undefined;
65
80
  }
66
81
 
67
82
  export interface NotificationSettings {
@@ -378,6 +393,10 @@ export interface UsersServiceClient {
378
393
  clearCart(request: ClearCartRequest): Observable<ClearCartResponse>;
379
394
 
380
395
  syncCart(request: SyncCartRequest): Observable<GetCartResponse>;
396
+
397
+ /** Admin CRM — редагування клієнта менеджером (customers.edit на gateway). */
398
+
399
+ adminUpdateCustomer(request: AdminUpdateCustomerRequest): Observable<AdminUpdateCustomerResponse>;
381
400
  }
382
401
 
383
402
  export interface UsersServiceController {
@@ -481,6 +500,12 @@ export interface UsersServiceController {
481
500
  clearCart(request: ClearCartRequest): Promise<ClearCartResponse> | Observable<ClearCartResponse> | ClearCartResponse;
482
501
 
483
502
  syncCart(request: SyncCartRequest): Promise<GetCartResponse> | Observable<GetCartResponse> | GetCartResponse;
503
+
504
+ /** Admin CRM — редагування клієнта менеджером (customers.edit на gateway). */
505
+
506
+ adminUpdateCustomer(
507
+ request: AdminUpdateCustomerRequest,
508
+ ): Promise<AdminUpdateCustomerResponse> | Observable<AdminUpdateCustomerResponse> | AdminUpdateCustomerResponse;
484
509
  }
485
510
 
486
511
  export function UsersServiceControllerMethods() {
@@ -513,6 +538,7 @@ export function UsersServiceControllerMethods() {
513
538
  "removeCartItem",
514
539
  "clearCart",
515
540
  "syncCart",
541
+ "adminUpdateCustomer",
516
542
  ];
517
543
  for (const method of grpcMethods) {
518
544
  const descriptor: any = Reflect.getOwnPropertyDescriptor(constructor.prototype, method);
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@mamindom/contracts",
3
3
  "description": "proto",
4
- "version": "1.0.129",
4
+ "version": "1.0.131",
5
5
  "main": "./dist/src/index.js",
6
6
  "types": "./dist/src/index.d.ts",
7
7
  "exports": {