Reputation: 21
I am building an integration between Shopify and our ERP via the admin API using GraphQL. All is working well except when I try and get the exact prices for an order.
In the documentation discountedTotalSet should be 'The total line price after discounts are applied' but I am finding it returns the full price - see examples below.
Can anyone give me guidance on how to get the API to show the same prices that are on the order? I need this to match exactly line by line. This is the query I am using for the order:
{
node(id: "gid://shopify/Order/4866288156908") {
id
...on Order {
name
lineItems (first: 50) {
edges {
node {
id
quantity
sku
discountedTotalSet {
shopMoney {
currencyCode
amount
}
}
}
}
}
}
}
}
And this is the result, note amount says 599.00 but that is not correct, see screenshot for the same order from the UI.
{
"data": {
"node": {
"id": "gid://shopify/Order/4866288156908",
"name": "AK-1003",
"lineItems": {
"edges": [
{
"node": {
"id": "gid://shopify/LineItem/12356850286828",
"quantity": 1,
"sku": "AK-A1081",
"discountedTotalSet": {
"shopMoney": {
"currencyCode": "AUD",
"amount": "599.0"
}
}
}
}
]
}
}
},
Shopify UI screenshotemphasized text
Upvotes: 2
Views: 1702
Reputation: 1965
discountedTotalSet
gives you the amount after discounts applied to that particular line. In your example you're applying a discount to the whole order. There is no field, in the lineItem
object that will give you the expected value for that line.
So you have to distribute the whole discount to each single line. I had the exact same problem and I had to implement this solution in python, I hope it helps:
from decimal import Decimal
def split_discounts(money, n):
quotient = Decimal(round(((money * Decimal(100)) // n) / Decimal(100), 2))
remainder = int(money * 100 % n)
q1 = Decimal(round(quotient + Decimal(0.01), 2)) # quotient + 0.01
result = [q1] * remainder + [quotient] * (n - remainder)
return result # returns an array of discounted amounts
def retrieve_shop_money(obj):
return Decimal(obj['shopMoney']['amount']) if obj and obj['shopMoney'] and obj['shopMoney']['amount'] else Decimal(
0) # this is just to retrieve the inner shopMoney field
def get_line_price(order_node):
discount = retrieve_shop_money(order_node["cartDiscountAmountSet"])
non_free_lines = len([1 for item in order_node["lineItems"]["edges"] if
retrieve_shop_money(item["node"]["discountedTotalSet"]) > 0])
if non_free_lines > 0:
discounts = split_discounts(discount, non_free_lines)
else:
discounts = 0 # this was an edge case for me, that you might not consider
discounted = 0
for item in order_node["lineItems"]["edges"]:
gross = retrieve_shop_money(item["node"]["originalTotalSet"]) # THIS IS THE VALUE WITHOUT DISCOUNTS
net = retrieve_shop_money(item["node"]["discountedTotalSet"])
if net > 0: # exluding free gifts
net = net - discounts[discounted] # THIS IS THE VALUE YOU'RE LOOKING FOR
discounted = discounted + 1
So first I retrieve if the whole order was free. This was an edge case that was giving me some issues. In that case I just know that 0 is the answer I want.
Otherwise with the method split_discounts
I calculate each single disount to be applied to the lines. Discounts can be different because if you discount $1 out of 3 items is going to be [0.33,0.33,0.34]
. So the result is an array. Then I just loop through the lines and apply the discount if discountedTotalSet
is >0
.
Thinking about it, you might also want to be sure that the discount is greater than the value of the line. But that is an edge case that I never encouted, but depends on the kind of discounts you have.
Upvotes: 2