@mamindom/contracts 1.0.143 → 1.0.145

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 (97) hide show
  1. package/dist/gen/attribute.d.ts +40 -0
  2. package/dist/gen/attribute.js +1 -0
  3. package/dist/gen/brand.d.ts +19 -0
  4. package/dist/gen/brand.js +8 -1
  5. package/dist/gen/bundle.d.ts +0 -2
  6. package/dist/gen/cart.d.ts +0 -28
  7. package/dist/gen/category.d.ts +26 -0
  8. package/dist/gen/category.js +1 -0
  9. package/dist/gen/delivery.d.ts +0 -1
  10. package/dist/gen/delivery_settings.d.ts +0 -4
  11. package/dist/gen/faq.d.ts +0 -6
  12. package/dist/gen/manager.d.ts +0 -12
  13. package/dist/gen/notification.d.ts +0 -71
  14. package/dist/gen/order.d.ts +0 -29
  15. package/dist/gen/page.d.ts +0 -5
  16. package/dist/gen/payment.d.ts +0 -22
  17. package/dist/gen/pickup.d.ts +0 -9
  18. package/dist/gen/product.d.ts +107 -11
  19. package/dist/gen/product.js +4 -0
  20. package/dist/gen/promotion.d.ts +0 -16
  21. package/dist/gen/rbac.d.ts +0 -16
  22. package/dist/gen/search.d.ts +0 -14
  23. package/dist/gen/seo_filter.d.ts +16 -48
  24. package/dist/gen/seo_filter.js +1 -0
  25. package/dist/gen/shop_filters.d.ts +0 -5
  26. package/dist/gen/users.d.ts +0 -9
  27. package/dist/gen/warehouse.d.ts +34 -0
  28. package/dist/gen/warehouse.js +28 -0
  29. package/dist/proto/attribute.proto +35 -0
  30. package/dist/proto/brand.proto +25 -0
  31. package/dist/proto/bundle.proto +2 -2
  32. package/dist/proto/cart.proto +5 -14
  33. package/dist/proto/category.proto +26 -0
  34. package/dist/proto/delivery.proto +1 -6
  35. package/dist/proto/delivery_settings.proto +4 -4
  36. package/dist/proto/faq.proto +3 -10
  37. package/dist/proto/manager.proto +3 -5
  38. package/dist/proto/notification.proto +33 -56
  39. package/dist/proto/order.proto +9 -21
  40. package/dist/proto/page.proto +1 -3
  41. package/dist/proto/payment.proto +8 -14
  42. package/dist/proto/pickup.proto +7 -9
  43. package/dist/proto/product.proto +129 -18
  44. package/dist/proto/promotion.proto +9 -22
  45. package/dist/proto/rbac.proto +7 -9
  46. package/dist/proto/search.proto +10 -14
  47. package/dist/proto/seo_filter.proto +37 -32
  48. package/dist/proto/shop_filters.proto +1 -3
  49. package/dist/proto/users.proto +5 -8
  50. package/dist/proto/warehouse.proto +38 -0
  51. package/dist/src/proto/paths.d.ts +1 -0
  52. package/dist/src/proto/paths.js +1 -0
  53. package/gen/attribute.ts +48 -0
  54. package/gen/brand.ts +35 -1
  55. package/gen/bundle.ts +1 -5
  56. package/gen/cart.ts +1 -35
  57. package/gen/category.ts +34 -0
  58. package/gen/delivery.ts +0 -1
  59. package/gen/delivery_settings.ts +0 -4
  60. package/gen/faq.ts +0 -12
  61. package/gen/manager.ts +1 -17
  62. package/gen/notification.ts +5 -98
  63. package/gen/order.ts +0 -33
  64. package/gen/page.ts +0 -5
  65. package/gen/payment.ts +0 -34
  66. package/gen/pickup.ts +2 -19
  67. package/gen/product.ts +147 -28
  68. package/gen/promotion.ts +3 -33
  69. package/gen/rbac.ts +1 -25
  70. package/gen/search.ts +0 -22
  71. package/gen/seo_filter.ts +27 -63
  72. package/gen/shop_filters.ts +0 -5
  73. package/gen/users.ts +1 -20
  74. package/gen/warehouse.ts +67 -0
  75. package/package.json +1 -1
  76. package/proto/attribute.proto +35 -0
  77. package/proto/brand.proto +25 -0
  78. package/proto/bundle.proto +2 -2
  79. package/proto/cart.proto +5 -14
  80. package/proto/category.proto +26 -0
  81. package/proto/delivery.proto +1 -6
  82. package/proto/delivery_settings.proto +4 -4
  83. package/proto/faq.proto +3 -10
  84. package/proto/manager.proto +3 -5
  85. package/proto/notification.proto +33 -56
  86. package/proto/order.proto +9 -21
  87. package/proto/page.proto +1 -3
  88. package/proto/payment.proto +8 -14
  89. package/proto/pickup.proto +7 -9
  90. package/proto/product.proto +129 -18
  91. package/proto/promotion.proto +9 -22
  92. package/proto/rbac.proto +7 -9
  93. package/proto/search.proto +10 -14
  94. package/proto/seo_filter.proto +37 -32
  95. package/proto/shop_filters.proto +1 -3
  96. package/proto/users.proto +5 -8
  97. package/proto/warehouse.proto +38 -0
@@ -15,6 +15,18 @@ service ProductService {
15
15
  rpc DeleteProduct (DeleteProductRequest) returns (DeleteResponse);
16
16
  rpc SetManualRating (SetManualRatingRequest) returns (SuccessResponse);
17
17
 
18
+
19
+ rpc UpsertProducts (UpsertProductsRequest) returns (UpsertProductsResponse);
20
+
21
+
22
+ rpc UpsertPrices (UpsertPricesRequest) returns (UpsertPricesResponse);
23
+
24
+
25
+ rpc UpsertCharacteristics (UpsertCharacteristicsRequest) returns (UpsertCharacteristicsResponse);
26
+
27
+
28
+ rpc UpsertStocks (UpsertStocksRequest) returns (UpsertStocksResponse);
29
+
18
30
 
19
31
  rpc BulkUpdateStatus (BulkUpdateStatusRequest) returns (SuccessResponse);
20
32
  rpc BulkUpdateCategory (BulkUpdateCategoryRequest) returns (SuccessResponse);
@@ -74,7 +86,7 @@ rpc AssignVariantSizeCharts (AssignVariantSizeChartsRequest) returns (SuccessRes
74
86
  rpc RemoveVariantSizeChart (RemoveVariantSizeChartRequest) returns (SuccessResponse);
75
87
  rpc GetVariantSizeCharts (GetVariantSizeChartsRequest) returns (GetProductSizeChartsResponse);
76
88
 
77
- // ─── Product colors (нова ієрархія: Product → Color → Variant) ──────────────
89
+
78
90
  rpc CreateProductColor (CreateProductColorRequest) returns (ProductColorResponse);
79
91
  rpc UpdateProductColor (UpdateProductColorRequest) returns (ProductColorResponse);
80
92
  rpc DeleteProductColor (DeleteProductColorRequest) returns (DeleteResponse);
@@ -170,7 +182,7 @@ message ProductListItemResponse {
170
182
  int32 review_count = 21;
171
183
  repeated ProductStickerResponse stickers = 22;
172
184
  optional ProductPromoInfo active_promo = 23;
173
- // Вага у кг для розрахунку доставки (0 → fallback на defaultItemWeightKg).
185
+
174
186
  double weight_kg = 24;
175
187
  }
176
188
 
@@ -221,7 +233,7 @@ message ProductDetailResponse {
221
233
  optional float manual_rating = 37;
222
234
  optional ProductPromoInfo active_promo = 38;
223
235
  repeated ProductColorResponse colors = 39;
224
- // Вага товару у кг для розрахунку доставки (variant може override'ити).
236
+
225
237
  double weight_kg = 40;
226
238
  }
227
239
 
@@ -630,7 +642,7 @@ message ProductVariantDetailResponse {
630
642
 
631
643
  optional string color_id = 21;
632
644
 
633
- // Override-вага варіанту у кг; 0 означає "успадкувати від продукту".
645
+
634
646
  double weight_kg = 22;
635
647
  }
636
648
 
@@ -673,7 +685,7 @@ message CreateProductVariantRequest {
673
685
  repeated ProductImagePayload images = 17;
674
686
  repeated string attribute_value_ids = 18;
675
687
  optional string color_id = 19;
676
- // Override-вага варіанту у кг (null/unset → успадкувати від продукту).
688
+
677
689
  optional double weight_kg = 20;
678
690
  }
679
691
 
@@ -702,7 +714,7 @@ message UpdateProductVariantRequest {
702
714
  repeated ProductImagePayload images = 17;
703
715
  repeated string attribute_value_ids = 18;
704
716
  optional string color_id = 19;
705
- // Override-вага варіанту у кг (null/unset → успадкувати від продукту).
717
+
706
718
  optional double weight_kg = 20;
707
719
 
708
720
 
@@ -740,8 +752,6 @@ message GetVariantSizeChartsRequest {
740
752
  }
741
753
 
742
754
 
743
- // ─── Bulk lookup by SKU / barcode ─────────────────────────────────────────────
744
-
745
755
  enum IdentifierType {
746
756
  IDENTIFIER_TYPE_UNSPECIFIED = 0;
747
757
  IDENTIFIER_TYPE_SKU = 1;
@@ -768,29 +778,24 @@ message BulkLookupProductsResponse {
768
778
  repeated ProductLookupResult results = 1;
769
779
  }
770
780
 
771
- // ─── Bulk lookup variants by ID (for cart price snapshot) ────────────────────
772
- //
773
- // Використовується cart-service для отримання актуальної ціни саме за варіантом
774
- // (variant.price якщо has_own_price, інакше product.price). Повертає достатньо
775
- // для побудови line snapshot: ціна/стара ціна/назва/sku/stock/main_image.
776
781
 
777
782
  message VariantLookupResult {
778
783
  string variant_id = 1;
779
784
  string product_id = 2;
780
785
  string sku = 3;
781
786
  bool found = 4;
782
- // Резолвлена з урахуванням variant override.
787
+
783
788
  double price = 5;
784
789
  optional double old_price = 6;
785
790
  int32 stock = 7;
786
791
  bool has_own_price = 8;
787
- // Локалізована назва (uk → ru → перше) для зручності клієнта.
792
+
788
793
  string name_uk = 9;
789
794
  string main_image = 10;
790
795
  optional string color_id = 11;
791
- // Вага у кг (variant.weight_kg ?? product.weight_kg ?? 0).
796
+
792
797
  double weight_kg = 12;
793
- // Розмір з variant.options.size — для відображення у замовленнях.
798
+
794
799
  string size = 13;
795
800
  }
796
801
 
@@ -803,7 +808,6 @@ message BulkLookupVariantsResponse {
803
808
  }
804
809
 
805
810
 
806
- // ─── Product colors ──────────────────────────────────────────────────────────
807
811
 
808
812
  message ProductColorImagePayload {
809
813
  string url = 1;
@@ -881,4 +885,111 @@ message ReorderProductColorsRequest {
881
885
  message ColorSortOrderItem {
882
886
  string color_id = 1;
883
887
  int32 sort_order = 2;
888
+ }
889
+
890
+
891
+ message ProductSyncItem {
892
+ string product_guid = 1;
893
+ string sku = 2;
894
+ map<string, string> name = 3;
895
+ optional string brand_value_guid = 4;
896
+ repeated string attribute_value_guids = 5;
897
+ repeated string characteristic_guids = 6;
898
+ repeated string category_guids = 7;
899
+ }
900
+
901
+ message UpsertProductsRequest {
902
+ repeated ProductSyncItem items = 1;
903
+ string sync_id = 2;
904
+ string created_by = 3;
905
+ string color_property_guid = 4;
906
+ }
907
+
908
+ message ProductUpsertResult {
909
+ string guid = 1;
910
+ string status = 2;
911
+ optional string reason = 3;
912
+ optional string id = 4;
913
+ int32 attributes_linked = 5;
914
+ int32 attributes_skipped = 6;
915
+ int32 variants_created = 7;
916
+ int32 variants_updated = 8;
917
+ int32 variants_skipped = 9;
918
+ }
919
+
920
+ message UpsertProductsResponse {
921
+ repeated ProductUpsertResult results = 1;
922
+ }
923
+
924
+ message PriceSyncItem {
925
+ string product_guid = 1;
926
+ optional string characteristic_guid = 2;
927
+ double price = 3;
928
+ optional double old_price = 4;
929
+ }
930
+
931
+ message UpsertPricesRequest {
932
+ repeated PriceSyncItem items = 1;
933
+ string sync_id = 2;
934
+ }
935
+
936
+ message PriceUpsertResult {
937
+ string guid = 1;
938
+ string status = 2;
939
+ optional string reason = 3;
940
+ }
941
+
942
+ message UpsertPricesResponse {
943
+ repeated PriceUpsertResult results = 1;
944
+ }
945
+
946
+
947
+ message CharacteristicPropertyLink {
948
+ string property_guid = 1;
949
+ string value_guid = 2;
950
+ }
951
+
952
+ message CharacteristicSyncItem {
953
+ string characteristic_guid = 1;
954
+ map<string, string> name = 2;
955
+ repeated CharacteristicPropertyLink properties = 3;
956
+ }
957
+
958
+ message UpsertCharacteristicsRequest {
959
+ repeated CharacteristicSyncItem items = 1;
960
+ string sync_id = 2;
961
+ }
962
+
963
+ message CharacteristicUpsertResult {
964
+ string guid = 1;
965
+ string status = 2;
966
+ optional string reason = 3;
967
+ optional string id = 4;
968
+ }
969
+
970
+ message UpsertCharacteristicsResponse {
971
+ repeated CharacteristicUpsertResult results = 1;
972
+ }
973
+
974
+
975
+ message StockSyncItem {
976
+ string product_guid = 1;
977
+ optional string characteristic_guid = 2;
978
+ string warehouse_guid = 3;
979
+ int32 quantity = 4;
980
+ }
981
+
982
+ message UpsertStocksRequest {
983
+ repeated StockSyncItem items = 1;
984
+ string sync_id = 2;
985
+ }
986
+
987
+ message StockUpsertResult {
988
+ string guid = 1;
989
+ string status = 2;
990
+ optional string reason = 3;
991
+ }
992
+
993
+ message UpsertStocksResponse {
994
+ repeated StockUpsertResult results = 1;
884
995
  }
@@ -19,28 +19,27 @@ service PromotionService {
19
19
  rpc GetActivePromotions (GetActivePromotionsRequest) returns (GetActivePromotionsResponse);
20
20
  rpc GetActivePromotionsSnapshot (GetActivePromotionsSnapshotRequest) returns (GetActivePromotionsSnapshotResponse);
21
21
 
22
- // Products
22
+
23
23
  rpc GetPromotionProducts (GetPromotionProductsRequest) returns (GetPromotionProductsResponse);
24
24
  rpc GetPromotionEligibleProductIds (GetPromotionEligibleProductIdsRequest) returns (GetPromotionEligibleProductIdsResponse);
25
25
  rpc AddPromotionProducts (AddPromotionProductsRequest) returns (SuccessResponse);
26
26
  rpc RemovePromotionProducts (RemovePromotionProductsRequest) returns (SuccessResponse);
27
27
 
28
- // Categories
28
+
29
29
  rpc GetPromotionCategories (GetPromotionCategoriesRequest) returns (GetPromotionCategoriesResponse);
30
30
  rpc SetPromotionCategories (SetPromotionCategoriesRequest) returns (SuccessResponse);
31
31
 
32
- // Brands
32
+
33
33
  rpc GetPromotionBrands (GetPromotionBrandsRequest) returns (GetPromotionBrandsResponse);
34
34
  rpc SetPromotionBrands (SetPromotionBrandsRequest) returns (SuccessResponse);
35
35
 
36
- // Bundles
36
+
37
37
  rpc GetPromotionBundles (GetPromotionBundlesRequest) returns (GetPromotionBundlesResponse);
38
38
  rpc AddPromotionBundles (AddPromotionBundlesRequest) returns (SuccessResponse);
39
39
  rpc RemovePromotionBundles (RemovePromotionBundlesRequest) returns (SuccessResponse);
40
40
  }
41
41
 
42
42
 
43
- // ─── Enums ────────────────────────────────────────────────────────────────────
44
43
 
45
44
  enum PromotionType {
46
45
  PROMOTION_TYPE_UNSPECIFIED = 0;
@@ -99,7 +98,6 @@ enum ExclusionEntityType {
99
98
  }
100
99
 
101
100
 
102
- // ─── Condition / Exclusion payloads ───────────────────────────────────────────
103
101
 
104
102
  message PromotionConditionPayload {
105
103
  ConditionLogic logic_type = 1;
@@ -126,7 +124,6 @@ message PromotionExclusionResponse {
126
124
  }
127
125
 
128
126
 
129
- // ─── Main response ────────────────────────────────────────────────────────────
130
127
 
131
128
  message PromotionResponse {
132
129
  string id = 1;
@@ -178,7 +175,6 @@ message PromotionResponse {
178
175
  }
179
176
 
180
177
 
181
- // ─── List ─────────────────────────────────────────────────────────────────────
182
178
 
183
179
  message GetPromotionsRequest {
184
180
  PaginationRequest pagination = 1;
@@ -188,8 +184,8 @@ message GetPromotionsRequest {
188
184
  optional string category_id = 5;
189
185
  optional string date_from = 6;
190
186
  optional string date_to = 7;
191
- optional string sort_by = 8; // startDate | endDate | priority | discountValue
192
- optional string sort_dir = 9; // asc | desc
187
+ optional string sort_by = 8;
188
+ optional string sort_dir = 9;
193
189
  }
194
190
 
195
191
  message GetPromotionsResponse {
@@ -216,7 +212,6 @@ message PromotionListItem {
216
212
  }
217
213
 
218
214
 
219
- // ─── CRUD requests ───────────────────────────────────────────────────────────
220
215
 
221
216
  message GetPromotionRequest {
222
217
  string id = 1;
@@ -314,7 +309,6 @@ message UpdatePromotionStatusRequest {
314
309
  }
315
310
 
316
311
 
317
- // ─── Bulk apply ───────────────────────────────────────────────────────────────
318
312
 
319
313
  message BulkApplyToCategoriesRequest {
320
314
  string promotion_id = 1;
@@ -322,7 +316,6 @@ message BulkApplyToCategoriesRequest {
322
316
  }
323
317
 
324
318
 
325
- // ─── Active promotions ────────────────────────────────────────────────────────
326
319
 
327
320
  message GetActivePromotionsRequest {
328
321
  PaginationRequest pagination = 1;
@@ -335,7 +328,6 @@ message GetActivePromotionsResponse {
335
328
  }
336
329
 
337
330
 
338
- // ─── Products ─────────────────────────────────────────────────────────────────
339
331
 
340
332
  message PromotionProductItem {
341
333
  string id = 1;
@@ -376,8 +368,7 @@ message GetPromotionEligibleProductIdsRequest {
376
368
  string promotion_id = 1;
377
369
  }
378
370
 
379
- // Returns the full membership of the promotion (NOT resolved to a flat list).
380
- // Catalog-service joins these (UNION include − exclude) using its own data.
371
+
381
372
  message GetPromotionEligibleProductIdsResponse {
382
373
  repeated string include_product_ids = 1;
383
374
  repeated string include_category_ids = 2;
@@ -388,7 +379,6 @@ message GetPromotionEligibleProductIdsResponse {
388
379
  optional bool exists = 7;
389
380
  }
390
381
 
391
- // ─── Active promotions snapshot (for cross-service enrichment) ───────────────
392
382
 
393
383
  message GetActivePromotionsSnapshotRequest {}
394
384
 
@@ -402,14 +392,14 @@ message ActivePromotionSnapshotItem {
402
392
  optional string seo_slug = 7;
403
393
  optional string starts_at = 8;
404
394
  optional string ends_at = 9;
405
- // Resolved eligible product IDs (already deduped, exclusions applied).
395
+
406
396
  repeated string product_ids = 10;
407
397
  repeated string category_ids = 11;
408
398
  repeated string brand_ids = 12;
409
399
  repeated string excluded_product_ids = 13;
410
400
  repeated string excluded_category_ids = 14;
411
401
  repeated string excluded_brand_ids = 15;
412
- // Per-product label/color override (key = productId).
402
+
413
403
  map<string, string> product_labels = 16;
414
404
  map<string, string> product_label_colors = 17;
415
405
  }
@@ -420,7 +410,6 @@ message GetActivePromotionsSnapshotResponse {
420
410
  }
421
411
 
422
412
 
423
- // ─── Categories ───────────────────────────────────────────────────────────────
424
413
 
425
414
  message GetPromotionCategoriesRequest {
426
415
  string promotion_id = 1;
@@ -436,7 +425,6 @@ message SetPromotionCategoriesRequest {
436
425
  }
437
426
 
438
427
 
439
- // ─── Brands ───────────────────────────────────────────────────────────────────
440
428
 
441
429
  message GetPromotionBrandsRequest {
442
430
  string promotion_id = 1;
@@ -452,7 +440,6 @@ message SetPromotionBrandsRequest {
452
440
  }
453
441
 
454
442
 
455
- // ─── Bundles ──────────────────────────────────────────────────────────────────
456
443
 
457
444
  message GetPromotionBundlesRequest {
458
445
  string promotion_id = 1;
package/proto/rbac.proto CHANGED
@@ -3,17 +3,17 @@ syntax = "proto3";
3
3
  package rbac.v1;
4
4
 
5
5
  service RbacService {
6
- // Permissions catalog (read-only, seeded).
6
+
7
7
  rpc ListPermissions(ListPermissionsRequest) returns (ListPermissionsResponse);
8
8
 
9
- // Roles CRUD.
9
+
10
10
  rpc ListRoles(ListRolesRequest) returns (ListRolesResponse);
11
11
  rpc GetRole(GetRoleRequest) returns (RbacRole);
12
12
  rpc CreateRole(CreateRoleRequest) returns (RbacRole);
13
13
  rpc UpdateRole(UpdateRoleRequest) returns (RbacRole);
14
14
  rpc DeleteRole(DeleteRoleRequest) returns (DeleteRoleResponse);
15
15
 
16
- // Account ↔ role bindings.
16
+
17
17
  rpc AssignAccountRole(AssignAccountRoleRequest) returns (AssignAccountRoleResponse);
18
18
  rpc GetAccountPermissions(GetAccountPermissionsRequest) returns (GetAccountPermissionsResponse);
19
19
  }
@@ -71,7 +71,7 @@ message UpdateRoleRequest {
71
71
  optional string name = 2;
72
72
  optional string description = 3;
73
73
  optional string color = 4;
74
- // Якщо передано — повна заміна; якщо не передано — без змін.
74
+
75
75
  repeated string permission_keys = 5;
76
76
  bool replace_permissions = 6;
77
77
  }
@@ -86,8 +86,7 @@ message DeleteRoleResponse {
86
86
 
87
87
  message AssignAccountRoleRequest {
88
88
  string account_id = 1;
89
- // Якщо custom_role_id порожній — користувач відвʼязується від кастомної ролі,
90
- // і дозволи беруться з системної.
89
+
91
90
  optional string custom_role_id = 2;
92
91
  }
93
92
 
@@ -100,10 +99,9 @@ message GetAccountPermissionsRequest {
100
99
  }
101
100
 
102
101
  message GetAccountPermissionsResponse {
103
- // Effective permissions з урахуванням system role + custom role override.
104
- // Може містити "*" — повний доступ (ADMIN).
102
+
105
103
  repeated string permission_keys = 1;
106
- // Слаг ефективної ролі (для UI/labels).
104
+
107
105
  string role_slug = 2;
108
106
  string role_name = 3;
109
107
  }
@@ -6,42 +6,41 @@ import "common.proto";
6
6
 
7
7
 
8
8
  service SearchService {
9
- // ─── Public (autocomplete) ───────────────────────────────────────────────
9
+
10
10
  rpc Suggest (SuggestRequest) returns (SuggestResponse);
11
11
 
12
- // ─── Admin: synonyms ─────────────────────────────────────────────────────
12
+
13
13
  rpc ListSynonyms (ListSynonymsRequest) returns (ListSynonymsResponse);
14
14
  rpc CreateSynonym (CreateSynonymRequest) returns (SynonymResponse);
15
15
  rpc UpdateSynonym (UpdateSynonymRequest) returns (SynonymResponse);
16
16
  rpc DeleteSynonym (DeleteSynonymRequest) returns (DeleteResponse);
17
17
  rpc SyncSynonymsToTypesense (SyncSynonymsRequest) returns (SuccessResponse);
18
18
 
19
- // ─── Admin: popular queries ──────────────────────────────────────────────
19
+
20
20
  rpc ListPopularQueries (ListPopularQueriesRequest) returns (ListPopularQueriesResponse);
21
21
  rpc CreatePopularQuery (CreatePopularQueryRequest) returns (PopularQueryResponse);
22
22
  rpc UpdatePopularQuery (UpdatePopularQueryRequest) returns (PopularQueryResponse);
23
23
  rpc DeletePopularQuery (DeletePopularQueryRequest) returns (DeleteResponse);
24
24
  rpc ReorderPopularQueries (ReorderPopularQueriesRequest) returns (SuccessResponse);
25
25
 
26
- // ─── Admin: zero-result analytics ────────────────────────────────────────
26
+
27
27
  rpc ListZeroResults (ListZeroResultsRequest) returns (ListZeroResultsResponse);
28
28
  rpc ClearZeroResults (ClearZeroResultsRequest) returns (SuccessResponse);
29
29
  }
30
30
 
31
- // ─────────────────────────── Suggest (public) ─────────────────────────────
32
31
 
33
32
  message SuggestRequest {
34
33
  string q = 1;
35
- int32 limit = 2; // 1..20, default 8
36
- bool only_in_stock = 3; // default true
37
- string locale = 4; // 'uk' | 'ru', default 'uk'
34
+ int32 limit = 2;
35
+ bool only_in_stock = 3;
36
+ string locale = 4;
38
37
  }
39
38
 
40
39
  message SuggestProduct {
41
40
  string id = 1;
42
41
  string sku = 2;
43
42
  string slug = 3;
44
- string name = 4; // already локалізована (uk/ru)
43
+ string name = 4;
45
44
  string main_image = 5;
46
45
  double price = 6;
47
46
  optional double old_price = 7;
@@ -62,10 +61,9 @@ message SuggestResponse {
62
61
  repeated SuggestProduct products = 2;
63
62
  repeated SuggestCategory categories = 3;
64
63
  repeated string popular_queries = 4;
65
- int32 total = 5; // загальна кількість збігів у продуктах
64
+ int32 total = 5;
66
65
  }
67
66
 
68
- // ─────────────────────────── Synonyms (admin) ─────────────────────────────
69
67
 
70
68
  enum SynonymType {
71
69
  SYNONYM_MULTI_WAY = 0;
@@ -118,7 +116,6 @@ message DeleteSynonymRequest {
118
116
  message SyncSynonymsRequest {
119
117
  }
120
118
 
121
- // ───────────────────────── Popular queries (admin) ────────────────────────
122
119
 
123
120
  message PopularQueryResponse {
124
121
  string id = 1;
@@ -163,10 +160,9 @@ message ReorderPopularQueryItem {
163
160
  int32 sort_order = 2;
164
161
  }
165
162
 
166
- // ─────────────────────── Zero-result analytics (admin) ─────────────────────
167
163
 
168
164
  message ListZeroResultsRequest {
169
- optional int32 limit = 1; // default 100, max 500
165
+ optional int32 limit = 1;
170
166
  }
171
167
 
172
168
  message ZeroResultItem {
@@ -6,14 +6,9 @@ import "common.proto";
6
6
 
7
7
 
8
8
  service SeoFilterService {
9
- // ─── Public ──────────────────────────────────────────────────────────────
10
9
 
11
- // Резолв ЧПУ-URL → metadata + canonical. Викликається SSR Next.js для
12
- // кожного category/[[...filters]] запиту. Якщо combo не знайдено —
13
- // повертає isIndexed=false і автогенерований fallback metadata.
14
10
  rpc ResolveSeoFilter (ResolveSeoFilterRequest) returns (ResolveSeoFilterResponse);
15
11
 
16
- // ─── Admin ───────────────────────────────────────────────────────────────
17
12
 
18
13
  rpc ListSeoFilters (ListSeoFiltersRequest) returns (ListSeoFiltersResponse);
19
14
  rpc GetSeoFilter (GetSeoFilterRequest) returns (SeoFilterResponse);
@@ -21,26 +16,24 @@ service SeoFilterService {
21
16
  rpc UpdateSeoFilter (UpdateSeoFilterRequest) returns (SeoFilterResponse);
22
17
  rpc DeleteSeoFilter (DeleteSeoFilterRequest) returns (DeleteResponse);
23
18
 
24
- // Топ-N непокритих combinations (за impressions/popularity) — для
25
- // швидкого створення SeoFilter з адмін-форми "Автопідказки".
19
+
26
20
  rpc SuggestSeoFilters (SuggestSeoFiltersRequest) returns (SuggestSeoFiltersResponse);
21
+
22
+ rpc ListIndexedForSitemap (ListIndexedForSitemapRequest) returns (ListIndexedForSitemapResponse);
27
23
  }
28
24
 
29
- // ─────────────────────────── Domain types ────────────────────────────────
30
25
 
31
- // Частина combo. Однаковий формат і у DB (combo_parts JSON), і у gRPC.
32
- // type: 'brand'|'price'|'color'|'size'
33
26
  message FilterPart {
34
27
  string type = 1;
35
- // Для brand/color/size:
28
+
36
29
  optional string value_id = 2;
37
30
  optional string value_slug = 3;
38
- // Для price:
31
+
39
32
  optional int32 price_min = 4;
40
33
  optional int32 price_max = 5;
41
34
  }
42
35
 
43
- // Локалізовані поля (uk/ru) у форматі { uk: "...", ru: "..." }.
36
+
44
37
  message LocaleStrings {
45
38
  string uk = 1;
46
39
  string ru = 2;
@@ -62,40 +55,35 @@ message SeoFilterResponse {
62
55
  int64 updated_at = 13;
63
56
  }
64
57
 
65
- // ─────────────────────────── Resolve (public) ────────────────────────────
66
58
 
67
59
  message ResolveSeoFilterRequest {
68
60
  string category_id = 1;
69
- // Канонічно відсортовані URL segments як приходять з Next.js, напр.
70
- // ["brend-cybex", "cina-1000-5000"]. Caller гарантує що порядок canonical.
61
+
71
62
  repeated string url_segments = 2;
72
- string locale = 3; // 'uk' | 'ru'
63
+ string locale = 3;
73
64
  }
74
65
 
75
66
  message ResolveSeoFilterResponse {
76
- // Якщо false → caller рендерить категорію з noindex,follow.
67
+
77
68
  bool found = 1;
78
- // Якщо false → caller додає <meta robots="noindex,follow"> навіть якщо
79
- // запис знайдено (наприклад, isIndexed=false manual override).
69
+
80
70
  bool is_indexed = 2;
81
71
  LocaleStrings title = 3;
82
72
  LocaleStrings description = 4;
83
73
  LocaleStrings h1 = 5;
84
- // Canonical-URL-path без host: "/uk/c/koliaski/brend-cybex"
74
+
85
75
  string canonical_path = 6;
86
- // Денормалізовані combo_parts з resolved valueId — для побудови
87
- // запиту до products (categoryId + filter ids).
76
+
88
77
  repeated FilterPart resolved_parts = 7;
89
78
  }
90
79
 
91
- // ─────────────────────────── List (admin) ────────────────────────────────
92
80
 
93
81
  message ListSeoFiltersRequest {
94
82
  PaginationRequest pagination = 1;
95
83
  optional string category_id = 2;
96
84
  optional bool is_indexed = 3;
97
85
  optional bool is_auto = 4;
98
- // Пошук за uk/ru title (для адмін-фільтра).
86
+
99
87
  optional string search = 5;
100
88
  }
101
89
 
@@ -108,7 +96,6 @@ message GetSeoFilterRequest {
108
96
  string id = 1;
109
97
  }
110
98
 
111
- // ─────────────────────────── Create / Update ─────────────────────────────
112
99
 
113
100
  message CreateSeoFilterRequest {
114
101
  string category_id = 1;
@@ -131,24 +118,42 @@ message DeleteSeoFilterRequest {
131
118
  string id = 1;
132
119
  }
133
120
 
134
- // ─────────────────────────── Suggestions (admin) ─────────────────────────
135
121
 
136
122
  message SuggestSeoFiltersRequest {
137
123
  string category_id = 1;
138
- int32 limit = 2; // default 20
124
+ int32 limit = 2;
139
125
  }
140
126
 
141
127
  message SuggestSeoFilterCandidate {
142
- // Запропоновані combo_parts (валідні, з resolved slug).
128
+
143
129
  repeated FilterPart combo_parts = 1;
144
- // Оцінка популярності: clicks / impressions / товарообіг (single число).
130
+
145
131
  int32 score = 2;
146
- // Чи існує вже SeoFilter з таким комбо (тоді UI ховає кнопку Create).
132
+
147
133
  bool already_exists = 3;
148
- // Pre-built canonical URL path для preview.
134
+
149
135
  LocaleStrings preview_segments = 4;
150
136
  }
151
137
 
152
138
  message SuggestSeoFiltersResponse {
153
139
  repeated SuggestSeoFilterCandidate items = 1;
154
140
  }
141
+
142
+
143
+ message ListIndexedForSitemapRequest {
144
+
145
+ optional int32 limit = 1;
146
+ optional string after_id = 2;
147
+ }
148
+
149
+ message SitemapEntry {
150
+ string id = 1;
151
+ string category_slug = 2;
152
+ LocaleStrings url_segments = 3;
153
+ int64 updated_at = 4;
154
+ }
155
+
156
+ message ListIndexedForSitemapResponse {
157
+ repeated SitemapEntry items = 1;
158
+ optional string next_after_id = 2;
159
+ }
@@ -60,9 +60,7 @@ message ShopFilterOption {
60
60
  string value = 1;
61
61
  string label = 2;
62
62
  int32 count = 3;
63
- // slug ОПЦІЙНИЙ — потрібен для побудови ЧПУ-URL фільтрами
64
- // (brend-<slug>, kolir-<slug>, rozmir-<slug>). Якщо slug ще не
65
- // згенеровано через backfill — пусто, frontend fallback на id.
63
+
66
64
  optional string slug = 4;
67
65
  }
68
66