OrderCloud: Resource Dependency Cheat Sheet

Reading Time: 5 minutes

 145 views

In this article, we will review the OrderCloud resources that we interact with directly or indirectly within the OrderCloud API to identify the dependencies that will guide the order of operations for implementations such as a data import. We will also identify a few platform nuances, or gotchas, to be aware of.

Introduction

We will start at the end, for quick reference, with the following dependency overview diagram shows OrderCloud resources, excluding the complete set of order resources, organised into priority groups. Each group number, represents the order in which data should typically be processed in an implementation to avoid any dependency conflicts in the OrderCloud API responses. For example, resources in group 1 would typically be executed before resources in group 2, group 2 before group 3, etc.

The overview diagram does not show the actual dependencies between resources, however in Resource Dependencies we break down each section (or logically grouped resources), aligned to the OrderCloud portal, to document the specific dependencies and note any nuances that should be considered when working with resources.

Figure 1: Resource dependency groups overview.

Resource Dependencies

In the following resource dependency graphs, the varying line colours are simply to differentiate the dependency references for each resource. The following legend also applies to the all graphs.

A resource reference is a reference in the resource’s url as opposed to the request body, e.g. /catalogs/{catalogID}/categories.

In order to understand the dependency graphs, we will look at the following example, where we want to import/sync supplier data via the OrderCloud API. If we were to attempt to create a supplier user where the supplier does not exist, we would encounter an EntityNotFound error in the API’s response.

Figure 2: Resource dependency example.

Using the dependency graph we can see that the supplier is a dependency and therefore if we aren’t planning on creating or updating the supplier then we should at least validate its existence before proceeding and with additional defensive programming we can proactively consider an alternate path of code logic instead.

private async Task<User> CreateSupplierUser(User supplierUser, string supplierID, string accessToken)
{
    var supplier = await oc.Suppliers.GetAsync(supplierID, accessToken);
    if (supplier == null)
    {
        // We implement our alternate code path here, for example:
        Logger.LogError($"Supplier '{supplierID}' should already exist. Supplier User '{supplierUser.ID}' will not be created.");
        return null;
    }

    return await oc.SupplierUsers.CreateAsync(supplierID, supplierUser, accessToken);
}

If we were importing all supplier information, using the dependency graph as a reference, we can identify the order of operations for our implementation to avoid dependency conflicts and optimise performance. For example, we know that we need to import suppliers before importing supplier users, while supplier addresses, suppliers users and supplier user groups can be safely imported asynchronously because they belong to the same dependency group.

// Group 1 dependencies
await ImportSuppliers();

// Group 2 dependencies
var supplierAddresses = ImportSupplierAddresses();
var supplierUsers = ImportSupplierUsers();
var supplierUserGroups = ImportSupplierUserGroups();
await Task.WhenAll(supplierAddresses, supplierUsers, supplierUserGroups);

// Group 3 dependencies
await ImportSupplierUserGroupAssignments();

Identifying the order of operations and employing defensive programming techniques will be critical in your solution design.

Authentication and Authorization Resources

Figure 3: Authentication and Authorization resource dependencies.

Seller

The seller resource dependencies have been broken out across two diagrams for clarity.

Figure 4: Seller resource dependencies.
Figure 5: Seller resource dependencies (cont.).

Buyers

The buyer resource has an implicit reference to the catalog resource as there is a nuance in the platform relating to buyer creation. When creating a buyer, the OrderCloud platform will create a catalog with the same ID. If a catalog with the same ID already exists, an IdExists error will be returned. However, if the catalog‘s ID is passed in as the DefaultCatalogID then the catalog will be associated to it instead, whereas if there is no catalog in existence an NotFound error will be returned.

Conditions1234
DefaultCatalogID providedNNYY
Catalog existsNYNY
Actions1234
Catalog created (201 response code)X
Catalog assigned to Buyer (201 response code)X
IdExists error (409 response code)X
NotFound error (404 response code)X
Table 1: Decision table for POST /buyers.
Figure 6: Buyer resource dependencies.

Suppliers

Figure 7: Supplier resource dependencies.

Product Catalogs

The product catalogs resource dependencies have been broken out across two diagrams for clarity.

Figure 8: Product Catalogs resource dependencies.

You will notice that the spec and spec option has a cyclical dependency. The nuance to the spec resource is that the DefaultOptionID cannot be assigned until after the spec option has been created, however it relies on the spec to exist. This chicken or egg scenario can be resolved by temporarily removing the DefaultOptionID before creating the spec and spec options then patching the value back onto the spec afterwards.

For the implicit references of Inventory > Product and Variant Inventory > Variant, the inventory objects updated on the Product and Variant input models, so they can be treated as being on the same level if applied together. However, the inventory cannot be created/updated without the existence on the Product/Variant entities.

// 1. Remove the DefaultOptionID from the spec prior to creation
var defaultOptionID = spec.DefaultOptionID;
spec.DefaultOptionID = null;
await orderCloudClient.Specs.CreateAsync(spec, accessToken);

// 2. Create the spec options
await ImportSpecOptions(specOptions);

// 3. Patch the spec's DefaultOptionID
await PatchSpecDefaultOptionID(spec, defaultOptionID);
Figure 9: Product Catalogs resource dependencies (cont.).

Orders and Fulfillment

For orders and fulfillment, we will focus on the promotion and seller approval rule resources as these a more typical of a Marketplace setup, whereasall other order resources typically represent historical order placement data, which is outside the scope of this article.

There is a seemingly cyclical dependency between the promotion and order resources, however the promotion-to-order is an implicit resource reference, which does not impact the validation logic for persistence of the promotion resource. Instead, it is used to identify the overall redemption count and user redemption count from orders placed and is used in the validation logic when applying a promotion to an order. When migrating data, excluding order data, between environments, this data inconsistency may be incorrectly identified as an environmental bug, which you can avoid troubleshooting with this knowledge.

Figure 10: Orders and Fulfillment resource dependencies.

Summary

Resource dependencies can be considered a huge gotcha when it comes to long-term maintenance. By having a sound knowledge of resource dependencies and nuances within the OrderCloud API, and employing defensive programming techniques, robust and performant ecommerce implementation can become a byproduct of good solution design.

References

Leave a Reply

Your email address will not be published.