[API] Discussion - Orders and Adjustments

Hi team,

I’m opening a conversation here about the orders/{number}.json endpoint. My intention is that the API will become focal in the refactoring of adjustments :pray:

This endpoint returns the breakdown of a specific order. It contains all order details in cluding line items, fees, product details, shipping and payment details… like, everything. This is the only OFN endpoint that will offer the line items of an order.

This code snippet is a section of a response from orders/{number}.json. I’ve removed the bulk of it so there is only one or two or each kind of object included in the snippet. In this post I want to explain the endpoint in a bit of detail so that we don’t all have to unpack the json code. Then I’ll add a few thoughts about what’s missing and what would be nice to change. In this post I am focusing on adjustments because that work is happening now. However if you have other thoughts feel free to contribute because it will be interesting to understand others’ use cases.

Find the full code snippet here.

The order object itself is pretty nice and self explanatory:

“id”: 1465395,
“number”: “R185726477”,
“user_id”: 211695,
“full_name”: “H”,
“email”: “h@yahoo.com”,
“phone”: “07977777777”,
“completed_at”: “December 02, 2020”,
“display_total”: “£153.68”,
“edit_path”: “/admin/orders/R185726477/edit”,
“state”: “complete”,
“payment_state”: “paid”,
“shipment_state”: “ready”,
“payments_path”: “/admin/orders/R185726477/payments”,
“ready_to_ship”: true,
“ready_to_capture”: null,
“created_at”: “December 02, 2020”,
“distributor_name”: “Aberystwyth Food Hub (New Online Farmers’ Market)”,
“special_instructions”: null,
“display_outstanding_balance”: “”,
“item_total”: “123.13”,
“adjustment_total”: “30.55”,
“payment_total”: “153.68”,
“total”: “153.68”,

Then we have details about the order cycles, enterprise and shipping method:

“order_cycle”: {
“id”: 206678
},
“shipping_method”: {
“id”: 200675,
“require_ship_address”: false,
“name”: "Collection time slots… ",
“description”: “After the order window closes you will receive an email confirming your personal collection time slot.\r\nVenue: The Morlan Centre, Queen’s Parade, Aberystwyth, SY23 2HH\r\n\r\nPlease turn up for your collection time slot in order to ensure this service is as safe as possible for everyone involved. Thanks for your understanding on this important matter”,
“price”: 0
},

Following this we have shipping and billing address. So unexciting I’m not going to post them.

And then comes the list of line items. Each line item looks like this:

“line_items”: [
{
“id”: 1116853,
“quantity”: 2,
“max_quantity”: null,
“price”: 3,
“variant”: {
“id”: 253904,
“is_master”: false,
“product_name”: “Beetroot”,
“sku”: “”,
“options_text”: “500g”,
“unit_value”: 500,
“unit_description”: “”,
“unit_to_display”: “500g”,
“display_as”: null,
“display_name”: null,
“name_to_display”: “Beetroot”,
“price”: “1.42”,
“on_demand”: true,
“on_hand”: 32,
“fees”: {},
“price_with_fees”: “1.42”,
“tag_list”: ,
“thumb_url”: “https://ofn-uk-production.s3.us-east-1.amazonaws.com/public/spree/products/15323/mini/5588A47E-6440-4508-9A87-250CCCB7A48A.jpeg?1603359545
}
}]

Following the list of line items comes the list of adjustments:

“adjustments”: [
{
“id”: 10257631,
“amount”: “-0.6”,
“label”: “Beetroot - admin fee by supplier Aberystwyth Food Hub (New Online Farmers’ Market)”,
“eligible”: true,
“source_type”: “Spree::LineItem”,
“source_id”: 1116853,
“adjustable_type”: “Spree::Order”,
“adjustable_id”: 1465395,
“originator_type”: “EnterpriseFee”,
“originator_id”: 200402
},

Weird things about this endpoint:

1. Tax Info is Missing

There is nothing about tax included anywhere. Tax needs to be calculated by querying the API separately to find tax rates and then applying them to products. This is maddness.

In actuality we need to know:

  • The line item total sale price
  • The line item cost price without tax
  • The fees added to the line item without tax
  • The tax amount on the cost price of the line item
  • The tax amount and type on the fees applied to the line item.

2. The list of adjustments is LONG.

Right now adjustments are applied to orders in quite an odd way.
The list of adjustments includes:

  • Shipping and Payment fee that apply to the whole order
  • Each fee that applies to a line item included as an individual ajustment object.

This means that for an order with 15 line items, 3 fees on the OC and a shipping and payment fee you end up with a list of 15*3+2 = 47 adjustments. Consuming the endpoint to create accurate figures for accounting software means looping through all the adjustments to try and apply them correctly to the right line item.

It seems odd to treat order adjustments and line item adjustments in the same way.

3. Prices are all over the place

Its worth having a play with the prices.

For example:

  "price": 3,
  "variant": {
    "price": "1.42",
    "fees": {},
    "price_with_fees": "1.42",

This is the breakdown of price per line item above. However these values still don’t include all information and the adjustments need to be iterated to create the correct line item price. Making this endpoint more useable will involve tidying up some of these price fields so that they offer clear naming and a simpler ability to derive different prices, fees and taxes per line item.

Obviously since OFN consumes this endpoint ourselves we’ll need to do any redesigning and refactoring carefully!

So I read this far… what now?

I’m sure some folks will just go off and design a new endpoint. I’d really like the people that aren’t contemplating just writing an endpoint reading this to have a think and see if there is anything else you find odd about this endpoint.

  • What else would you like an external accounting/POS tool to know?
  • What might make it easier to integrate with other platforms?
  • What tools might want to understand OFN orders to make them more effective?

For anyone that does just go and design a new endpoint - please share below with your explanations and questions :slight_smile:

Are we sure the current refactoring will benefit from this? Is that something Spree has made as well?

The API is mostly Spree’s API with some tweaks from us.
This strikes me as a perfect way to drive our work as an ‘API First’ team. Let’s design the API and the tests THEN write the code to meet these requirements.

Would be good to hear from the @devs on this.

What I’ve meant was: did Spree made their adjustments changes on their API as well?
I’ve understood that the adjustments refactoring was already solved in Spree and that our current work is inspired by what they have done.
I’d be interested to know what it means in terms of scope to add an API first requirement here :+1:

1 Like

OFN currently doesn’t have API endpoints for adjustments or line items, but Spree actually does. As a side note; it also has checkout endpoints on the API in spree 2.2. In some cases they might need to be customised for OFN, but there’s definitely potential for looking at bringing in some of those Spree API controllers, or at least looking at how they are doing things like the checkout endpoints (rather than re-inventing the wheel).

There should be lots of scope for showing much nicer data after the adjustments changes are made, like clear and simple tax breakdowns (which are not currently easy to do).

I didn’t realise we were returning all that adjustment data on the orders endpoint, it doesn’t look like a good idea to me. It would be better to have simpler order data there and a have a separate endpoint for the specific case where the client wants a ton of fine-grained adjustments data…