Skip to content

Commit 4e32c92

Browse files
authored
Merge pull request #446 from Ecwid/ECWID-153684
ECWID-153684 - added new method searchBrands in API Client.
2 parents c01e7e2 + ef1bef7 commit 4e32c92

File tree

11 files changed

+245
-4
lines changed

11 files changed

+245
-4
lines changed

src/main/kotlin/com/ecwid/apiclient/v3/ApiClient.kt

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,6 @@ import com.ecwid.apiclient.v3.dto.customergroup.request.*
2626
import com.ecwid.apiclient.v3.dto.customergroup.result.*
2727
import com.ecwid.apiclient.v3.dto.instantsite.redirects.request.*
2828
import com.ecwid.apiclient.v3.dto.instantsite.redirects.result.*
29-
import com.ecwid.apiclient.v3.dto.order.request.*
30-
import com.ecwid.apiclient.v3.dto.order.result.*
3129
import com.ecwid.apiclient.v3.dto.productreview.request.*
3230
import com.ecwid.apiclient.v3.dto.productreview.result.*
3331
import com.ecwid.apiclient.v3.dto.producttype.request.*
@@ -55,6 +53,7 @@ import kotlin.reflect.KClass
5553
open class ApiClient private constructor(
5654
protected val apiClientHelper: ApiClientHelper,
5755
storeProfileApiClient: StoreProfileApiClient,
56+
brandsApiClient: BrandsApiClient,
5857
productsApiClient: ProductsApiClient,
5958
categoriesApiClient: CategoriesApiClient,
6059
ordersApiClient: OrdersApiClient,
@@ -76,6 +75,7 @@ open class ApiClient private constructor(
7675
storeExtrafieldsApiClient: StoreExtrafieldsApiClientImpl,
7776
) :
7877
StoreProfileApiClient by storeProfileApiClient,
78+
BrandsApiClient by brandsApiClient,
7979
ProductsApiClient by productsApiClient,
8080
CategoriesApiClient by categoriesApiClient,
8181
OrdersApiClient by ordersApiClient,
@@ -99,6 +99,7 @@ open class ApiClient private constructor(
9999
constructor(apiClientHelper: ApiClientHelper) : this(
100100
apiClientHelper = apiClientHelper,
101101
storeProfileApiClient = StoreProfileApiClientImpl(apiClientHelper),
102+
brandsApiClient = BrandsApiClientImpl(apiClientHelper),
102103
productsApiClient = ProductsApiClientImpl(apiClientHelper),
103104
categoriesApiClient = CategoriesApiClientImpl(apiClientHelper),
104105
ordersApiClient = OrdersApiClientImpl(apiClientHelper),
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package com.ecwid.apiclient.v3
2+
3+
import com.ecwid.apiclient.v3.dto.brand.request.BrandsSearchRequest
4+
import com.ecwid.apiclient.v3.dto.brand.result.BrandsSearchResult
5+
import com.ecwid.apiclient.v3.dto.common.PartialResult
6+
import kotlin.reflect.KClass
7+
8+
// Brands
9+
// https://api-docs.ecwid.com/reference/product-brands
10+
interface BrandsApiClient {
11+
fun searchBrands(request: BrandsSearchRequest): BrandsSearchResult
12+
fun <Result> searchBrands(request: BrandsSearchRequest, resultClass: KClass<Result>): Result
13+
where Result : PartialResult<BrandsSearchResult>
14+
}
15+
16+
@Suppress("EXTENSION_SHADOWED_BY_MEMBER")
17+
inline fun <reified Result : PartialResult<BrandsSearchResult>> BrandsApiClient.searchBrands(
18+
request: BrandsSearchRequest
19+
): Result {
20+
return searchBrands(request, resultClass = Result::class)
21+
}
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
package com.ecwid.apiclient.v3.dto.brand.request
2+
3+
import com.ecwid.apiclient.v3.dto.ApiRequest
4+
import com.ecwid.apiclient.v3.dto.common.PagingRequest
5+
import com.ecwid.apiclient.v3.impl.RequestInfo
6+
import com.ecwid.apiclient.v3.responsefields.ResponseFields
7+
8+
sealed class BrandsSearchRequest : ApiRequest {
9+
10+
data class ByFilters(
11+
val limit: Int = 100,
12+
override val offset: Int = 0,
13+
val lang: String? = null,
14+
val hiddenBrands: Boolean? = null,
15+
val baseUrl: String? = null,
16+
val cleanUrls: Boolean? = null,
17+
val sortBy: SortOrder? = null,
18+
val responseFields: ResponseFields = ResponseFields.All,
19+
) : BrandsSearchRequest(), PagingRequest<ByFilters> {
20+
override fun toRequestInfo() = RequestInfo.createGetRequest(
21+
pathSegments = listOf(
22+
"brands",
23+
),
24+
params = toParams(),
25+
responseFields = responseFields,
26+
)
27+
28+
private fun toParams(): Map<String, String> {
29+
val request = this
30+
return mutableMapOf<String, String>().apply {
31+
put("limit", request.limit.toString())
32+
put("offset", request.offset.toString())
33+
request.lang?.let { put("lang", it) }
34+
request.hiddenBrands?.let { put("hiddenBrands", it.toString()) }
35+
request.baseUrl?.let { put("baseUrl", it) }
36+
request.cleanUrls?.let { put("cleanUrls", it.toString()) }
37+
request.sortBy?.let { put("sortBy", it.name) }
38+
}.toMap()
39+
}
40+
41+
override fun copyWithOffset(offset: Int) = copy(offset = offset)
42+
}
43+
44+
@Suppress("unused")
45+
enum class SortOrder {
46+
PRODUCT_COUNT_DESC,
47+
NAME_ASC,
48+
}
49+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package com.ecwid.apiclient.v3.dto.brand.result
2+
3+
import com.ecwid.apiclient.v3.dto.common.ApiResultDTO
4+
5+
data class BrandsSearchResult(
6+
val items: List<FetchedBrand> = listOf(),
7+
val count: Int = 0,
8+
val total: Int = 0,
9+
val limit: Int = 0,
10+
val offset: Int = 0
11+
) : ApiResultDTO
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
package com.ecwid.apiclient.v3.dto.brand.result
2+
3+
import com.ecwid.apiclient.v3.dto.common.ApiFetchedDTO
4+
import com.ecwid.apiclient.v3.dto.common.ApiResultDTO
5+
6+
data class FetchedBrand(
7+
val name: String = "",
8+
val nameTranslated: Map<String, String>? = null,
9+
val productsFilteredByBrandUrl: String? = null,
10+
) : ApiFetchedDTO, ApiResultDTO {
11+
override fun getModifyKind() = ApiFetchedDTO.ModifyKind.ReadOnly
12+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
package com.ecwid.apiclient.v3.impl
2+
3+
import com.ecwid.apiclient.v3.ApiClientHelper
4+
import com.ecwid.apiclient.v3.BrandsApiClient
5+
import com.ecwid.apiclient.v3.dto.brand.request.BrandsSearchRequest
6+
import com.ecwid.apiclient.v3.dto.brand.result.BrandsSearchResult
7+
import com.ecwid.apiclient.v3.dto.common.PartialResult
8+
import kotlin.reflect.KClass
9+
10+
internal class BrandsApiClientImpl(
11+
private val apiClientHelper: ApiClientHelper,
12+
) : BrandsApiClient {
13+
14+
override fun searchBrands(request: BrandsSearchRequest) =
15+
apiClientHelper.makeObjectResultRequest<BrandsSearchResult>(request)
16+
17+
override fun <Result : PartialResult<BrandsSearchResult>> searchBrands(
18+
request: BrandsSearchRequest,
19+
resultClass: KClass<Result>
20+
): Result {
21+
return apiClientHelper.makeObjectPartialResultRequest(
22+
request = request,
23+
resultClass = resultClass,
24+
)
25+
}
26+
}
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
package com.ecwid.apiclient.v3.entity
2+
3+
import com.ecwid.apiclient.v3.dto.brand.request.BrandsSearchRequest
4+
import com.ecwid.apiclient.v3.dto.product.request.ProductCreateRequest
5+
import com.ecwid.apiclient.v3.dto.product.request.ProductsSearchRequest.ByFilters
6+
import com.ecwid.apiclient.v3.dto.product.request.UpdatedProduct
7+
import com.ecwid.apiclient.v3.dto.product.request.UpdatedProduct.*
8+
import com.ecwid.apiclient.v3.util.randomAlphanumeric
9+
import com.ecwid.apiclient.v3.util.randomPrice
10+
import org.junit.jupiter.api.Assertions.assertTrue
11+
import org.junit.jupiter.api.BeforeEach
12+
import kotlin.test.Test
13+
import kotlin.test.assertEquals
14+
15+
class BrandsTest : BaseEntityTest() {
16+
17+
@BeforeEach
18+
override fun beforeEach() {
19+
super.beforeEach()
20+
21+
initStoreProfile()
22+
removeAllProducts()
23+
}
24+
25+
@Test
26+
fun getBrands() {
27+
val brandedProductsCreateResult = createProductsWithBrands()
28+
29+
// Waiting till product became available for searching
30+
brandedProductsCreateResult.skus.forEach { sku ->
31+
waitForIndexedProducts(
32+
productsSearchRequest = ByFilters(sku = sku),
33+
desiredProductCount = 1
34+
)
35+
}
36+
37+
val result = apiClient.searchBrands(BrandsSearchRequest.ByFilters())
38+
assertEquals(
39+
brandedProductsCreateResult.brandNames,
40+
result.items.map { it.name }
41+
)
42+
}
43+
44+
private fun createProductsWithBrands(productsCount: Int = 5): BrandedProductsCreateResult {
45+
val brands = mutableListOf<String>()
46+
val skus = mutableListOf<String>()
47+
48+
for (i in 1..productsCount) {
49+
val randomBrand = randomAlphanumeric(8)
50+
val randomSku = randomAlphanumeric(10)
51+
val price = randomPrice()
52+
53+
val productCreateRequest = ProductCreateRequest(
54+
newProduct = UpdatedProduct(
55+
name = "Product $i ${randomAlphanumeric(8)}",
56+
sku = randomSku,
57+
price = price,
58+
compareToPrice = 2 * price,
59+
enabled = true,
60+
quantity = 10,
61+
attributes = listOf(
62+
AttributeValue.createBrandAttributeValue(randomBrand),
63+
),
64+
options = listOf(
65+
ProductOption.createSelectOption(
66+
name = "Color",
67+
choices = listOf(
68+
ProductOptionChoice("Black"),
69+
ProductOptionChoice("White"),
70+
ProductOptionChoice("Yellow"),
71+
ProductOptionChoice("Red")
72+
),
73+
defaultChoice = 0,
74+
required = true
75+
)
76+
)
77+
)
78+
)
79+
val productCreateResult = apiClient.createProduct(productCreateRequest)
80+
assertTrue(productCreateResult.id > 0)
81+
82+
skus.add(randomSku)
83+
brands.add(randomBrand)
84+
}
85+
86+
return BrandedProductsCreateResult(
87+
brandNames = brands,
88+
skus = skus,
89+
)
90+
}
91+
92+
data class BrandedProductsCreateResult(
93+
val brandNames: List<String>,
94+
val skus: List<String>,
95+
)
96+
}

src/test/kotlin/com/ecwid/apiclient/v3/rule/NullablePropertyRules.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,8 @@ val nullablePropertyRules: List<NullablePropertyRule<*, *>> = listOf(
200200
productReviewMassUpdateRequestNullablePropertyRules,
201201
productReviewSearchRequestNullablePropertyRules,
202202
fetchedCustomersConfigNullablePropertyRules,
203+
brandsSearchRequestNullablePropertyRules,
204+
fetchedBrandNullablePropertyRules,
203205
).flatten()
204206

205207
sealed class NullablePropertyRule<T, R>(
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package com.ecwid.apiclient.v3.rule.nullablepropertyrules
2+
3+
import com.ecwid.apiclient.v3.dto.brand.request.BrandsSearchRequest
4+
import com.ecwid.apiclient.v3.rule.NullablePropertyRule
5+
import com.ecwid.apiclient.v3.rule.NullablePropertyRule.AllowNullable
6+
7+
val brandsSearchRequestNullablePropertyRules: List<NullablePropertyRule<*, *>> = listOf(
8+
AllowNullable(BrandsSearchRequest.ByFilters::lang),
9+
AllowNullable(BrandsSearchRequest.ByFilters::hiddenBrands),
10+
AllowNullable(BrandsSearchRequest.ByFilters::baseUrl),
11+
AllowNullable(BrandsSearchRequest.ByFilters::cleanUrls),
12+
AllowNullable(BrandsSearchRequest.ByFilters::sortBy),
13+
)
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
package com.ecwid.apiclient.v3.rule.nullablepropertyrules
2+
3+
import com.ecwid.apiclient.v3.dto.brand.result.FetchedBrand
4+
import com.ecwid.apiclient.v3.rule.NullablePropertyRule
5+
import com.ecwid.apiclient.v3.rule.NullablePropertyRule.AllowNullable
6+
7+
val fetchedBrandNullablePropertyRules: List<NullablePropertyRule<*, *>> = listOf(
8+
AllowNullable(FetchedBrand::nameTranslated),
9+
AllowNullable(FetchedBrand::productsFilteredByBrandUrl),
10+
)

0 commit comments

Comments
 (0)