tgflash
tgflash

Reputation: 21

Shopify Admin API: How To Get Correct Prices For Discounted Order?

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

Answers (1)

Fabio Filippi
Fabio Filippi

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

Related Questions