@infrab4a/connect-angular 5.0.0-beta.97 → 5.0.0

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 (211) hide show
  1. package/CHANGELOG.md +13 -0
  2. package/eslint.config.js +18 -0
  3. package/index.ts +1 -0
  4. package/karma.conf.js +32 -0
  5. package/ng-package.json +8 -0
  6. package/package.json +10 -22
  7. package/project.json +37 -0
  8. package/src/angular-connect.module.ts +256 -0
  9. package/src/angular-elastic-search.module.ts +23 -0
  10. package/src/angular-firebase-auth.module.ts +101 -0
  11. package/src/angular-firestore.module.ts +371 -0
  12. package/src/angular-hasura-graphql.module.ts +219 -0
  13. package/src/angular-vertex-search.module.ts +23 -0
  14. package/src/consts/backend-url.const.ts +1 -0
  15. package/src/consts/category-structure.ts +1 -0
  16. package/src/consts/default-shop.const.ts +1 -0
  17. package/src/consts/es-config.const.ts +1 -0
  18. package/src/consts/firebase-const.ts +5 -0
  19. package/src/consts/hasura-options.const.ts +1 -0
  20. package/src/consts/index.ts +8 -0
  21. package/src/consts/persistence.const.ts +1 -0
  22. package/src/consts/storage-base-url.const.ts +1 -0
  23. package/src/consts/vertex-config.const.ts +1 -0
  24. package/src/helpers/index.ts +1 -0
  25. package/src/helpers/mobile-operation-system-checker.helper.ts +10 -0
  26. package/src/index.ts +6 -0
  27. package/src/interfaces/catalog-strategies.interface.ts +36 -0
  28. package/src/interfaces/category-facades.interface.ts +7 -0
  29. package/src/interfaces/index.ts +2 -0
  30. package/src/persistence/cookie-data-persistence.ts +21 -0
  31. package/src/persistence/data-persistence.ts +7 -0
  32. package/src/persistence/index.ts +2 -0
  33. package/src/services/auth.service.ts +39 -0
  34. package/src/services/cart/cart-services.facade.ts +14 -0
  35. package/src/services/cart/index.ts +1 -0
  36. package/src/services/cart.service.ts +124 -0
  37. package/src/services/catalog/adapters/category-structure.adapter.ts +5 -0
  38. package/src/services/catalog/adapters/index.ts +3 -0
  39. package/src/services/catalog/adapters/new-category-structure.adapter.ts +42 -0
  40. package/src/services/catalog/adapters/old-category-structure.adapter.ts +17 -0
  41. package/src/services/catalog/catalog.service.ts +153 -0
  42. package/src/services/catalog/category.service.ts +52 -0
  43. package/src/services/catalog/context/catalog-search.context.ts +61 -0
  44. package/src/services/catalog/enums/index.ts +1 -0
  45. package/src/services/catalog/enums/product-sorts.enum.ts +9 -0
  46. package/src/services/catalog/facades/catalog-service.facade.ts +32 -0
  47. package/src/services/catalog/facades/catalog-strategies.facade.ts +12 -0
  48. package/src/services/catalog/facades/category-repository.facade.ts +10 -0
  49. package/src/services/catalog/facades/category-service.facade.ts +25 -0
  50. package/src/services/catalog/facades/index.ts +5 -0
  51. package/src/services/catalog/facades/product-catalog.facade.ts +13 -0
  52. package/src/services/catalog/helpers/brand-manager.helper.ts +63 -0
  53. package/src/services/catalog/helpers/catalog-filter.helper.ts +50 -0
  54. package/src/services/catalog/helpers/catalog-sort.helper.ts +54 -0
  55. package/src/services/catalog/helpers/index.ts +4 -0
  56. package/src/services/catalog/helpers/product-fields.helper.ts +35 -0
  57. package/src/services/catalog/index.ts +7 -0
  58. package/src/services/catalog/models/category-with-tree.model.ts +7 -0
  59. package/src/services/catalog/models/index.ts +1 -0
  60. package/src/services/catalog/services/catalog-helpers.service.ts +35 -0
  61. package/src/services/catalog/services/catalog-operations.facade.ts +24 -0
  62. package/src/services/catalog/services/catalog-repository.service.ts +20 -0
  63. package/src/services/catalog/services/index.ts +4 -0
  64. package/src/services/catalog/services/product-management.facade.ts +20 -0
  65. package/src/services/catalog/strategies/category-search.strategy.ts +172 -0
  66. package/src/services/catalog/strategies/index.ts +3 -0
  67. package/src/services/catalog/strategies/profile-search.strategy.ts +51 -0
  68. package/src/services/catalog/strategies/term-search.strategy.ts +178 -0
  69. package/src/services/catalog/strategies/types/strategy-params.type.ts +58 -0
  70. package/src/services/catalog/types/fetch-products-options.type.ts +10 -0
  71. package/src/services/catalog/types/fetch-products-params.type.ts +27 -0
  72. package/src/services/catalog/types/fetch-products-response.type.ts +11 -0
  73. package/src/services/catalog/types/index.ts +5 -0
  74. package/src/services/catalog/types/method-params.type.ts +21 -0
  75. package/src/services/catalog/types/product-sort.type.ts +3 -0
  76. package/src/services/catalog/wishlist.service.ts +368 -0
  77. package/src/services/checkout/checkout-dependencies.facade.ts +13 -0
  78. package/src/services/checkout/checkout-repositories.facade.ts +10 -0
  79. package/src/services/checkout/index.ts +2 -0
  80. package/src/services/checkout-subscription.service.ts +76 -0
  81. package/src/services/checkout.service.ts +196 -0
  82. package/src/services/coupon/coupon-repositories.facade.ts +11 -0
  83. package/src/services/coupon/index.ts +1 -0
  84. package/src/services/coupon/types/coupon-params.type.ts +15 -0
  85. package/src/services/coupon.service.ts +347 -0
  86. package/src/services/errors/group-invalid-coupon.error.ts +9 -0
  87. package/src/services/errors/index.ts +2 -0
  88. package/src/services/errors/invalid-coupon.error.ts +7 -0
  89. package/src/services/helpers/index.ts +1 -0
  90. package/src/services/helpers/util.helper.ts +17 -0
  91. package/src/services/home-shop/home-shop-repositories.facade.ts +11 -0
  92. package/src/services/home-shop/index.ts +1 -0
  93. package/src/services/home-shop.service.ts +196 -0
  94. package/src/services/index.ts +9 -0
  95. package/src/services/order.service.ts +23 -0
  96. package/src/services/shared/configuration.facade.ts +21 -0
  97. package/src/services/shared/index.ts +1 -0
  98. package/src/services/types/index.ts +2 -0
  99. package/src/services/types/required-checkout-data.type.ts +3 -0
  100. package/src/services/types/required-checkout-subscription-data.type.ts +3 -0
  101. package/src/types/firebase-app-config.type.ts +1 -0
  102. package/src/types/index.ts +1 -0
  103. package/tsconfig.json +17 -0
  104. package/tsconfig.lib.json +13 -0
  105. package/tsconfig.lib.prod.json +13 -0
  106. package/tsconfig.spec.json +17 -0
  107. package/angular-connect.module.d.ts +0 -32
  108. package/angular-elastic-search.module.d.ts +0 -9
  109. package/angular-firebase-auth.module.d.ts +0 -11
  110. package/angular-firestore.module.d.ts +0 -17
  111. package/angular-hasura-graphql.module.d.ts +0 -14
  112. package/angular-vertex-search.module.d.ts +0 -9
  113. package/consts/backend-url.const.d.ts +0 -1
  114. package/consts/category-structure.d.ts +0 -1
  115. package/consts/default-shop.const.d.ts +0 -1
  116. package/consts/es-config.const.d.ts +0 -1
  117. package/consts/firebase-const.d.ts +0 -4
  118. package/consts/hasura-options.const.d.ts +0 -1
  119. package/consts/index.d.ts +0 -8
  120. package/consts/persistence.const.d.ts +0 -1
  121. package/consts/storage-base-url.const.d.ts +0 -1
  122. package/consts/vertex-config.const.d.ts +0 -1
  123. package/esm2022/angular-connect.module.mjs +0 -187
  124. package/esm2022/angular-elastic-search.module.mjs +0 -34
  125. package/esm2022/angular-firebase-auth.module.mjs +0 -141
  126. package/esm2022/angular-firestore.module.mjs +0 -541
  127. package/esm2022/angular-hasura-graphql.module.mjs +0 -333
  128. package/esm2022/angular-vertex-search.module.mjs +0 -34
  129. package/esm2022/consts/backend-url.const.mjs +0 -2
  130. package/esm2022/consts/category-structure.mjs +0 -2
  131. package/esm2022/consts/default-shop.const.mjs +0 -2
  132. package/esm2022/consts/es-config.const.mjs +0 -2
  133. package/esm2022/consts/firebase-const.mjs +0 -5
  134. package/esm2022/consts/hasura-options.const.mjs +0 -2
  135. package/esm2022/consts/index.mjs +0 -9
  136. package/esm2022/consts/persistence.const.mjs +0 -2
  137. package/esm2022/consts/storage-base-url.const.mjs +0 -2
  138. package/esm2022/consts/vertex-config.const.mjs +0 -2
  139. package/esm2022/helpers/index.mjs +0 -2
  140. package/esm2022/helpers/mobile-operation-system-checker.helper.mjs +0 -7
  141. package/esm2022/index.mjs +0 -7
  142. package/esm2022/infrab4a-connect-angular.mjs +0 -5
  143. package/esm2022/persistence/cookie-data-persistence.mjs +0 -22
  144. package/esm2022/persistence/data-persistence.mjs +0 -2
  145. package/esm2022/persistence/index.mjs +0 -3
  146. package/esm2022/services/auth.service.mjs +0 -37
  147. package/esm2022/services/cart.service.mjs +0 -86
  148. package/esm2022/services/catalog/adapters/category-structure.adapter.mjs +0 -2
  149. package/esm2022/services/catalog/adapters/index.mjs +0 -4
  150. package/esm2022/services/catalog/adapters/new-category-structure.adapter.mjs +0 -43
  151. package/esm2022/services/catalog/adapters/old-category-structure.adapter.mjs +0 -23
  152. package/esm2022/services/catalog/catalog.service.mjs +0 -325
  153. package/esm2022/services/catalog/category.service.mjs +0 -51
  154. package/esm2022/services/catalog/enums/index.mjs +0 -2
  155. package/esm2022/services/catalog/enums/product-sorts.enum.mjs +0 -11
  156. package/esm2022/services/catalog/index.mjs +0 -8
  157. package/esm2022/services/catalog/models/category-with-tree.model.mjs +0 -10
  158. package/esm2022/services/catalog/models/index.mjs +0 -2
  159. package/esm2022/services/catalog/types/index.mjs +0 -2
  160. package/esm2022/services/catalog/types/product-sort.type.mjs +0 -2
  161. package/esm2022/services/catalog/wishlist.service.mjs +0 -235
  162. package/esm2022/services/checkout-subscription.service.mjs +0 -50
  163. package/esm2022/services/checkout.service.mjs +0 -122
  164. package/esm2022/services/coupon.service.mjs +0 -228
  165. package/esm2022/services/helpers/index.mjs +0 -2
  166. package/esm2022/services/helpers/util.helper.mjs +0 -18
  167. package/esm2022/services/home-shop.service.mjs +0 -125
  168. package/esm2022/services/index.mjs +0 -10
  169. package/esm2022/services/order.service.mjs +0 -30
  170. package/esm2022/services/types/index.mjs +0 -3
  171. package/esm2022/services/types/required-checkout-data.type.mjs +0 -2
  172. package/esm2022/services/types/required-checkout-subscription-data.type.mjs +0 -2
  173. package/esm2022/types/firebase-app-config.type.mjs +0 -2
  174. package/esm2022/types/index.mjs +0 -2
  175. package/fesm2022/infrab4a-connect-angular.mjs +0 -2603
  176. package/fesm2022/infrab4a-connect-angular.mjs.map +0 -1
  177. package/helpers/index.d.ts +0 -1
  178. package/helpers/mobile-operation-system-checker.helper.d.ts +0 -3
  179. package/index.d.ts +0 -6
  180. package/persistence/cookie-data-persistence.d.ts +0 -10
  181. package/persistence/data-persistence.d.ts +0 -6
  182. package/persistence/index.d.ts +0 -2
  183. package/services/auth.service.d.ts +0 -18
  184. package/services/cart.service.d.ts +0 -31
  185. package/services/catalog/adapters/category-structure.adapter.d.ts +0 -4
  186. package/services/catalog/adapters/index.d.ts +0 -3
  187. package/services/catalog/adapters/new-category-structure.adapter.d.ts +0 -12
  188. package/services/catalog/adapters/old-category-structure.adapter.d.ts +0 -10
  189. package/services/catalog/catalog.service.d.ts +0 -96
  190. package/services/catalog/category.service.d.ts +0 -24
  191. package/services/catalog/enums/index.d.ts +0 -1
  192. package/services/catalog/enums/product-sorts.enum.d.ts +0 -9
  193. package/services/catalog/index.d.ts +0 -7
  194. package/services/catalog/models/category-with-tree.model.d.ts +0 -4
  195. package/services/catalog/models/index.d.ts +0 -1
  196. package/services/catalog/types/index.d.ts +0 -1
  197. package/services/catalog/types/product-sort.type.d.ts +0 -2
  198. package/services/catalog/wishlist.service.d.ts +0 -50
  199. package/services/checkout-subscription.service.d.ts +0 -19
  200. package/services/checkout.service.d.ts +0 -34
  201. package/services/coupon.service.d.ts +0 -27
  202. package/services/helpers/index.d.ts +0 -1
  203. package/services/helpers/util.helper.d.ts +0 -3
  204. package/services/home-shop.service.d.ts +0 -26
  205. package/services/index.d.ts +0 -9
  206. package/services/order.service.d.ts +0 -13
  207. package/services/types/index.d.ts +0 -2
  208. package/services/types/required-checkout-data.type.d.ts +0 -2
  209. package/services/types/required-checkout-subscription-data.type.d.ts +0 -2
  210. package/types/firebase-app-config.type.d.ts +0 -1
  211. package/types/index.d.ts +0 -1
@@ -0,0 +1,25 @@
1
+ import { Inject, Injectable } from '@angular/core'
2
+ import { Shops } from '@infrab4a/connect'
3
+
4
+ import { DEFAULT_SHOP } from '../../../consts'
5
+ import { CategoryService } from '../category.service'
6
+
7
+ import { CategoryRepositoryFacade } from './category-repository.facade'
8
+ import { ProductCatalogFacade } from './product-catalog.facade'
9
+
10
+ @Injectable()
11
+ export class CategoryServiceFacade {
12
+ private categoryService: CategoryService
13
+
14
+ constructor(
15
+ private readonly categoryRepositoryFacade: CategoryRepositoryFacade,
16
+ private readonly productCatalogFacade: ProductCatalogFacade,
17
+ @Inject(DEFAULT_SHOP) private readonly shop: Shops,
18
+ ) {
19
+ this.categoryService = new CategoryService(this.categoryRepositoryFacade, this.productCatalogFacade, this.shop)
20
+ }
21
+
22
+ getCategoryService(): CategoryService {
23
+ return this.categoryService
24
+ }
25
+ }
@@ -0,0 +1,5 @@
1
+ export { CatalogServiceFacade } from './catalog-service.facade'
2
+ export { CatalogStrategiesFacade } from './catalog-strategies.facade'
3
+ export { CategoryRepositoryFacade } from './category-repository.facade'
4
+ export { CategoryServiceFacade } from './category-service.facade'
5
+ export { ProductCatalogFacade } from './product-catalog.facade'
@@ -0,0 +1,13 @@
1
+ import { Inject, Injectable } from '@angular/core'
2
+ import { ProductRepository } from '@infrab4a/connect'
3
+
4
+ import { CATEGORY_STRUCTURE } from '../../../consts'
5
+ import { CategoryStructureAdapter } from '../adapters'
6
+
7
+ @Injectable()
8
+ export class ProductCatalogFacade {
9
+ constructor(
10
+ @Inject('ProductRepository') public readonly productRepository: ProductRepository,
11
+ @Inject(CATEGORY_STRUCTURE) public readonly categoryStructureAdapter: CategoryStructureAdapter,
12
+ ) {}
13
+ }
@@ -0,0 +1,63 @@
1
+ import { Injectable } from '@angular/core'
2
+ import { Where, isEmpty } from '@infrab4a/connect'
3
+
4
+ import { CatalogSearchParams } from '../../../interfaces'
5
+ import { ProductCatalogFacade } from '../facades'
6
+
7
+ @Injectable()
8
+ export class BrandManagerHelper {
9
+ private brandsList: Record<string, string[]> = {}
10
+
11
+ constructor(private readonly productCatalog: ProductCatalogFacade) {}
12
+
13
+ async setBrandsList(options: CatalogSearchParams, brands: string[]): Promise<void> {
14
+ const filterBrands = options.filters?.brands
15
+ const indexKey = this.buildIndexBrands(options)
16
+
17
+ if (isEmpty(brands) && options.filters) {
18
+ delete options.filters.brands
19
+ }
20
+
21
+ this.brandsList[indexKey] = this.brandsList[indexKey] || brands || (await this.fetchBrandsOnly(options))
22
+
23
+ this.brandsList[indexKey] = this.brandsList[indexKey].filter(Boolean)
24
+
25
+ if (options.filters) {
26
+ options.filters = {
27
+ ...options.filters,
28
+ brands: filterBrands,
29
+ }
30
+ }
31
+ }
32
+
33
+ getBrandsList(indexKey: string): string[] {
34
+ return this.brandsList[indexKey]
35
+ }
36
+
37
+ buildIndexBrands(options: CatalogSearchParams): string {
38
+ if (options.category) return `category-${options.category.id}`
39
+
40
+ if (options.term) return `term-${options.term}`
41
+
42
+ if (options.profile) return `profile-${options.profile.join(',')}`
43
+
44
+ return ''
45
+ }
46
+
47
+ private async fetchBrandsOnly(options: CatalogSearchParams): Promise<string[]> {
48
+ return this.productCatalog.productRepository
49
+ .findCatalog(
50
+ {
51
+ fields: ['id'],
52
+ filters: {
53
+ published: { operator: Where.EQUALS, value: true },
54
+ },
55
+ options: {
56
+ distinct: ['brand'],
57
+ },
58
+ },
59
+ options.mainGender,
60
+ )
61
+ .then((result) => result.distinct.brand)
62
+ }
63
+ }
@@ -0,0 +1,50 @@
1
+ import { Injectable } from '@angular/core'
2
+ import { Product, RepositoryFindFielters, Where, set } from '@infrab4a/connect'
3
+
4
+ import { CatalogFilters } from '../../../interfaces'
5
+
6
+ @Injectable()
7
+ export class CatalogFilterHelper {
8
+ buildFilterQuery(filters: CatalogFilters): RepositoryFindFielters<Product> {
9
+ const filterQuery = {} as RepositoryFindFielters<Product>
10
+
11
+ if (filters.clubDiscount?.length) {
12
+ set(filterQuery, 'price.subscriberDiscountPercentage', {
13
+ operator: Where.IN,
14
+ value: filters.clubDiscount,
15
+ })
16
+ }
17
+
18
+ if (filters.brands?.length) {
19
+ filterQuery.brand = { operator: Where.IN, value: filters.brands }
20
+ }
21
+
22
+ if (filters.gender?.length) {
23
+ filterQuery.gender = { operator: Where.IN, value: filters.gender }
24
+ }
25
+
26
+ if (filters.prices?.min || filters.prices?.max) {
27
+ const priceField = filters.prices.subscriberPrice ? 'price.subscriberPrice' : 'price.price'
28
+ const priceFilters = [
29
+ ...(filters.prices.min ? [{ operator: Where.GTE, value: Math.floor(filters.prices.min) }] : []),
30
+ ...(filters.prices.max ? [{ operator: Where.LTE, value: Math.ceil(filters.prices.max) }] : []),
31
+ ]
32
+
33
+ set(filterQuery, priceField, priceFilters)
34
+ }
35
+
36
+ if (filters.rate) {
37
+ filterQuery.rate = { operator: Where.GTE, value: filters.rate }
38
+ }
39
+
40
+ if (filters.tags?.length) {
41
+ filterQuery.tags = { operator: Where.LIKE, value: filters.tags }
42
+ }
43
+
44
+ if (filters.customOptions?.length) {
45
+ filterQuery.filters = { operator: Where.LIKE, value: filters.customOptions }
46
+ }
47
+
48
+ return filterQuery
49
+ }
50
+ }
@@ -0,0 +1,54 @@
1
+ import { Injectable } from '@angular/core'
2
+ import { Product, RepositoryOrderBy } from '@infrab4a/connect'
3
+
4
+ @Injectable()
5
+ export class CatalogSortHelper {
6
+ buildSortQuery(sort: string): RepositoryOrderBy<Product> {
7
+ if (!sort || sort === 'most-relevant') return {}
8
+
9
+ switch (sort) {
10
+ case 'best-sellers':
11
+ return {
12
+ shoppingCount: 'desc',
13
+ rate: 'desc',
14
+ stock: 'desc',
15
+ name: 'asc',
16
+ }
17
+
18
+ case 'biggest-price':
19
+ return {
20
+ subscriberPrice: 'desc',
21
+ rate: 'desc',
22
+ shoppingCount: 'desc',
23
+ } as any
24
+
25
+ case 'lowest-price':
26
+ return {
27
+ subscriberPrice: 'asc',
28
+ rate: 'desc',
29
+ shoppingCount: 'desc',
30
+ } as any
31
+
32
+ case 'best-rating':
33
+ return {
34
+ rate: 'desc',
35
+ shoppingCount: 'desc',
36
+ stock: 'desc',
37
+ name: 'asc',
38
+ }
39
+
40
+ case 'news':
41
+ return { createdAt: 'desc' }
42
+
43
+ case 'biggest-discount':
44
+ return {
45
+ subscriberDiscountPercentage: 'desc',
46
+ rate: 'desc',
47
+ shoppingCount: 'desc',
48
+ } as any
49
+
50
+ default:
51
+ return {}
52
+ }
53
+ }
54
+ }
@@ -0,0 +1,4 @@
1
+ export * from './brand-manager.helper'
2
+ export * from './catalog-filter.helper'
3
+ export * from './catalog-sort.helper'
4
+ export * from './product-fields.helper'
@@ -0,0 +1,35 @@
1
+ import { Injectable } from '@angular/core'
2
+ import { NonFunctionPropertyNames, Product } from '@infrab4a/connect'
3
+
4
+ @Injectable()
5
+ export class ProductFieldsHelper {
6
+ getStandardFields(): NonFunctionPropertyNames<Product>[] {
7
+ return [
8
+ 'id',
9
+ 'name',
10
+ 'slug',
11
+ 'images',
12
+ 'miniatures',
13
+ 'price',
14
+ 'stock',
15
+ 'published',
16
+ 'CEST',
17
+ 'EAN',
18
+ 'NCM',
19
+ 'brand',
20
+ 'costPrice',
21
+ 'hasVariants',
22
+ 'isKit',
23
+ 'sku',
24
+ 'rate',
25
+ 'tags',
26
+ 'type',
27
+ 'shoppingCount',
28
+ 'gender',
29
+ 'createdAt',
30
+ 'label',
31
+ 'outlet',
32
+ 'group',
33
+ ]
34
+ }
35
+ }
@@ -0,0 +1,7 @@
1
+ export * from './adapters'
2
+ export * from './catalog.service'
3
+ export * from './category.service'
4
+ export * from './enums'
5
+ export * from './models'
6
+ export * from './types'
7
+ export * from './wishlist.service'
@@ -0,0 +1,7 @@
1
+ import { Type } from 'class-transformer'
2
+ import { Category } from '@infrab4a/connect'
3
+
4
+ export class CategoryWithTree extends Category {
5
+ @Type(() => CategoryWithTree)
6
+ children?: CategoryWithTree[]
7
+ }
@@ -0,0 +1 @@
1
+ export * from './category-with-tree.model'
@@ -0,0 +1,35 @@
1
+ import { Injectable } from '@angular/core'
2
+
3
+ import { ProductServicesFacade } from '../../../interfaces'
4
+ import { BrandManagerHelper, CatalogFilterHelper, CatalogSortHelper, ProductFieldsHelper } from '../helpers'
5
+
6
+ import { CatalogOperationsFacade } from './catalog-operations.facade'
7
+ import { ProductManagementFacade } from './product-management.facade'
8
+
9
+ @Injectable()
10
+ export class CatalogHelpersService {
11
+ constructor(
12
+ private readonly catalogOperations: CatalogOperationsFacade,
13
+ private readonly productManagement: ProductManagementFacade,
14
+ ) {}
15
+
16
+ getFilterHelper(): CatalogFilterHelper {
17
+ return this.catalogOperations.getFilterHelper()
18
+ }
19
+
20
+ getSortHelper(): CatalogSortHelper {
21
+ return this.catalogOperations.getSortHelper()
22
+ }
23
+
24
+ getFieldsHelper(): ProductFieldsHelper {
25
+ return this.catalogOperations.getFieldsHelper()
26
+ }
27
+
28
+ getBrandManager(): BrandManagerHelper {
29
+ return this.productManagement.getBrandManager()
30
+ }
31
+
32
+ getProductServices(): ProductServicesFacade {
33
+ return this.productManagement.getProductServices()
34
+ }
35
+ }
@@ -0,0 +1,24 @@
1
+ import { Injectable } from '@angular/core'
2
+
3
+ import { CatalogFilterHelper, CatalogSortHelper, ProductFieldsHelper } from '../helpers'
4
+
5
+ @Injectable()
6
+ export class CatalogOperationsFacade {
7
+ constructor(
8
+ private readonly filterHelper: CatalogFilterHelper,
9
+ private readonly sortHelper: CatalogSortHelper,
10
+ private readonly fieldsHelper: ProductFieldsHelper,
11
+ ) {}
12
+
13
+ getFilterHelper(): CatalogFilterHelper {
14
+ return this.filterHelper
15
+ }
16
+
17
+ getSortHelper(): CatalogSortHelper {
18
+ return this.sortHelper
19
+ }
20
+
21
+ getFieldsHelper(): ProductFieldsHelper {
22
+ return this.fieldsHelper
23
+ }
24
+ }
@@ -0,0 +1,20 @@
1
+ import { Injectable } from '@angular/core'
2
+
3
+ import { ProductServicesFacade } from '../../../interfaces'
4
+ import { ProductCatalogFacade } from '../facades'
5
+
6
+ @Injectable()
7
+ export class CatalogRepositoryService {
8
+ constructor(
9
+ private readonly productCatalog: ProductCatalogFacade,
10
+ private readonly productServices: ProductServicesFacade,
11
+ ) {}
12
+
13
+ getProductCatalog(): ProductCatalogFacade {
14
+ return this.productCatalog
15
+ }
16
+
17
+ getProductServices(): ProductServicesFacade {
18
+ return this.productServices
19
+ }
20
+ }
@@ -0,0 +1,4 @@
1
+ export { CatalogHelpersService } from './catalog-helpers.service'
2
+ export { CatalogOperationsFacade } from './catalog-operations.facade'
3
+ export * from './catalog-repository.service'
4
+ export { ProductManagementFacade } from './product-management.facade'
@@ -0,0 +1,20 @@
1
+ import { Injectable } from '@angular/core'
2
+
3
+ import { ProductServicesFacade } from '../../../interfaces'
4
+ import { BrandManagerHelper } from '../helpers'
5
+
6
+ @Injectable()
7
+ export class ProductManagementFacade {
8
+ constructor(
9
+ private readonly brandManager: BrandManagerHelper,
10
+ private readonly productServices: ProductServicesFacade,
11
+ ) {}
12
+
13
+ getBrandManager(): BrandManagerHelper {
14
+ return this.brandManager
15
+ }
16
+
17
+ getProductServices(): ProductServicesFacade {
18
+ return this.productServices
19
+ }
20
+ }
@@ -0,0 +1,172 @@
1
+ import { Injectable } from '@angular/core'
2
+ import { Product, RepositoryCacheOptions, RepositoryFindResult, Shops, Where, isEmpty } from '@infrab4a/connect'
3
+
4
+ import { CatalogSearchParams, CatalogSearchStrategy } from '../../../interfaces'
5
+ import { CatalogHelpersService, CatalogRepositoryService } from '../services'
6
+
7
+ import {
8
+ FindAndSortByMostRelevantParams,
9
+ SearchDefaultParams,
10
+ SearchWithMostRelevantParams,
11
+ } from './types/strategy-params.type'
12
+
13
+ @Injectable()
14
+ export class CategorySearchStrategy implements CatalogSearchStrategy {
15
+ constructor(
16
+ private readonly repositoryService: CatalogRepositoryService,
17
+ private readonly helpersService: CatalogHelpersService,
18
+ ) {}
19
+
20
+ async search(
21
+ params: CatalogSearchParams,
22
+ shop: Shops,
23
+ optionsCache?: { cache?: RepositoryCacheOptions },
24
+ ): Promise<RepositoryFindResult<Product>> {
25
+ const { category, filters, limits, sort, mainGender } = params
26
+
27
+ if (!category) {
28
+ throw new Error('Category is required for CategorySearchStrategy')
29
+ }
30
+
31
+ const fields = this.helpersService.getFieldsHelper().getStandardFields()
32
+
33
+ if (sort === 'most-relevant') {
34
+ return this.searchWithMostRelevant({
35
+ category,
36
+ filters,
37
+ limits,
38
+ shop,
39
+ mainGender,
40
+ optionsCache,
41
+ fields,
42
+ })
43
+ }
44
+
45
+ return this.searchDefault({
46
+ category,
47
+ filters,
48
+ limits,
49
+ shop,
50
+ mainGender,
51
+ sort,
52
+ optionsCache,
53
+ fields,
54
+ })
55
+ }
56
+
57
+ private async searchWithMostRelevant(params: SearchWithMostRelevantParams) {
58
+ const { category, filters, shop, optionsCache } = params
59
+ const mostRelevant = category.isWishlist ? [] : category.getMostRelevantByShop(shop)
60
+ const productsIds = await this.getProductIds(category, filters, optionsCache)
61
+
62
+ return this.findAndSortByMostRelevant({
63
+ mostRelevants: mostRelevant,
64
+ productIds: productsIds,
65
+ filters: params.filters,
66
+ limits: params.limits,
67
+ shop: params.shop,
68
+ mainGender: params.mainGender,
69
+ optionsCache: params.optionsCache,
70
+ fields: params.fields,
71
+ })
72
+ }
73
+
74
+ private async searchDefault(params: SearchDefaultParams) {
75
+ const { category, filters, limits, shop, mainGender, sort, optionsCache, fields } = params
76
+ const productCatalog = this.repositoryService.getProductCatalog()
77
+ const filterHelper = this.helpersService.getFilterHelper()
78
+ const sortHelper = this.helpersService.getSortHelper()
79
+
80
+ const repoParams = {
81
+ fields,
82
+ filters: {
83
+ ...(await productCatalog.categoryStructureAdapter.buildProductFilterByCategory(category)),
84
+ ...filterHelper.buildFilterQuery(filters || {}),
85
+ },
86
+ ...(sort ? { orderBy: sortHelper.buildSortQuery(sort) } : {}),
87
+ limits,
88
+ options: {
89
+ minimal: ['price'],
90
+ maximum: ['price'],
91
+ distinct: ['brand'],
92
+ },
93
+ }
94
+
95
+ return productCatalog.productRepository.findCatalog(
96
+ repoParams,
97
+ mainGender || (shop === Shops.MENSMARKET ? 'male' : 'female'),
98
+ optionsCache,
99
+ )
100
+ }
101
+
102
+ private async getProductIds(category: any, filters: any, optionsCache: any): Promise<string[]> {
103
+ const productCatalog = this.repositoryService.getProductCatalog()
104
+ const filterHelper = this.helpersService.getFilterHelper()
105
+
106
+ return productCatalog.productRepository
107
+ .findCatalog(
108
+ {
109
+ fields: ['id'],
110
+ filters: {
111
+ ...(await productCatalog.categoryStructureAdapter.buildProductFilterByCategory(category)),
112
+ ...filterHelper.buildFilterQuery(filters || {}),
113
+ },
114
+ },
115
+ undefined,
116
+ optionsCache,
117
+ )
118
+ .then((products) => products.data.map((product) => product.id))
119
+ }
120
+
121
+ private async findAndSortByMostRelevant(
122
+ params: FindAndSortByMostRelevantParams,
123
+ ): Promise<RepositoryFindResult<Product>> {
124
+ const { mostRelevants, productIds, filters, shop, mainGender, optionsCache, fields, limits } = params
125
+ const productCatalog = this.repositoryService.getProductCatalog()
126
+ const filterHelper = this.helpersService.getFilterHelper()
127
+ const sortHelper = this.helpersService.getSortHelper()
128
+
129
+ const mostRelevantProductsIds = [...new Set(mostRelevants.concat(productIds))]
130
+ const totalResult = await productCatalog.productRepository.findCatalog(
131
+ {
132
+ fields,
133
+ filters: {
134
+ id: { operator: Where.IN, value: mostRelevantProductsIds },
135
+ ...filterHelper.buildFilterQuery(filters || {}),
136
+ },
137
+ orderBy: sortHelper.buildSortQuery('best-sellers'),
138
+ options: {
139
+ minimal: ['price'],
140
+ maximum: ['price'],
141
+ ...(isEmpty(filters?.brands) ? { distinct: ['brand'] } : {}),
142
+ },
143
+ },
144
+ mainGender || (shop === Shops.MENSMARKET ? 'male' : 'female'),
145
+ optionsCache,
146
+ )
147
+
148
+ return this.sortProductsByRelevance(totalResult, mostRelevants, limits)
149
+ }
150
+
151
+ private sortProductsByRelevance(totalResult: any, mostRelevants: string[], limits: any) {
152
+ const mostRelevantWithoutStock = totalResult.data.filter(
153
+ (product: any) => mostRelevants.includes(product.id) && product.stock.quantity <= 0,
154
+ )
155
+ const firstProducts = totalResult.data
156
+ .filter((product: any) => mostRelevants.includes(product.id) && product.stock.quantity > 0)
157
+ .sort((a: any, b: any) => mostRelevants.indexOf(a.id) - mostRelevants.indexOf(b.id))
158
+ const lastProducts = totalResult.data
159
+ .filter((product: any) => !mostRelevants.includes(product.id))
160
+ .concat(mostRelevantWithoutStock)
161
+ const categoryMostRelevants = firstProducts.concat(lastProducts)
162
+ const resultFinal = categoryMostRelevants.slice(limits.offset, limits.offset + limits.limit)
163
+
164
+ return {
165
+ data: resultFinal,
166
+ count: totalResult.count,
167
+ maximum: totalResult.maximum,
168
+ minimal: totalResult.minimal,
169
+ distinct: totalResult.distinct,
170
+ }
171
+ }
172
+ }
@@ -0,0 +1,3 @@
1
+ export * from './category-search.strategy'
2
+ export * from './profile-search.strategy'
3
+ export * from './term-search.strategy'
@@ -0,0 +1,51 @@
1
+ import { Injectable } from '@angular/core'
2
+ import { Product, RepositoryCacheOptions, RepositoryFindResult, Shops, Where } from '@infrab4a/connect'
3
+
4
+ import { CatalogSearchParams, CatalogSearchStrategy } from '../../../interfaces'
5
+ import { CatalogHelpersService, CatalogRepositoryService } from '../services'
6
+
7
+ @Injectable()
8
+ export class ProfileSearchStrategy implements CatalogSearchStrategy {
9
+ constructor(
10
+ private readonly repositoryService: CatalogRepositoryService,
11
+ private readonly helpersService: CatalogHelpersService,
12
+ ) {}
13
+
14
+ async search(
15
+ params: CatalogSearchParams,
16
+ shop: Shops,
17
+ optionsCache?: { cache?: RepositoryCacheOptions },
18
+ ): Promise<RepositoryFindResult<Product>> {
19
+ const { profile, filters, limits, sort, mainGender } = params
20
+
21
+ if (!profile) {
22
+ throw new Error('Profile is required for ProfileSearchStrategy')
23
+ }
24
+
25
+ const productCatalog = this.repositoryService.getProductCatalog()
26
+ const filterHelper = this.helpersService.getFilterHelper()
27
+ const sortHelper = this.helpersService.getSortHelper()
28
+ const fieldsHelper = this.helpersService.getFieldsHelper()
29
+
30
+ const repoParams = {
31
+ fields: fieldsHelper.getStandardFields(),
32
+ filters: {
33
+ tags: { operator: Where.LIKE, value: profile },
34
+ ...filterHelper.buildFilterQuery(filters || {}),
35
+ },
36
+ ...(sort ? { orderBy: sortHelper.buildSortQuery(sort) } : {}),
37
+ limits,
38
+ options: {
39
+ minimal: ['price'],
40
+ maximum: ['price'],
41
+ distinct: ['brand'],
42
+ },
43
+ }
44
+
45
+ return productCatalog.productRepository.findCatalog(
46
+ repoParams,
47
+ mainGender || (shop === Shops.MENSMARKET ? 'male' : 'female'),
48
+ optionsCache,
49
+ )
50
+ }
51
+ }