Use Case - Supplier Returns

What are supplier returns to Jungle?

Supplier return is a process that enables you to return products to your supplier for whatever the reason may be (ie: damaged, unwanted, etc.). In Jungle, a supplier return is represented by PurchaseReturn object.

Even though "Purchasing" is part of the object name itself, PurchaseReturn, by no means, has any strict technical dependencies on the purchasing process in general, or specifically PurchaseOrder object. You can create a supplier return as long as inventory is on hand, without prior existence of purchase orders or any receiving process.

The most significant elements of a PurchaseReturn involve:

  • A list of ReturnLineItem, describing the products to be returned.
  • A list of Allocation, describing groups of items to be fulfilled.

Creating a supplier return

In general, the steps to prepare a supplier return are in the following orders:

  1. Create a PurchaseReturn object.
  2. Create ReturnLineItem and add it to the created PurchaseReturn object.
  3. Create an Allocation to hold fulfilment details.
  4. Create AllocationLineItem to hold items to fulfill by associating ReturnLineItem created above with the Allocation.
  5. Move quantity from ReturnLineItem to the associated AllocationLineItem to populate the actual quantity for fulfilment.
  6. Approve PurchaseReturn to trigger the creation of a pack job.

For simplicity's sake, the example here goes for 1 Allocation per PurchaseReturn, and 1 AllocationLineItem per ReturnLineItem. In reality, there's no restriction over the amount of Allocation a PurchaseReturn can have, nor the amount of AllocationLineItem that can be associated with a ReturnLineItem. It's possible to have a PurchaseReturn broken down into several Allocation (for smaller shipments), while at the same time have multiple AllocationLineItem that each holds a part of the total quantity in ReturnLineItem.

Before we continue, the ID in the following examples are random. It may look like ID keeps incrementing by 1 every time something is created but that's not the case.

Create PurchaseReturn

Assuming you are returning products to supplier "Foo" that already exists with ID "100".

mutation purchaseReturnCreate {
  purchaseReturnCreate(
    input: {
      supplierId: "100"
      reference: "PR-001" # Doesn't need to be unique.
    }
  ) {
    __typename
    ... on MutationSuccess {
      objects {
        typename
        id
      }
    }
    ... on MutationFailure {
      reason
    }
  }
}

A successful response will look like this:

{
  "data": {
    "purchaseReturnCreate": {
      "__typename": "MutationSuccess",
      "objects": [
        {
          "typename": "PurchaseReturn",
          "id": "101"
        }
      ]
    }
  }
}

You now have PurchaseReturn with ID 101. You will need this to add ReturnLineItem in the next step.

Create ReturnLineItem

In this step, you will have to use the ID of the PurchaseReturn created in the previous step.

To define a list of items to return, you will need something to define the product (generally SKU) and quantity. There are 2 ways to populate the product data:

  • Nominate SKU explicitly.
  • Nominate ID of the line item this return is for (which can be from either sales order or purchase order). Product data from that line will be used to populate this return line.
mutation purchaseReturnLineItemReturningAdd {
  purchaseReturnLineItemReturningAdd(
    input: {
      id: "101" # Use I
      lineItemsReturning: [
        { sku: "SKU-01", quantity: 1 }
        { lineItemId: "4720", quantity: 1 } # This refers to a line in PurchaseOrder with SKU "SKU-02".
      ]
    }
  ) {
    __typename
    ... on MutationSuccess {
      objects {
        typename
        id
      }
    }
    ... on MutationFailure {
      reason
    }
  }
}

A successful response will look like this:

{
  "data": {
    "purchaseReturnLineItemReturningAdd": {
      "__typename": "MutationSuccess",
      "objects": [
        {
          "typename": "ReturnLineItem",
          "id": "102"
        },
        {
          "typename": "ReturnLineItem",
          "id": "103"
        }
      ]
    }
  }
}

2 ReturnLineItem are created in response to the 2 entries from the input.

Create Allocation

In this step, you will create an allocation to hold the items and details for fulfilment. Input is mostly similar to one of order allocation, except that you don't need to provide a list of lineItems upfront (this will be handled in later steps). Basically the following information is required:

  • method: Fulfilment method. Most likely being SHIP, as this is going to end up in shipment.
  • serviceCode: Shipping service code. Either standard or express. Select depending on use case. This is no different from selecting the right service code for order allocation.
  • locationId: The top-level location where the inventory is returned from
  • shippingAddress: The address where the inventory is returned to. This would most likely be the supplier's address.

Assuming you are shipping with "standard" service from "Jungle HQ" (ID 50) to supplier "Foo" located at "70 Mary St, Brisbane":

mutation allocationCreate {
  allocationCreate(
    input: {
      name: "RETURN-100" # You can set a friendly name for the allocation.
      method: "SHIP"
      serviceCode: "standard"
      locationId: "50"
      shippingAddress: {
        lines: ["70 Mary St"]
        countryCode: "AU"
        suburb: "Brisbane"
        postalCode: "4000"
        contactPerson: { name: "Head of Foo", email: "head@foo.com" }
      }
    }
  ) {
    __typename
    ... on MutationSuccess {
      objects {
        typename
        id
      }
    }
    ... on MutationFailure {
      reason
    }
  }
}

There is another mutation with a similar name, which is orderAllocationCreate. That mutation is applied for Order Allocation and does not work here. However, there's a plan in the future to combine these 2 mutations together for easier consumption.

A successful response will look like this:

{
  "data": {
    "allocationCreate": {
      "__typename": "MutationSuccess",
      "objects": [
        {
          "typename": "Allocation",
          "id": "104"
        }
      ]
    }
  }
}

Create AllocationLineItem and populate quantity

Now you have created an Allocation. But it's currently empty. In order to have inventory allocated/assigned to the allocation and allow the system to create a pack job, the allocation needs to have lines. In this step, you will need the ID of the ReturnLineItem created before and the allocation ID.

mutation allocationLineItemAssociate {
  allocationLineItemAssociate(input: { allocationId: "104", lineItemId: "102" }) {
    __typename
    ... on MutationSuccess {
      objects {
        typename
        id
      }
    }
    ... on MutationFailure {
      reason
    }
  }
}

You will need to do this for each ReturnLineItem. In this example, you will need to run the mutation again with lineItemId: "103".

A successful response will look like this:

{
  "data": {
    "allocationLineItemAssociate": {
      "__typename": "MutationSuccess",
      "objects": [
        {
          "typename": "AllocationLineItem",
          "id": "105" // Actual ID may look much longer and in different format.
        }
      ]
    }
  }
}

It's time to populate quantity from ReturnLineItem to AllocationLineItem:

mutation allocationLineItemMove {
  allocationLineItemMove(
    input: {
      toAllocationLineItemId: "105"
      reason: "Populate AllocationLineItem for return" # It's a good practice to be as detailed as possible.
      # You can optionally provide the quantity this AllocationLineItem can hold (useful for spanning a ReturnLineItem over multiple AllocationLineItem).
      # If omitted, the quantity of the associated ReturnLineItem will be used.
      # quantity": 1
    }
  ) {
    __typename
    ... on MutationSuccess {
      objects {
        typename
        id
      }
    }
    ... on MutationFailure {
      reason
    }
  }
}

Similar to allocationLineItemAssociate, you will need to do this for each AllocationLineItem. In this example, you will need to run the mutation again with the remaining AllocationLineItem/

A successful response will look like this:

{
  "data": {
    "allocationLineItemMove": {
      "__typename": "MutationSuccess"
    }
  }
}

Approve PurchaseReturn

At this point, the PurchaseReturn created at the start should look like the following:

{
  "id": "101",
  "approved": false,
  "lineItemsQuantity": 2,
  "lineItemsCount": 2,
  "lineItemsReturning": {
    "results": [
      {
        "node": {
          "__typename": "ReturnLineItem",
          "id": "102",
          "quantity": 1,
          "sku": "SKU-01"
        }
      },
      {
        "node": {
          "__typename": "ReturnLineItem",
          "id": "103",
          "quantity": 1,
          "sku": "SKU-02"
        }
      }
    ]
  },
  "allocations": {
    "results": [
      {
        "node": {
          "id": "104",
          "location": {
            "name": "Jungle HQ"
          },
          "source": {
            "__typename": "PurchaseReturn"
          },
          "lineItemsConnection": {
            "results": [
              {
                "node": {
                  "id": "105",
                  "quantity": 1,
                  "lineItemV2": {
                    "id": "102",
                    "sku": "SKU-01"
                  }
                }
              },
              {
                "node": {
                  "id": "106",
                  "quantity": 1,
                  "lineItemV2": {
                    "id": "103",
                    "sku": "SKU-02"
                  }
                }
              }
            ]
          }
        }
      }
    ]
  }
}

No inventory will be allocated/assigned to the allocation (which inherently means no pack job for fulfilment) until the supplier return is approved. To approve the supplier return, use the following mutation:

mutation purchaseReturnApprove {
  purchaseReturnApprove(input: { id: "101" }) {
    __typename
    ... on MutationSuccess {
      objects {
        typename
        id
      }
    }
    ... on MutationFailure {
      reason
    }
  }
}

A successful response will look like this:

{
  "data": {
    "purchaseReturnApprove": {
      "__typename": "MutationSuccess"
    }
  }
}

Approving a purchase return is listed as the last step in this example but it's not necessarily the case. Approval can occur as soon as a PurchaseReturn is created. It being the last step in this example is only to make the demonstration easier to follow.

Fill 1

Can't find what you're looking for?

Contact Us