Skip to content

Commit dd7cd5c

Browse files
ryankazokasdevclericuzziclericuzzi
authored
Release 2.6.0 (#101)
* migration to fulfillmet order api (2023-04) * javaDocs problem solved * feedback implemented * fulfillment order move response root added * feedback implemented * throwing exception if we cannot create a fulfillment * throwing exception for non supported actions * feedback implemented * Updates release version * Removes duplicate runs of ci during PRs --------- Co-authored-by: Pedro Clericuzzi <dev.clericuzzi@gmail.com> Co-authored-by: Pedro Clericuzzi <pedroclericuzzi@gmail.com>
1 parent 18217a7 commit dd7cd5c

31 files changed

+2051
-44
lines changed

.github/workflows/maven-feature-hotfix.yml

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,7 @@ name: Shopify SDK Build Feature/Hotfix Branch
55

66
on:
77
pull_request:
8-
push:
9-
branches:
10-
- '**'
11-
- '!master'
12-
- '!develop'
8+
139

1410
jobs:
1511
build:

pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
<modelVersion>4.0.0</modelVersion>
55
<groupId>com.channelape</groupId>
66
<artifactId>shopify-sdk</artifactId>
7-
<version>2.5.0</version>
7+
<version>2.6.0</version>
88

99
<name>Shopify SDK</name>
1010
<description>Java SDK for Shopify REST API.</description>

src/main/java/com/shopify/ShopifySdk.java

Lines changed: 151 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,9 @@
3737
import com.github.rholder.retry.WaitStrategies;
3838
import com.shopify.exceptions.ShopifyClientException;
3939
import com.shopify.exceptions.ShopifyErrorResponseException;
40+
import com.shopify.exceptions.ShopifyIncompatibleApiException;
41+
import com.shopify.exceptions.ShopifyEmptyLineItemsException;
42+
import com.shopify.mappers.LegacyToFulfillmentOrderMapping;
4043
import com.shopify.mappers.ResponseEntityToStringMapper;
4144
import com.shopify.mappers.ShopifySdkObjectMapper;
4245
import com.shopify.model.Count;
@@ -59,6 +62,11 @@
5962
import com.shopify.model.ShopifyCustomersRoot;
6063
import com.shopify.model.ShopifyFulfillment;
6164
import com.shopify.model.ShopifyFulfillmentCreationRequest;
65+
import com.shopify.model.ShopifyFulfillmentOrder;
66+
import com.shopify.model.ShopifyFulfillmentOrderMoveRequestRoot;
67+
import com.shopify.model.ShopifyFulfillmentOrderMoveResponseRoot;
68+
import com.shopify.model.ShopifyFulfillmentOrdersRoot;
69+
import com.shopify.model.ShopifyFulfillmentPayloadRoot;
6270
import com.shopify.model.ShopifyFulfillmentRoot;
6371
import com.shopify.model.ShopifyFulfillmentUpdateRequest;
6472
import com.shopify.model.ShopifyGetCustomersRequest;
@@ -96,6 +104,7 @@
96104
import com.shopify.model.ShopifyShop;
97105
import com.shopify.model.ShopifyTransaction;
98106
import com.shopify.model.ShopifyTransactionsRoot;
107+
import com.shopify.model.ShopifyUpdateFulfillmentPayloadRoot;
99108
import com.shopify.model.ShopifyVariant;
100109
import com.shopify.model.ShopifyVariantMetafieldCreationRequest;
101110
import com.shopify.model.ShopifyVariantRoot;
@@ -129,12 +138,15 @@ public class ShopifySdk {
129138
static final String RECURRING_APPLICATION_CHARGES = "recurring_application_charges";
130139
static final String ORDERS = "orders";
131140
static final String FULFILLMENTS = "fulfillments";
141+
static final String FULFILLMENT_ORDERS = "fulfillment_orders";
132142
static final String ACTIVATE = "activate";
133143
static final String IMAGES = "images";
134144
static final String SHOP = "shop";
135145
static final String COUNT = "count";
136146
static final String CLOSE = "close";
137147
static final String CANCEL = "cancel";
148+
static final String MOVE = "move";
149+
static final String UPDATE_TRACKING = "update_tracking";
138150
static final String METAFIELDS = "metafields";
139151
static final String RISKS = "risks";
140152
static final String LOCATIONS = "locations";
@@ -199,28 +211,34 @@ public class ShopifySdk {
199211
public static interface OptionalsStep {
200212

201213
/**
202-
* The Shopify SDK uses random waits in between retry attempts. Minimum duration
203-
* time to wait before retrying a failed request. Value must also be less than
204-
* {@link #withMaximumRequestRetryRandomDelay(int, TimeUnit) Maximum Request
205-
* Retry Random Delay}.<br>
214+
* The Shopify SDK uses random waits in between retry attempts. Minimum
215+
* duration time to wait before retrying a failed request. Value must
216+
* also be less than
217+
* {@link #withMaximumRequestRetryRandomDelay(int, TimeUnit) Maximum
218+
* Request Retry Random Delay}.<br>
206219
* Default value is: 1 second.
207220
*
208221
* @param duration
222+
* of the minimum retry delay
209223
* @param timeUnit
210-
* @return {@link OptionalsStep}
224+
* the time unit to be used (miliseconds, seconds, etc...)
225+
* @return {@link OptionalsStep} the OptionalsStep interface
211226
*/
212227
OptionalsStep withMinimumRequestRetryRandomDelay(int duration, TimeUnit timeUnit);
213228

214229
/**
215-
* The Shopify SDK uses random waits in between retry attempts. Maximum duration
216-
* time to wait before retrying a failed request. Value must also be more than
217-
* {@link #withMinimumRequestRetryRandomDelay(int, TimeUnit) Minimum Request
218-
* Retry Random Delay}.<br>
230+
* The Shopify SDK uses random waits in between retry attempts. Maximum
231+
* duration time to wait before retrying a failed request. Value must
232+
* also be more than
233+
* {@link #withMinimumRequestRetryRandomDelay(int, TimeUnit) Minimum
234+
* Request Retry Random Delay}.<br>
219235
* Default value is: 5 seconds.
220236
*
221237
* @param duration
238+
* of the maximum retry delay
222239
* @param timeUnit
223-
* @return {@link OptionalsStep}
240+
* the time unit to be used (miliseconds, seconds, etc...)
241+
* @return {@link OptionalsStep} the OptionalsStep interface
224242
*/
225243
OptionalsStep withMaximumRequestRetryRandomDelay(int duration, TimeUnit timeUnit);
226244

@@ -229,8 +247,10 @@ public static interface OptionalsStep {
229247
* Default value is: 3 minutes.
230248
*
231249
* @param duration
250+
* of the request timeout
232251
* @param timeUnit
233-
* @return {@link OptionalsStep}
252+
* the time unit to be used (miliseconds, seconds, etc...)
253+
* @return {@link OptionalsStep} the OptionalsStep interface
234254
*/
235255
OptionalsStep withMaximumRequestRetryTimeout(int duration, TimeUnit timeUnit);
236256

@@ -239,8 +259,10 @@ public static interface OptionalsStep {
239259
* Default value is: 1 minute.
240260
*
241261
* @param duration
262+
* of the connection timeout
242263
* @param timeUnit
243-
* @return {@link OptionalsStep}
264+
* the time unit to be used (miliseconds, seconds, etc...)
265+
* @return {@link OptionalsStep} the OptionalsStep interface
244266
*/
245267
OptionalsStep withConnectionTimeout(int duration, TimeUnit timeUnit);
246268

@@ -249,20 +271,23 @@ public static interface OptionalsStep {
249271
* Default value is: 15 seconds.
250272
*
251273
* @param duration
274+
* of the duration to be considered
252275
* @param timeUnit
253-
* @return {@link OptionalsStep}
276+
* the time unit to be used (miliseconds, seconds, etc...)
277+
* @return {@link OptionalsStep} the OptionalsStep interface
254278
*/
255279
OptionalsStep withReadTimeout(int duration, TimeUnit timeUnit);
256280

257281
/**
258-
* String representation of the version you want to use. If not populated, this
259-
* will use shopify oldest stable version. Although this is not recommended so
260-
* you can target a set of shopify features. Ex: '2020-10' '2020-07' '2020-04'.
261-
* If you are specifying the API URL ensure you leave off the version if you are
262-
* using this.
282+
* String representation of the version you want to use. If not
283+
* populated, this will use shopify oldest stable version. Although this
284+
* is not recommended so you can target a set of shopify features. Ex:
285+
* '2020-10' '2020-07' '2020-04'. If you are specifying the API URL
286+
* ensure you leave off the version if you are using this.
263287
*
264288
* @param apiVersion
265-
* @return
289+
* current apiVersion value
290+
* @return {@link OptionalsStep} the OptionalsStep interface
266291
*/
267292
OptionalsStep withApiVersion(final String apiVersion);
268293

@@ -688,24 +713,75 @@ public ShopifyPage<ShopifyOrder> getOrders(final String pageInfo, final int page
688713
return getOrders(response);
689714
}
690715

716+
/**
717+
* Creates a fulfillment in shopify
718+
*
719+
* @deprecated starting in March 01, 2023 this method will be obsolete
720+
* @param shopifyFulfillmentCreationRequest
721+
* the fulfillment creaton request
722+
* @return the newly created fulfillment
723+
*/
724+
@Deprecated
691725
public ShopifyFulfillment createFulfillment(
692726
final ShopifyFulfillmentCreationRequest shopifyFulfillmentCreationRequest) {
727+
return this.createFulfillmentWithLegacyApi(shopifyFulfillmentCreationRequest);
728+
}
729+
730+
/**
731+
* Creates a fulfillment in shopify starting with api 2023-04
732+
*
733+
* @param shopifyFulfillmentCreationRequest
734+
* the fulfillment creaton request
735+
*
736+
* @param fulfillmentOrders
737+
* the fulfillment orders list to create the new fulfillment
738+
* @return the newly created fulfillment
739+
* @throws ShopifyEmptyLineItemsException
740+
* in case we have a fulfillment associated with a
741+
* fulfillmentOrder without supported action
742+
*/
743+
public ShopifyFulfillment createFulfillment(
744+
final ShopifyFulfillmentCreationRequest shopifyFulfillmentCreationRequest,
745+
List<ShopifyFulfillmentOrder> fulfillmentOrders) throws ShopifyEmptyLineItemsException {
746+
return this.createFulfillmentWithFulfillmentOrderApi(shopifyFulfillmentCreationRequest, fulfillmentOrders);
747+
}
748+
749+
/**
750+
* Updates a fulfillment in shopify
751+
*
752+
* @deprecated starting in March 01, 2023 this method will be obsolete
753+
* @param shopifyFulfillmentUpdateRequest
754+
* the fulfillment update request
755+
* @return the newly updated fulfillment
756+
*/
757+
@Deprecated
758+
public ShopifyFulfillment updateFulfillment(final ShopifyFulfillmentUpdateRequest shopifyFulfillmentUpdateRequest) {
693759
final ShopifyFulfillmentRoot shopifyFulfillmentRoot = new ShopifyFulfillmentRoot();
694-
final ShopifyFulfillment shopifyFulfillment = shopifyFulfillmentCreationRequest.getRequest();
695-
760+
final ShopifyFulfillment shopifyFulfillment = shopifyFulfillmentUpdateRequest.getRequest();
696761
shopifyFulfillmentRoot.setFulfillment(shopifyFulfillment);
697-
final Response response = post(buildOrdersEndpoint().path(shopifyFulfillment.getOrderId()).path(FULFILLMENTS),
698-
shopifyFulfillmentRoot);
762+
final Response response = put(buildOrdersEndpoint().path(shopifyFulfillment.getOrderId()).path(FULFILLMENTS)
763+
.path(shopifyFulfillment.getId()), shopifyFulfillmentRoot);
699764
final ShopifyFulfillmentRoot shopifyFulfillmentRootResponse = response.readEntity(ShopifyFulfillmentRoot.class);
700765
return shopifyFulfillmentRootResponse.getFulfillment();
701766
}
702767

703-
public ShopifyFulfillment updateFulfillment(final ShopifyFulfillmentUpdateRequest shopifyFulfillmentUpdateRequest) {
704-
final ShopifyFulfillmentRoot shopifyFulfillmentRoot = new ShopifyFulfillmentRoot();
768+
/**
769+
* Based on the api starting from 2023-04 it only updates tracking
770+
* information
771+
*
772+
* @param shopifyFulfillmentUpdateRequest
773+
* the information needed to update the fulfillment's tracking
774+
* info
775+
* @return the updated version of the shopify fulfillment
776+
*/
777+
public ShopifyFulfillment updateFulfillmentTrackingInfo(
778+
final ShopifyFulfillmentUpdateRequest shopifyFulfillmentUpdateRequest) {
705779
final ShopifyFulfillment shopifyFulfillment = shopifyFulfillmentUpdateRequest.getRequest();
706-
shopifyFulfillmentRoot.setFulfillment(shopifyFulfillment);
707-
final Response response = put(buildOrdersEndpoint().path(shopifyFulfillment.getOrderId()).path(FULFILLMENTS)
708-
.path(shopifyFulfillment.getId()), shopifyFulfillmentRoot);
780+
final ShopifyUpdateFulfillmentPayloadRoot payload = LegacyToFulfillmentOrderMapping
781+
.toUpdateShopifyFulfillmentPayloadRoot(shopifyFulfillment);
782+
783+
final Response response = post(
784+
getWebTarget().path(FULFILLMENTS).path(shopifyFulfillment.getId()).path(UPDATE_TRACKING), payload);
709785
final ShopifyFulfillmentRoot shopifyFulfillmentRootResponse = response.readEntity(ShopifyFulfillmentRoot.class);
710786
return shopifyFulfillmentRootResponse.getFulfillment();
711787
}
@@ -996,7 +1072,7 @@ private Response invokeResponseCallable(final Callable<Response> responseCallabl
9961072
}
9971073

9981074
private Retryer<Response> buildResponseRetyer() {
999-
return RetryerBuilder.<Response>newBuilder().retryIfResult(ShopifySdk::shouldRetryResponse).retryIfException()
1075+
return RetryerBuilder.<Response> newBuilder().retryIfResult(ShopifySdk::shouldRetryResponse).retryIfException()
10001076
.withWaitStrategy(WaitStrategies.randomWait(minimumRequestRetryRandomDelayMilliseconds,
10011077
TimeUnit.MILLISECONDS, maximumRequestRetryRandomDelayMilliseconds, TimeUnit.MILLISECONDS))
10021078
.withStopStrategy(
@@ -1156,4 +1232,50 @@ private String getQueryParam(final URI uri, final String key) {
11561232
private WebTarget buildOrdersEndpoint() {
11571233
return getWebTarget().path(ORDERS);
11581234
}
1235+
1236+
public List<ShopifyFulfillmentOrder> getFulfillmentOrdersFromOrder(final String shopifyOrderId) {
1237+
final List<ShopifyFulfillmentOrder> fulfillmentOrders = new LinkedList<>();
1238+
final Response response = get(buildOrdersEndpoint().path(shopifyOrderId).path(FULFILLMENT_ORDERS));
1239+
final ShopifyFulfillmentOrdersRoot shopifyFulfillmentOrdersRoot = response
1240+
.readEntity(ShopifyFulfillmentOrdersRoot.class);
1241+
1242+
fulfillmentOrders.addAll(shopifyFulfillmentOrdersRoot.getFulfillmentOrders());
1243+
1244+
return fulfillmentOrders;
1245+
}
1246+
1247+
public ShopifyFulfillmentOrder moveFulfillmentOrder(final String newLocationId,
1248+
final ShopifyFulfillmentOrder shopifyFulfillmentOrder) throws ShopifyIncompatibleApiException {
1249+
final ShopifyFulfillmentOrderMoveRequestRoot payload = LegacyToFulfillmentOrderMapping
1250+
.toShopifyMoveFulfillmentOrder(newLocationId, shopifyFulfillmentOrder);
1251+
1252+
final Response response = post(
1253+
getWebTarget().path(FULFILLMENT_ORDERS).path(shopifyFulfillmentOrder.getId()).path(MOVE), payload);
1254+
final ShopifyFulfillmentOrderMoveResponseRoot shopifyFulfillmentRootResponse = response
1255+
.readEntity(ShopifyFulfillmentOrderMoveResponseRoot.class);
1256+
return shopifyFulfillmentRootResponse.getOriginalFulfillmentOrder();
1257+
}
1258+
1259+
private ShopifyFulfillment createFulfillmentWithLegacyApi(
1260+
final ShopifyFulfillmentCreationRequest shopifyFulfillmentCreationRequest) {
1261+
final ShopifyFulfillmentRoot shopifyFulfillmentRoot = new ShopifyFulfillmentRoot();
1262+
final ShopifyFulfillment shopifyFulfillment = shopifyFulfillmentCreationRequest.getRequest();
1263+
shopifyFulfillmentRoot.setFulfillment(shopifyFulfillment);
1264+
final Response response = post(buildOrdersEndpoint().path(shopifyFulfillment.getOrderId()).path(FULFILLMENTS),
1265+
shopifyFulfillmentRoot);
1266+
final ShopifyFulfillmentRoot shopifyFulfillmentRootResponse = response.readEntity(ShopifyFulfillmentRoot.class);
1267+
return shopifyFulfillmentRootResponse.getFulfillment();
1268+
}
1269+
1270+
private ShopifyFulfillment createFulfillmentWithFulfillmentOrderApi(
1271+
final ShopifyFulfillmentCreationRequest shopifyFulfillmentCreationRequest,
1272+
final List<ShopifyFulfillmentOrder> fulfillmentOrders) throws ShopifyEmptyLineItemsException {
1273+
final ShopifyFulfillmentPayloadRoot payload = LegacyToFulfillmentOrderMapping
1274+
.toShopifyFulfillmentPayloadRoot(shopifyFulfillmentCreationRequest.getRequest(), fulfillmentOrders);
1275+
1276+
final Response response = post(getWebTarget().path(FULFILLMENTS), payload);
1277+
final ShopifyFulfillmentRoot shopifyFulfillmentRootResponse = response.readEntity(ShopifyFulfillmentRoot.class);
1278+
1279+
return shopifyFulfillmentRootResponse.getFulfillment();
1280+
}
11591281
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
package com.shopify.exceptions;
2+
3+
public class ShopifyEmptyLineItemsException extends Exception {
4+
private static final long serialVersionUID = -6803895255030397292L;
5+
6+
public ShopifyEmptyLineItemsException() {
7+
super("LineItems are required when creating a new fulfillment from a fulfillmentOrder");
8+
}
9+
10+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
package com.shopify.exceptions;
2+
3+
public class ShopifyIncompatibleApiException extends RuntimeException {
4+
5+
private static final String defaultMessage = "This action cannot be done in the current ShopifyApi version";
6+
private static final long serialVersionUID = 147838161361971621L;
7+
8+
public ShopifyIncompatibleApiException() {
9+
super(defaultMessage);
10+
}
11+
12+
public ShopifyIncompatibleApiException(final Throwable throwable) {
13+
super(defaultMessage, throwable);
14+
}
15+
16+
}

0 commit comments

Comments
 (0)