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:
- Create a
PurchaseReturn
object. - Create
ReturnLineItem
and add it to the createdPurchaseReturn
object. - Create an
Allocation
to hold fulfilment details. - Create
AllocationLineItem
to hold items to fulfill by associatingReturnLineItem
created above with theAllocation
. - Move quantity from
ReturnLineItem
to the associatedAllocationLineItem
to populate the actual quantity for fulfilment. - Approve
PurchaseReturn
to trigger the creation of a pack job.
For simplicity's sake, the example here goes for 1
Allocation
perPurchaseReturn
, and 1AllocationLineItem
perReturnLineItem
. In reality, there's no restriction over the amount ofAllocation
aPurchaseReturn
can have, nor the amount ofAllocationLineItem
that can be associated with aReturnLineItem
. It's possible to have aPurchaseReturn
broken down into severalAllocation
(for smaller shipments), while at the same time have multipleAllocationLineItem
that each holds a part of the total quantity inReturnLineItem
.
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 beingSHIP
, as this is going to end up in shipment.serviceCode
: Shipping service code. Eitherstandard
orexpress
. 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 fromshippingAddress
: 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 remainingAllocationLineItem
/
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.