Skip to content

Commit

Permalink
Adds mapping fix for order fulfillments (#106)
Browse files Browse the repository at this point in the history
* 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

* removing unecessary try/catch

* feedback implemented

* fixing tracking url mapping

* missing tests

* pom version update

* Updates release version

---------

Co-authored-by: Pedro Clericuzzi <[email protected]>
Co-authored-by: Pedro Clericuzzi <[email protected]>
  • Loading branch information
3 people authored Mar 29, 2023
1 parent dd7cd5c commit 4ece967
Show file tree
Hide file tree
Showing 4 changed files with 340 additions and 50 deletions.
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>com.channelape</groupId>
<artifactId>shopify-sdk</artifactId>
<version>2.6.0</version>
<version>2.8.0</version>

<name>Shopify SDK</name>
<description>Java SDK for Shopify REST API.</description>
Expand Down
115 changes: 66 additions & 49 deletions src/main/java/com/shopify/mappers/LegacyToFulfillmentOrderMapping.java
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,29 @@ public class LegacyToFulfillmentOrderMapping {

private static final Logger LOGGER = LoggerFactory.getLogger(LegacyToFulfillmentOrderMapping.class);

/**
* creates the fulfillment order's tracking info based on a fulfillment
* shopify fulfillment order based creation does not support a list of
* tracking urls, so we're getting the first one of CA's list if available.
* Otherwise we just grab the single tracking url string
*
* @param fulfillment
* the fulfillment to be created by the fulfillment order api
* @return the payload's tracking info
*/
private static ShopifyTrackingInfo getFulfillmentTrackingInfo(final ShopifyFulfillment fulfillment) {
final ShopifyTrackingInfo trackingInfo = new ShopifyTrackingInfo();
if (fulfillment.getTrackingUrls().size() > 0) {
trackingInfo.setUrl(fulfillment.getTrackingUrls().get(0));
} else {
trackingInfo.setUrl(fulfillment.getTrackingUrl());
}
trackingInfo.setNumber(fulfillment.getTrackingNumber());
trackingInfo.setCompany(fulfillment.getTrackingCompany());

return trackingInfo;
}

/**
* the idea here is to create a payload similar to what <a href=
* "https://shopify.dev/docs/api/admin-rest/2023-04/resources/fulfillmentorder#post-fulfillment-orders-fulfillment-order-id-move">we
Expand Down Expand Up @@ -70,6 +93,14 @@ public static ShopifyFulfillmentOrderMoveRequestRoot toShopifyMoveFulfillmentOrd
* have here</a>, the resulting payload will be sent to shopify via the
* active ShopifySdk instance
*
* we need to iterate through all fulfillmentOrder line items to determine
* which fulfillment order line items are going to be referenced inside the
* payload's line_items_by_fulfillment_order section
*
* if a shopify fulfillment is cancelled a new fulfillment order is added
* the old one gets it's supported actions emptied, so we need to make sure
* the current fulfillmentOrder supportes fulfillment creation under it
*
* @see ShopifySdk
* @see ShopifyFulfillmentPayloadRoot
*
Expand All @@ -83,57 +114,47 @@ public static ShopifyFulfillmentOrderMoveRequestRoot toShopifyMoveFulfillmentOrd
*/
public static ShopifyFulfillmentPayloadRoot toShopifyFulfillmentPayloadRoot(final ShopifyFulfillment fulfillment,
final List<ShopifyFulfillmentOrder> fulfillmentOrders) throws ShopifyEmptyLineItemsException {
try {
final ShopifyTrackingInfo trackingInfo = new ShopifyTrackingInfo();
final ShopifyFulfillmentPayload payload = new ShopifyFulfillmentPayload();
final List<ShopifyLineItemsByFulfillmentOrder> lineItemsByFulfillmentOrder = new LinkedList<>();

trackingInfo.setUrl(fulfillment.getTrackingUrl());
trackingInfo.setNumber(fulfillment.getTrackingNumber());
trackingInfo.setCompany(fulfillment.getTrackingCompany());

// here we need to iterate through all fulfillmentOrder line items
// to determine which fulfillment order line items are going to be
// referenced inside the payload's line_items_by_fulfillment_order
// section
for (final ShopifyFulfillmentOrder fulfillmentOrder : fulfillmentOrders) {
// if a shopify fulfillment is cancelled a new fulfillment order
// is added the old one gets it's supported actions emptied, so
// we need to make sure the current fulfillmentOrder supportes
// fulfillment creation under it
if (fulfillmentOrder.hasSupportedAction(SupportedActions.CREATE_FULFILLMENT)) {
ShopifyLineItemsByFulfillmentOrder lineItemsByFulfillment = new ShopifyLineItemsByFulfillmentOrder();
lineItemsByFulfillment.setFulfillmentOrderId(fulfillmentOrder.getId());
for (final ShopifyFulfillmentOrderLineItem fulfillmentOrderLineItem : fulfillmentOrder
.getLineItems()) {
for (final ShopifyLineItem fulfillmentLineItem : fulfillment.getLineItems()) {
if (fulfillmentOrderLineItem.getLineItemId().equals(fulfillmentLineItem.getId())) {
ShopifyFulfillmentOrderPayloadLineItem payloadLineItem = new ShopifyFulfillmentOrderPayloadLineItem(
fulfillmentOrderLineItem.getId(), fulfillmentLineItem.getQuantity());
lineItemsByFulfillment.getFulfillmentOrderLineItems().add(payloadLineItem);
}
final ShopifyTrackingInfo trackingInfo = getFulfillmentTrackingInfo(fulfillment);
final ShopifyFulfillmentPayload payload = new ShopifyFulfillmentPayload();
final List<ShopifyLineItemsByFulfillmentOrder> lineItemsByFulfillmentOrder = new LinkedList<>();

// here we need to iterate through all fulfillmentOrder line items
// to determine which fulfillment order line items are going to be
// referenced inside the payload's line_items_by_fulfillment_order
// section
for (final ShopifyFulfillmentOrder fulfillmentOrder : fulfillmentOrders) {
// if a shopify fulfillment is cancelled a new fulfillment order
// is added the old one gets it's supported actions emptied, so
// we need to make sure the current fulfillmentOrder supportes
// fulfillment creation under it
if (fulfillmentOrder.hasSupportedAction(SupportedActions.CREATE_FULFILLMENT)) {
ShopifyLineItemsByFulfillmentOrder lineItemsByFulfillment = new ShopifyLineItemsByFulfillmentOrder();
lineItemsByFulfillment.setFulfillmentOrderId(fulfillmentOrder.getId());
for (final ShopifyFulfillmentOrderLineItem fulfillmentOrderLineItem : fulfillmentOrder.getLineItems()) {
for (final ShopifyLineItem fulfillmentLineItem : fulfillment.getLineItems()) {
if (fulfillmentOrderLineItem.getLineItemId().equals(fulfillmentLineItem.getId())) {
ShopifyFulfillmentOrderPayloadLineItem payloadLineItem = new ShopifyFulfillmentOrderPayloadLineItem(
fulfillmentOrderLineItem.getId(), fulfillmentLineItem.getQuantity());
lineItemsByFulfillment.getFulfillmentOrderLineItems().add(payloadLineItem);
}
}
}

if (lineItemsByFulfillment.getFulfillmentOrderLineItems().size() > 0) {
lineItemsByFulfillmentOrder.add(lineItemsByFulfillment);
}
if (lineItemsByFulfillment.getFulfillmentOrderLineItems().size() > 0) {
lineItemsByFulfillmentOrder.add(lineItemsByFulfillment);
}
}
if (lineItemsByFulfillmentOrder.size() < 1)
throw new ShopifyEmptyLineItemsException();
}
if (lineItemsByFulfillmentOrder.size() < 1)
throw new ShopifyEmptyLineItemsException();

payload.setTrackingInfo(trackingInfo);
payload.setNotifyCustomer(fulfillment.isNotifyCustomer());
payload.setLineItemsByFulfillmentOrder(lineItemsByFulfillmentOrder);
payload.setTrackingInfo(trackingInfo);
payload.setNotifyCustomer(fulfillment.isNotifyCustomer());
payload.setLineItemsByFulfillmentOrder(lineItemsByFulfillmentOrder);

ShopifyFulfillmentPayloadRoot root = new ShopifyFulfillmentPayloadRoot();
root.setFulfillment(payload);
return root;
} catch (final Exception e) {
LOGGER.error("There was an error parsing fulfillmentOrder into a ShopifyFulfillment create payload", e);
throw e;
}
ShopifyFulfillmentPayloadRoot root = new ShopifyFulfillmentPayloadRoot();
root.setFulfillment(payload);
return root;
}

/**
Expand All @@ -153,13 +174,9 @@ public static ShopifyFulfillmentPayloadRoot toShopifyFulfillmentPayloadRoot(fina
public static ShopifyUpdateFulfillmentPayloadRoot toUpdateShopifyFulfillmentPayloadRoot(
final ShopifyFulfillment fulfillment) {
try {
final ShopifyTrackingInfo trackingInfo = new ShopifyTrackingInfo();
final ShopifyTrackingInfo trackingInfo = getFulfillmentTrackingInfo(fulfillment);
final ShopifyUpdateFulfillmentPayload payload = new ShopifyUpdateFulfillmentPayload();

trackingInfo.setUrl(fulfillment.getTrackingUrl());
trackingInfo.setNumber(fulfillment.getTrackingNumber());
trackingInfo.setCompany(fulfillment.getTrackingCompany());

payload.setTrackingInfo(trackingInfo);
payload.setNotifyCustomer(fulfillment.isNotifyCustomer());

Expand Down
73 changes: 73 additions & 0 deletions src/test/java/com/shopify/ShopifySdkTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
import com.shopify.exceptions.ShopifyClientException;
import com.shopify.exceptions.ShopifyEmptyLineItemsException;
import com.shopify.exceptions.ShopifyErrorResponseException;
import com.shopify.mappers.LegacyToFulfillmentOrderMapping;
import com.shopify.mappers.ShopifySdkObjectMapper;
import com.shopify.model.Count;
import com.shopify.model.Image;
Expand All @@ -69,6 +70,7 @@
import com.shopify.model.ShopifyFulfillmentCreationRequest;
import com.shopify.model.ShopifyFulfillmentOrder;
import com.shopify.model.ShopifyFulfillmentOrderLineItem;
import com.shopify.model.ShopifyFulfillmentPayloadRoot;
import com.shopify.model.ShopifyFulfillmentRoot;
import com.shopify.model.ShopifyFulfillmentUpdateRequest;
import com.shopify.model.ShopifyGetCustomersRequest;
Expand Down Expand Up @@ -447,6 +449,77 @@ public void givenSomeShopifyFulfillmentCreationRequestWhenCreatingShopifyFulfill

final ShopifyFulfillment actualShopifyFulfillment = shopifySdk.createFulfillment(request, fulfillmentOrders);

// making sure the tracking url mapping is correct
final ShopifyFulfillmentPayloadRoot payload = LegacyToFulfillmentOrderMapping
.toShopifyFulfillmentPayloadRoot(request.getRequest(), fulfillmentOrders);

assertEquals(payload.getFulfillment().getTrackingInfo().getUrl(), "tracking_url1");
assertValidFulfillment(currentFulfillment, actualShopifyFulfillment);
}

@Test
public void givenSomeShopifyFulfillmentCreationRequestWhenCreatingShopifyFulfillmentThenCreateAndReturnFulfillmentWithFulfillmentOrderApiWithoutTrackingUrlsArray()
throws JsonProcessingException, ConnectException, ShopifyEmptyLineItemsException {
final String lineItemId = "987";
final String fulfillmentOrderId = "1234";

final ShopifyLineItem lineItem = new ShopifyLineItem();
lineItem.setId(lineItemId);
lineItem.setSku("some_sku");
lineItem.setQuantity(5L);

List<ShopifyFulfillmentOrderLineItem> fulfillmentOrderLineItems = new LinkedList<>();
ShopifyFulfillmentOrderLineItem fulfillmentOrderLineItem = new ShopifyFulfillmentOrderLineItem();
fulfillmentOrderLineItem.setQuantity(1);
fulfillmentOrderLineItem.setLineItemId(lineItemId);
fulfillmentOrderLineItem.setFulfillableQuantity(1);
fulfillmentOrderLineItem.setFulfillmentOrderId(fulfillmentOrderId);
fulfillmentOrderLineItems.add(fulfillmentOrderLineItem);

final List<String> supportedActions = new LinkedList<>();
supportedActions.add("move");
supportedActions.add("create_fulfillment");

final ShopifyFulfillmentOrder fulfillmentOrder = new ShopifyFulfillmentOrder();
fulfillmentOrder.setId(fulfillmentOrderId);
fulfillmentOrder.setLineItems(fulfillmentOrderLineItems);
fulfillmentOrder.setSupportedActions(supportedActions);
fulfillmentOrder.setAssignedLocationId("5678");
final List<ShopifyFulfillmentOrder> fulfillmentOrders = new LinkedList<>();
fulfillmentOrders.add(fulfillmentOrder);

final String expectedPath = new StringBuilder().append(FORWARD_SLASH).append(ShopifySdk.API_VERSION_PREFIX)
.append(FORWARD_SLASH).append(SOME_API_VERSION).append(FORWARD_SLASH).append(ShopifySdk.FULFILLMENTS)
.toString();
final ShopifyFulfillment currentFulfillment = buildShopifyFulfillment(lineItem);
final ShopifyFulfillmentRoot shopifyFulfillmentRoot = new ShopifyFulfillmentRoot();
shopifyFulfillmentRoot.setFulfillment(currentFulfillment);

final String expectedResponseBodyString = getJsonString(ShopifyFulfillmentRoot.class, shopifyFulfillmentRoot);

final Status expectedStatus = Status.CREATED;
final int expectedStatusCode = expectedStatus.getStatusCode();
final JsonBodyCapture actualRequestBody = new JsonBodyCapture();
driver.addExpectation(
onRequestTo(expectedPath).withHeader(ShopifySdk.ACCESS_TOKEN_HEADER, accessToken)
.withMethod(Method.POST).capturingBodyIn(actualRequestBody),
giveResponse(expectedResponseBodyString, MediaType.APPLICATION_JSON).withStatus(expectedStatusCode)
.withHeader(ShopifySdk.DEPRECATED_REASON_HEADER, "Call to be removed from API.")
.withHeader("Location", new StringBuilder().append("https://test.myshopify.com/admin")
.append(expectedPath).toString()));

final ShopifyFulfillmentCreationRequest request = ShopifyFulfillmentCreationRequest.newBuilder()
.withOrderId("1234").withTrackingCompany("USPS").withTrackingNumber("12341234").withNotifyCustomer(true)
.withLineItems(Arrays.asList(lineItem)).withLocationId("1").withTrackingUrls(Arrays.asList()).build();

request.getRequest().setTrackingUrl("tracking_url");
final ShopifyFulfillment actualShopifyFulfillment = shopifySdk.createFulfillment(request, fulfillmentOrders);

// making sure the tracking url mapping is correct
final ShopifyFulfillmentPayloadRoot payload = LegacyToFulfillmentOrderMapping
.toShopifyFulfillmentPayloadRoot(request.getRequest(), fulfillmentOrders);

assertEquals(payload.getFulfillment().getTrackingInfo().getUrl(), "tracking_url");
assertValidFulfillment(currentFulfillment, actualShopifyFulfillment);
}

Expand Down
Loading

0 comments on commit 4ece967

Please sign in to comment.