Skip to content

Commit

Permalink
Merge pull request #446 from Ecwid/ECWID-153684
Browse files Browse the repository at this point in the history
ECWID-153684 - added new method searchBrands in API Client.
  • Loading branch information
Alexeyyy authored Dec 17, 2024
2 parents c01e7e2 + ef1bef7 commit 4e32c92
Show file tree
Hide file tree
Showing 11 changed files with 245 additions and 4 deletions.
5 changes: 3 additions & 2 deletions src/main/kotlin/com/ecwid/apiclient/v3/ApiClient.kt
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,6 @@ import com.ecwid.apiclient.v3.dto.customergroup.request.*
import com.ecwid.apiclient.v3.dto.customergroup.result.*
import com.ecwid.apiclient.v3.dto.instantsite.redirects.request.*
import com.ecwid.apiclient.v3.dto.instantsite.redirects.result.*
import com.ecwid.apiclient.v3.dto.order.request.*
import com.ecwid.apiclient.v3.dto.order.result.*
import com.ecwid.apiclient.v3.dto.productreview.request.*
import com.ecwid.apiclient.v3.dto.productreview.result.*
import com.ecwid.apiclient.v3.dto.producttype.request.*
Expand Down Expand Up @@ -55,6 +53,7 @@ import kotlin.reflect.KClass
open class ApiClient private constructor(
protected val apiClientHelper: ApiClientHelper,
storeProfileApiClient: StoreProfileApiClient,
brandsApiClient: BrandsApiClient,
productsApiClient: ProductsApiClient,
categoriesApiClient: CategoriesApiClient,
ordersApiClient: OrdersApiClient,
Expand All @@ -76,6 +75,7 @@ open class ApiClient private constructor(
storeExtrafieldsApiClient: StoreExtrafieldsApiClientImpl,
) :
StoreProfileApiClient by storeProfileApiClient,
BrandsApiClient by brandsApiClient,
ProductsApiClient by productsApiClient,
CategoriesApiClient by categoriesApiClient,
OrdersApiClient by ordersApiClient,
Expand All @@ -99,6 +99,7 @@ open class ApiClient private constructor(
constructor(apiClientHelper: ApiClientHelper) : this(
apiClientHelper = apiClientHelper,
storeProfileApiClient = StoreProfileApiClientImpl(apiClientHelper),
brandsApiClient = BrandsApiClientImpl(apiClientHelper),
productsApiClient = ProductsApiClientImpl(apiClientHelper),
categoriesApiClient = CategoriesApiClientImpl(apiClientHelper),
ordersApiClient = OrdersApiClientImpl(apiClientHelper),
Expand Down
21 changes: 21 additions & 0 deletions src/main/kotlin/com/ecwid/apiclient/v3/BrandsApiClient.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package com.ecwid.apiclient.v3

import com.ecwid.apiclient.v3.dto.brand.request.BrandsSearchRequest
import com.ecwid.apiclient.v3.dto.brand.result.BrandsSearchResult
import com.ecwid.apiclient.v3.dto.common.PartialResult
import kotlin.reflect.KClass

// Brands
// https://api-docs.ecwid.com/reference/product-brands
interface BrandsApiClient {
fun searchBrands(request: BrandsSearchRequest): BrandsSearchResult
fun <Result> searchBrands(request: BrandsSearchRequest, resultClass: KClass<Result>): Result
where Result : PartialResult<BrandsSearchResult>
}

@Suppress("EXTENSION_SHADOWED_BY_MEMBER")
inline fun <reified Result : PartialResult<BrandsSearchResult>> BrandsApiClient.searchBrands(
request: BrandsSearchRequest
): Result {
return searchBrands(request, resultClass = Result::class)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package com.ecwid.apiclient.v3.dto.brand.request

import com.ecwid.apiclient.v3.dto.ApiRequest
import com.ecwid.apiclient.v3.dto.common.PagingRequest
import com.ecwid.apiclient.v3.impl.RequestInfo
import com.ecwid.apiclient.v3.responsefields.ResponseFields

sealed class BrandsSearchRequest : ApiRequest {

data class ByFilters(
val limit: Int = 100,
override val offset: Int = 0,
val lang: String? = null,
val hiddenBrands: Boolean? = null,
val baseUrl: String? = null,
val cleanUrls: Boolean? = null,
val sortBy: SortOrder? = null,
val responseFields: ResponseFields = ResponseFields.All,
) : BrandsSearchRequest(), PagingRequest<ByFilters> {
override fun toRequestInfo() = RequestInfo.createGetRequest(
pathSegments = listOf(
"brands",
),
params = toParams(),
responseFields = responseFields,
)

private fun toParams(): Map<String, String> {
val request = this
return mutableMapOf<String, String>().apply {
put("limit", request.limit.toString())
put("offset", request.offset.toString())
request.lang?.let { put("lang", it) }
request.hiddenBrands?.let { put("hiddenBrands", it.toString()) }
request.baseUrl?.let { put("baseUrl", it) }
request.cleanUrls?.let { put("cleanUrls", it.toString()) }
request.sortBy?.let { put("sortBy", it.name) }
}.toMap()
}

override fun copyWithOffset(offset: Int) = copy(offset = offset)
}

@Suppress("unused")
enum class SortOrder {
PRODUCT_COUNT_DESC,
NAME_ASC,
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.ecwid.apiclient.v3.dto.brand.result

import com.ecwid.apiclient.v3.dto.common.ApiResultDTO

data class BrandsSearchResult(
val items: List<FetchedBrand> = listOf(),
val count: Int = 0,
val total: Int = 0,
val limit: Int = 0,
val offset: Int = 0
) : ApiResultDTO
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.ecwid.apiclient.v3.dto.brand.result

import com.ecwid.apiclient.v3.dto.common.ApiFetchedDTO
import com.ecwid.apiclient.v3.dto.common.ApiResultDTO

data class FetchedBrand(
val name: String = "",
val nameTranslated: Map<String, String>? = null,
val productsFilteredByBrandUrl: String? = null,
) : ApiFetchedDTO, ApiResultDTO {
override fun getModifyKind() = ApiFetchedDTO.ModifyKind.ReadOnly
}
26 changes: 26 additions & 0 deletions src/main/kotlin/com/ecwid/apiclient/v3/impl/BrandsApiClientImpl.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package com.ecwid.apiclient.v3.impl

import com.ecwid.apiclient.v3.ApiClientHelper
import com.ecwid.apiclient.v3.BrandsApiClient
import com.ecwid.apiclient.v3.dto.brand.request.BrandsSearchRequest
import com.ecwid.apiclient.v3.dto.brand.result.BrandsSearchResult
import com.ecwid.apiclient.v3.dto.common.PartialResult
import kotlin.reflect.KClass

internal class BrandsApiClientImpl(
private val apiClientHelper: ApiClientHelper,
) : BrandsApiClient {

override fun searchBrands(request: BrandsSearchRequest) =
apiClientHelper.makeObjectResultRequest<BrandsSearchResult>(request)

override fun <Result : PartialResult<BrandsSearchResult>> searchBrands(
request: BrandsSearchRequest,
resultClass: KClass<Result>
): Result {
return apiClientHelper.makeObjectPartialResultRequest(
request = request,
resultClass = resultClass,
)
}
}
96 changes: 96 additions & 0 deletions src/test/kotlin/com/ecwid/apiclient/v3/entity/BrandsTest.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
package com.ecwid.apiclient.v3.entity

import com.ecwid.apiclient.v3.dto.brand.request.BrandsSearchRequest
import com.ecwid.apiclient.v3.dto.product.request.ProductCreateRequest
import com.ecwid.apiclient.v3.dto.product.request.ProductsSearchRequest.ByFilters
import com.ecwid.apiclient.v3.dto.product.request.UpdatedProduct
import com.ecwid.apiclient.v3.dto.product.request.UpdatedProduct.*
import com.ecwid.apiclient.v3.util.randomAlphanumeric
import com.ecwid.apiclient.v3.util.randomPrice
import org.junit.jupiter.api.Assertions.assertTrue
import org.junit.jupiter.api.BeforeEach
import kotlin.test.Test
import kotlin.test.assertEquals

class BrandsTest : BaseEntityTest() {

@BeforeEach
override fun beforeEach() {
super.beforeEach()

initStoreProfile()
removeAllProducts()
}

@Test
fun getBrands() {
val brandedProductsCreateResult = createProductsWithBrands()

// Waiting till product became available for searching
brandedProductsCreateResult.skus.forEach { sku ->
waitForIndexedProducts(
productsSearchRequest = ByFilters(sku = sku),
desiredProductCount = 1
)
}

val result = apiClient.searchBrands(BrandsSearchRequest.ByFilters())
assertEquals(
brandedProductsCreateResult.brandNames,
result.items.map { it.name }
)
}

private fun createProductsWithBrands(productsCount: Int = 5): BrandedProductsCreateResult {
val brands = mutableListOf<String>()
val skus = mutableListOf<String>()

for (i in 1..productsCount) {
val randomBrand = randomAlphanumeric(8)
val randomSku = randomAlphanumeric(10)
val price = randomPrice()

val productCreateRequest = ProductCreateRequest(
newProduct = UpdatedProduct(
name = "Product $i ${randomAlphanumeric(8)}",
sku = randomSku,
price = price,
compareToPrice = 2 * price,
enabled = true,
quantity = 10,
attributes = listOf(
AttributeValue.createBrandAttributeValue(randomBrand),
),
options = listOf(
ProductOption.createSelectOption(
name = "Color",
choices = listOf(
ProductOptionChoice("Black"),
ProductOptionChoice("White"),
ProductOptionChoice("Yellow"),
ProductOptionChoice("Red")
),
defaultChoice = 0,
required = true
)
)
)
)
val productCreateResult = apiClient.createProduct(productCreateRequest)
assertTrue(productCreateResult.id > 0)

skus.add(randomSku)
brands.add(randomBrand)
}

return BrandedProductsCreateResult(
brandNames = brands,
skus = skus,
)
}

data class BrandedProductsCreateResult(
val brandNames: List<String>,
val skus: List<String>,
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,8 @@ val nullablePropertyRules: List<NullablePropertyRule<*, *>> = listOf(
productReviewMassUpdateRequestNullablePropertyRules,
productReviewSearchRequestNullablePropertyRules,
fetchedCustomersConfigNullablePropertyRules,
brandsSearchRequestNullablePropertyRules,
fetchedBrandNullablePropertyRules,
).flatten()

sealed class NullablePropertyRule<T, R>(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package com.ecwid.apiclient.v3.rule.nullablepropertyrules

import com.ecwid.apiclient.v3.dto.brand.request.BrandsSearchRequest
import com.ecwid.apiclient.v3.rule.NullablePropertyRule
import com.ecwid.apiclient.v3.rule.NullablePropertyRule.AllowNullable

val brandsSearchRequestNullablePropertyRules: List<NullablePropertyRule<*, *>> = listOf(
AllowNullable(BrandsSearchRequest.ByFilters::lang),
AllowNullable(BrandsSearchRequest.ByFilters::hiddenBrands),
AllowNullable(BrandsSearchRequest.ByFilters::baseUrl),
AllowNullable(BrandsSearchRequest.ByFilters::cleanUrls),
AllowNullable(BrandsSearchRequest.ByFilters::sortBy),
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.ecwid.apiclient.v3.rule.nullablepropertyrules

import com.ecwid.apiclient.v3.dto.brand.result.FetchedBrand
import com.ecwid.apiclient.v3.rule.NullablePropertyRule
import com.ecwid.apiclient.v3.rule.NullablePropertyRule.AllowNullable

val fetchedBrandNullablePropertyRules: List<NullablePropertyRule<*, *>> = listOf(
AllowNullable(FetchedBrand::nameTranslated),
AllowNullable(FetchedBrand::productsFilteredByBrandUrl),
)
4 changes: 2 additions & 2 deletions src/test/kotlin/com/ecwid/apiclient/v3/util/OrderUtils.kt
Original file line number Diff line number Diff line change
Expand Up @@ -105,9 +105,9 @@ fun generateTestOrder(): UpdatedOrder {
shippingMethodName = "Method " + randomAlphanumeric(8),
shippingRate = randomPrice(),
estimatedTransitTime = "Estimates " + randomAlphanumeric(8),
isPickup = false,
isPickup = true,
pickupInstruction = "Instruction " + randomAlphanumeric(64),
fulfillmentType = FulfillmentType.SHIPPING
fulfillmentType = FulfillmentType.PICKUP
),
taxesOnShipping = listOf(),
handlingFee = UpdatedOrder.HandlingFee(
Expand Down

0 comments on commit 4e32c92

Please sign in to comment.