openfoodfoundation / openfoodnetwork

Connect suppliers, distributors and consumers to trade local produce.
https://www.openfoodnetwork.org
GNU Affero General Public License v3.0
1.1k stars 713 forks source link

[DFC Orders] Create/update order when order is placed within OFN #12178

Open lin-d-hop opened 6 months ago

lin-d-hop commented 6 months ago

Funded Feature. Please track ALL ASSOCIATED WORK under the associated tracking code: #11678 DFC Orders

Description

  1. When customer places an order with a Hub that reduces On Hand for a DFC Product below 0:
  2. Check if we have a held order with the Producer for the current SalesSession.
  3. If so, update quantities as required.
  4. If not, create new held Order for any/all DFC products requiring replenishment.

Acceptance Criteria

RaggedStaff commented 6 months ago

@mkllnk - had a stab at updating this, let me know if it tallies with your understanding ?

mkllnk commented 6 months ago

Yes, looking good.

mkllnk commented 2 months ago

My current work in progress:

mkllnk commented 3 weeks ago

@RaggedStaff, my latest blocker is the orders endpoint responding with an error 500 when posting a new order. I don't know if it's a bug or just missing parameters. I'm sending POST https://env-0105831.jcloud-ver-jpe.ik-server.com/api/dfc/Enterprises/test-hodmedod/Orders:

{
    "@context": "https://www.datafoodconsortium.org",
    "@graph": [
        {
            "@type": "dfc-b:Order",
            "dfc-b:orderNumber": "",
            "dfc-b:date": "",
            "dfc-b:hasPart": {
                "@type": "dfc-b:OrderLine",
                "dfc-b:description": "",
                "dfc-b:quantity": 3,
                "dfc-b:concerns": "https://env-0105831.jcloud-ver-jpe.ik-server.com/api/dfc/Enterprises/test-hodmedod/SuppliedProducts/44519466238259/Offer"
            },
            "dfc-b:orderedBy": "http://test.host/api/dfc/enterprises/384"
        },
        {
            "@type": "dfc-b:OrderLine",
            "dfc-b:description": "",
            "dfc-b:quantity": 3,
            "dfc-b:concerns": "https://env-0105831.jcloud-ver-jpe.ik-server.com/api/dfc/Enterprises/test-hodmedod/SuppliedProducts/44519466238259/Offer"
        }
    ]
}

Comparing that to the spec by Garethe, I have some questions. There are a lot more fields which I thought were not needed here. But which ones are mandatory?

RaggedStaff commented 3 weeks ago

From a DFC Standard/ontology perspective, almost everything is optional. That said, Shopify will require some data to build an Order. Have you tried Orders.GET to see what it looks like coming back ?

I think you need to send

         "dfc-b:orderNumber": "#",

To indicate a null id.

You do need to include the states:

         "dfc-b:hasOrderStatus: Draft ,
         "dfc-b:hasFulfilmentStatus: Unfulfilled ,
         "dfc-b:hasPaymentStatus: Unpaid ,

Are the defaults, I think. @ajluker or @dupreesi can confirm what they expect/accept.

"dfc-b:hasPaymentMethod": I don't know any published payment methods. Is there a magical value here or can I omit?

Not enumerated within DFC, I think you can ommit this.

"dfc-b:discount": Surely not used here.

No, not required for this UC. May be applied by the creating platform.

"dfc-b:OrderedBy": Required? Person identified on the OFN? Or do I need to know the id of the person on the Shopify side?

This is the URI (Id) of the Agent placing the Order... in this case the Shopify customer. I'm expecting the receiving platform to handle that, using data from the OIDC credentials (& any linked account).

"dfc-b:soldBy": Required? Same, can I use the OFN id?

Not required, or even relevant for this UC.

"dfc-b:selects": Do I need to know a shipping method?

Nope. That should be set later (probably within the Shopify UI)

"dfc-b:uses": Same question.

I don't think PickUpOptions are valid for this pilot, but same story -

"dfc-b:hasPart": When posting an order, I don't set my own price, do I?

In this instance - hasPart indicates a relationship to an OrderLine object, which contains a link to Offer, not Price, there was an error in the ontology & the swagger spec needs updating. You will need to include at least 1 OrderLine object - as Shopify will not allow the creation of an order without a line item. You can will need to include:

RaggedStaff commented 3 weeks ago

Further to email thread... this is the latest POST command I've tried (as per @dupreesi 's update):

curl -X POST -k -H 'authorization: JWT ${oidc_token}' -i 'https://env-0105831.jcloud-ver-jpe.ik-server.com/api/dfc/Enterprises/test-hodmedod/Orders' --data '{
  "@context": "https://www.datafoodconsortium.org",
  "@graph": [
    {
      "@id": "_:b45457",
      "@type": "dfc-b:Price",
      "dfc-b:hasUnit": "dfc-m:PoundSterling",
      "dfc-b:value": "30.2"
    },
    {
      "@id": "https://env-0105831.jcloud-ver-jpe.ik-server.com/api/dfc/Enterprises/test-hodmedod/Offers/44519466271027",
      "@type": "dfc-b:Offer",
      "dfc-b:offeredItem": {
        "@id": "https://env-0105831.jcloud-ver-jpe.ik-server.com/api/dfc/Enterprises/test-hodmedod/SuppliedProducts/44519466271027"
      }
    },
    {
      "@id": "https://env-0105831.jcloud-ver-jpe.ik-server.com/api/dfc/Enterprises/test-hodmedod/Orders/#/OrderLines/1",
      "@type": "dfc-b:OrderLine",
      "dfc-b:concerns": {
        "@id": "https://env-0105831.jcloud-ver-jpe.ik-server.com/api/dfc/Enterprises/test-hodmedod/Offers/44519466271027"
      },
      "dfc-b:hasPrice": {
        "@id": "_:b45457"
      },
      "dfc-b:quantity": "1"
    },
    {
      "@id": "https://env-0105831.jcloud-ver-jpe.ik-server.com/api/dfc/Enterprises/test-hodmedod/SaleSession/001",
      "@type": "dfc-b:SaleSession",
      "dfc-b:endDate": "2024-08-13T09:00:00+01:00",
      "dfc-b:startDate": "2024-08-12T09:00:00+01:00"
    },
    {
      "@id": "https://env-0105831.jcloud-ver-jpe.ik-server.com/api/dfc/Enterprises/test-hodmedod/Orders/#",
      "@type": "dfc-b:Order",
      "dfc-b:belongsTo": {
        "@id": "https://env-0105831.jcloud-ver-jpe.ik-server.com/api/dfc/Enterprises/test-hodmedod/SaleSession/001"
      },
      "dfc-b:hasOrderStatus": "dfc-v:Held",
      "dfc-b:hasPart": {
        "@id": "https://env-0105831.jcloud-ver-jpe.ik-server.com/api/dfc/Enterprises/test-hodmedod/Orders/#/OrderLines/1"
      },
      "dfc-b:orderNumber": "OFN-TEST00012"
    }
  ]
}'

Still getting 500 error. 😖

dupreesi commented 2 weeks ago

Hi @RaggedStaff @mkllnk as promised here are some logs when a Hub sends Shopify Orders to the Producer. I hope it helps, if you are still having issues I'd suggest we try an debug on a call.

1. CREATE ORDER (POST https://env-0105831.jcloud-ver-jpe.ik-server.com/api/dfc/Enterprises/test-hodmedod/Orders)

Example request body for creating a DraftOrder ordering 5 cases of Apple Syrup from the producer (test-hodmedod). Note that we need to send Offers/1 + OrderLines/1 + Orders/# + SalesSession/# These generic Ids are needed for the DFC Connector to work. Shopify will then create own Ids (see following requests).

{
  "@context": "https://www.datafoodconsortium.org",
  "@graph": [
    {
      "@id": "https://env-0105831.jcloud-ver-jpe.ik-server.com/api/dfc/Enterprises/test-hodmedod/Offers/1",
      "@type": "dfc-b:Offer",
      "dfc-b:offeredItem": {
        "@id": "https://env-0105831.jcloud-ver-jpe.ik-server.com/api/dfc/Enterprises/test-hodmedod/SuppliedProducts/44519466402099"
      }
    },
    {
      "@id": "https://env-0105831.jcloud-ver-jpe.ik-server.com/api/dfc/Enterprises/test-hodmedod/Orders/#",
      "@type": "dfc-b:Order",
      "dfc-b:hasOrderStatus": {
        "@id": "dfc-v:Held"
      },
      "dfc-b:hasPart": {
        "@id": "https://env-0105831.jcloud-ver-jpe.ik-server.com/api/dfc/Enterprises/test-hodmedod/Orders/#/OrderLines/1"
      }
    },
    {
      "@id": "https://env-0105831.jcloud-ver-jpe.ik-server.com/api/dfc/Enterprises/test-hodmedod/Orders/#/OrderLines/1",
      "@type": "dfc-b:OrderLine",
      "dfc-b:concerns": {
        "@id": "https://env-0105831.jcloud-ver-jpe.ik-server.com/api/dfc/Enterprises/test-hodmedod/Offers/1"
      },
      "dfc-b:quantity": "5"
    },
    {
      "@id": "https://env-0105831.jcloud-ver-jpe.ik-server.com/api/dfc/Enterprises/test-hodmedod/SalesSession/#",
      "@type": "dfc-b:SaleSession",
      "dfc-b:beginDate": "Tue Aug 20 2024 08:02:23 GMT+0000 (Coordinated Universal Time)",
      "dfc-b:endDate": "Tue Aug 27 2024 08:02:23 GMT+0000 (Coordinated Universal Time)"
    },
    {
      "@id": "https://env-0105831.jcloud-ver-jpe.ik-server.com/api/dfc/Enterprises/test-hodmedod/SuppliedProducts/44519466402099",
      "@type": "dfc-b:SuppliedProduct"
    }
  ]
}

This post request created Draft 50:

Bildschirmfoto 2024-08-20 um 10 04 29 Bildschirmfoto 2024-08-20 um 10 04 38

2. UPDATE ORDER (PUT https://env-0105831.jcloud-ver-jpe.ik-server.com/api/dfc/Enterprises/test-hodmedod/Orders/1173026636083)

Example request body to update the existing Draft 50 (OrderId 1173026636083) with updated line items (10 cases of Barley Flakes). Note that for updating an existing DraftOrder, all of the existing + updated line items need to be sent. Once Shopify has created / updated a Draft Order, OrderLinesIds get created. When new OrderLines are being sent (that aren't part of the existing order), we can use an indexed Id, e.g. OrderLines.length + 1.

{
  "@context": "https://www.datafoodconsortium.org",
  "@graph": [
    {
      "@id": "https://env-0105831.jcloud-ver-jpe.ik-server.com/api/dfc/Enterprises/test-hodmedod/Offers/1",
      "@type": "dfc-b:Offer",
      "dfc-b:offeredItem": {
        "@id": "https://env-0105831.jcloud-ver-jpe.ik-server.com/api/dfc/Enterprises/test-hodmedod/SuppliedProducts/44519466402099"
      }
    },
    {
      "@id": "https://env-0105831.jcloud-ver-jpe.ik-server.com/api/dfc/Enterprises/test-hodmedod/Offers/2",
      "@type": "dfc-b:Offer",
      "dfc-b:offeredItem": {
        "@id": "https://env-0105831.jcloud-ver-jpe.ik-server.com/api/dfc/Enterprises/test-hodmedod/SuppliedProducts/44519466565939"
      }
    },
    {
      "@id": "https://env-0105831.jcloud-ver-jpe.ik-server.com/api/dfc/Enterprises/test-hodmedod/Orders/1173026636083",
      "@type": "dfc-b:Order",
      "dfc-b:hasOrderStatus": {
        "@id": "dfc-v:Held"
      },
      "dfc-b:hasPart": [
        {
          "@id": "https://env-0105831.jcloud-ver-jpe.ik-server.com/api/dfc/Enterprises/test-hodmedod/Orders/1173026636083/OrderLines/93"
        },
        {
          "@id": "https://env-0105831.jcloud-ver-jpe.ik-server.com/api/dfc/Enterprises/test-hodmedod/Orders/1173026636083/OrderLines/2"
        }
      ]
    },
    {
      "@id": "https://env-0105831.jcloud-ver-jpe.ik-server.com/api/dfc/Enterprises/test-hodmedod/Orders/1173026636083/OrderLines/2",
      "@type": "dfc-b:OrderLine",
      "dfc-b:concerns": {
        "@id": "https://env-0105831.jcloud-ver-jpe.ik-server.com/api/dfc/Enterprises/test-hodmedod/Offers/2"
      },
      "dfc-b:quantity": "10"
    },
    {
      "@id": "https://env-0105831.jcloud-ver-jpe.ik-server.com/api/dfc/Enterprises/test-hodmedod/Orders/1173026636083/OrderLines/93",
      "@type": "dfc-b:OrderLine",
      "dfc-b:concerns": {
        "@id": "https://env-0105831.jcloud-ver-jpe.ik-server.com/api/dfc/Enterprises/test-hodmedod/Offers/1"
      },
      "dfc-b:quantity": "5"
    },
    {
      "@id": "https://env-0105831.jcloud-ver-jpe.ik-server.com/api/dfc/Enterprises/test-hodmedod/SuppliedProducts/44519466402099",
      "@type": "dfc-b:SuppliedProduct"
    },
    {
      "@id": "https://env-0105831.jcloud-ver-jpe.ik-server.com/api/dfc/Enterprises/test-hodmedod/SuppliedProducts/44519466565939",
      "@type": "dfc-b:SuppliedProduct"
    }
  ]
}

Updated Draft Order:

Bildschirmfoto 2024-08-20 um 10 12 13

3. Ordering 7 cases of Baked British Beans (another PUT to https://env-0105831.jcloud-ver-jpe.ik-server.com/api/dfc/Enterprises/test-hodmedod/Orders/1173026636083)

Same principle as above - exiting + updated order lines are needed for Shopify to update the draft order.

{
  "@context": "https://www.datafoodconsortium.org",
  "@graph": [
    {
      "@id": "https://env-0105831.jcloud-ver-jpe.ik-server.com/api/dfc/Enterprises/test-hodmedod/Offers/1",
      "@type": "dfc-b:Offer",
      "dfc-b:offeredItem": {
        "@id": "https://env-0105831.jcloud-ver-jpe.ik-server.com/api/dfc/Enterprises/test-hodmedod/SuppliedProducts/44519466402099"
      }
    },
    {
      "@id": "https://env-0105831.jcloud-ver-jpe.ik-server.com/api/dfc/Enterprises/test-hodmedod/Offers/2",
      "@type": "dfc-b:Offer",
      "dfc-b:offeredItem": {
        "@id": "https://env-0105831.jcloud-ver-jpe.ik-server.com/api/dfc/Enterprises/test-hodmedod/SuppliedProducts/44519466565939"
      }
    },
    {
      "@id": "https://env-0105831.jcloud-ver-jpe.ik-server.com/api/dfc/Enterprises/test-hodmedod/Offers/3",
      "@type": "dfc-b:Offer",
      "dfc-b:offeredItem": {
        "@id": "https://env-0105831.jcloud-ver-jpe.ik-server.com/api/dfc/Enterprises/test-hodmedod/SuppliedProducts/44519466500403"
      }
    },
    {
      "@id": "https://env-0105831.jcloud-ver-jpe.ik-server.com/api/dfc/Enterprises/test-hodmedod/Orders/1173026636083",
      "@type": "dfc-b:Order",
      "dfc-b:hasOrderStatus": {
        "@id": "dfc-v:Held"
      },
      "dfc-b:hasPart": [
        {
          "@id": "https://env-0105831.jcloud-ver-jpe.ik-server.com/api/dfc/Enterprises/test-hodmedod/Orders/1173026636083/OrderLines/93"
        },
        {
          "@id": "https://env-0105831.jcloud-ver-jpe.ik-server.com/api/dfc/Enterprises/test-hodmedod/Orders/1173026636083/OrderLines/95"
        },
        {
          "@id": "https://env-0105831.jcloud-ver-jpe.ik-server.com/api/dfc/Enterprises/test-hodmedod/Orders/1173026636083/OrderLines/3"
        }
      ]
    },
    {
      "@id": "https://env-0105831.jcloud-ver-jpe.ik-server.com/api/dfc/Enterprises/test-hodmedod/Orders/1173026636083/OrderLines/3",
      "@type": "dfc-b:OrderLine",
      "dfc-b:concerns": {
        "@id": "https://env-0105831.jcloud-ver-jpe.ik-server.com/api/dfc/Enterprises/test-hodmedod/Offers/3"
      },
      "dfc-b:quantity": "7"
    },
    {
      "@id": "https://env-0105831.jcloud-ver-jpe.ik-server.com/api/dfc/Enterprises/test-hodmedod/Orders/1173026636083/OrderLines/93",
      "@type": "dfc-b:OrderLine",
      "dfc-b:concerns": {
        "@id": "https://env-0105831.jcloud-ver-jpe.ik-server.com/api/dfc/Enterprises/test-hodmedod/Offers/1"
      },
      "dfc-b:quantity": "5"
    },
    {
      "@id": "https://env-0105831.jcloud-ver-jpe.ik-server.com/api/dfc/Enterprises/test-hodmedod/Orders/1173026636083/OrderLines/95",
      "@type": "dfc-b:OrderLine",
      "dfc-b:concerns": {
        "@id": "https://env-0105831.jcloud-ver-jpe.ik-server.com/api/dfc/Enterprises/test-hodmedod/Offers/2"
      },
      "dfc-b:quantity": "10"
    },
    {
      "@id": "https://env-0105831.jcloud-ver-jpe.ik-server.com/api/dfc/Enterprises/test-hodmedod/SuppliedProducts/44519466402099",
      "@type": "dfc-b:SuppliedProduct"
    },
    {
      "@id": "https://env-0105831.jcloud-ver-jpe.ik-server.com/api/dfc/Enterprises/test-hodmedod/SuppliedProducts/44519466500403",
      "@type": "dfc-b:SuppliedProduct"
    },
    {
      "@id": "https://env-0105831.jcloud-ver-jpe.ik-server.com/api/dfc/Enterprises/test-hodmedod/SuppliedProducts/44519466565939",
      "@type": "dfc-b:SuppliedProduct"
    }
  ]
}

4. Completing the Draft Order (Also PUT to https://env-0105831.jcloud-ver-jpe.ik-server.com/api/dfc/Enterprises/test-hodmedod/Orders/1173026636083)

To complete the draft order the order status has to be updated using this request body:

{
  "@context": "https://www.datafoodconsortium.org",
  "@graph": [
    {
      "@id": "https://env-0105831.jcloud-ver-jpe.ik-server.com/api/dfc/Enterprises/test-hodmedod/Offers/1",
      "@type": "dfc-b:Offer",
      "dfc-b:offeredItem": {
        "@id": "https://env-0105831.jcloud-ver-jpe.ik-server.com/api/dfc/Enterprises/test-hodmedod/SuppliedProducts/44519466402099"
      }
    },
    {
      "@id": "https://env-0105831.jcloud-ver-jpe.ik-server.com/api/dfc/Enterprises/test-hodmedod/Offers/2",
      "@type": "dfc-b:Offer",
      "dfc-b:offeredItem": {
        "@id": "https://env-0105831.jcloud-ver-jpe.ik-server.com/api/dfc/Enterprises/test-hodmedod/SuppliedProducts/44519466565939"
      }
    },
    {
      "@id": "https://env-0105831.jcloud-ver-jpe.ik-server.com/api/dfc/Enterprises/test-hodmedod/Offers/3",
      "@type": "dfc-b:Offer",
      "dfc-b:offeredItem": {
        "@id": "https://env-0105831.jcloud-ver-jpe.ik-server.com/api/dfc/Enterprises/test-hodmedod/SuppliedProducts/44519466500403"
      }
    },
    {
      "@id": "https://env-0105831.jcloud-ver-jpe.ik-server.com/api/dfc/Enterprises/test-hodmedod/Orders/1173026636083",
      "@type": "dfc-b:Order",
      "dfc-b:hasOrderStatus": {
        "@id": "dfc-v:Complete"
      },
      "dfc-b:hasPart": [
        {
          "@id": "https://env-0105831.jcloud-ver-jpe.ik-server.com/api/dfc/Enterprises/test-hodmedod/Orders/1173026636083/OrderLines/93"
        },
        {
          "@id": "https://env-0105831.jcloud-ver-jpe.ik-server.com/api/dfc/Enterprises/test-hodmedod/Orders/1173026636083/OrderLines/95"
        },
        {
          "@id": "https://env-0105831.jcloud-ver-jpe.ik-server.com/api/dfc/Enterprises/test-hodmedod/Orders/1173026636083/OrderLines/98"
        }
      ]
    },
    {
      "@id": "https://env-0105831.jcloud-ver-jpe.ik-server.com/api/dfc/Enterprises/test-hodmedod/Orders/1173026636083/OrderLines/93",
      "@type": "dfc-b:OrderLine",
      "dfc-b:concerns": {
        "@id": "https://env-0105831.jcloud-ver-jpe.ik-server.com/api/dfc/Enterprises/test-hodmedod/Offers/1"
      },
      "dfc-b:quantity": "5"
    },
    {
      "@id": "https://env-0105831.jcloud-ver-jpe.ik-server.com/api/dfc/Enterprises/test-hodmedod/Orders/1173026636083/OrderLines/95",
      "@type": "dfc-b:OrderLine",
      "dfc-b:concerns": {
        "@id": "https://env-0105831.jcloud-ver-jpe.ik-server.com/api/dfc/Enterprises/test-hodmedod/Offers/2"
      },
      "dfc-b:quantity": "10"
    },
    {
      "@id": "https://env-0105831.jcloud-ver-jpe.ik-server.com/api/dfc/Enterprises/test-hodmedod/Orders/1173026636083/OrderLines/98",
      "@type": "dfc-b:OrderLine",
      "dfc-b:concerns": {
        "@id": "https://env-0105831.jcloud-ver-jpe.ik-server.com/api/dfc/Enterprises/test-hodmedod/Offers/3"
      },
      "dfc-b:quantity": "7"
    },
    {
      "@id": "https://env-0105831.jcloud-ver-jpe.ik-server.com/api/dfc/Enterprises/test-hodmedod/SuppliedProducts/44519466402099",
      "@type": "dfc-b:SuppliedProduct"
    },
    {
      "@id": "https://env-0105831.jcloud-ver-jpe.ik-server.com/api/dfc/Enterprises/test-hodmedod/SuppliedProducts/44519466500403",
      "@type": "dfc-b:SuppliedProduct"
    },
    {
      "@id": "https://env-0105831.jcloud-ver-jpe.ik-server.com/api/dfc/Enterprises/test-hodmedod/SuppliedProducts/44519466565939",
      "@type": "dfc-b:SuppliedProduct"
    }
  ]
}

Result:

Bildschirmfoto 2024-08-20 um 10 34 25
dupreesi commented 2 weeks ago

So in summary:

  1. get all supplied products that are available via the producer endpoint
  2. create a new order using one or more supplied products including their required Offers / OrderLines / SalesSession
  3. Get the OrderId of the created Order
  4. test the PUT endpoint to update the Order by its Id
mkllnk commented 2 weeks ago

I tried to follow your example as closely as possible and finally created an order. :tada:

Here are a few things I noticed:

dupreesi commented 2 weeks ago

Hey @mkllnk, I'm pleased to hear that it has worked! Regarding your first two remarks, I think it'd be best to check with @RaggedStaff as we're not in charge of refactoring code within the connector repository (we're only calling its functions to create the graph). Regarding the SalesSession - this is only used to send across the dates for the stock to be reserved until (end-date). We are also storing these dates in our database and there is an automation in place that automatically finishes a SalesSession and opens an new one based on the end date. Additionally, the hub user has the option to manually create or finish a SalesSession if needed. Once a SalesSession ends, the draft order is being completed and can be fulfilled. Regarding formatting the dates: do you think you could stick to the provided example format?

"Tue Aug 27 2024 08:02:23 GMT+0000 (Coordinated Universal Time)"
mkllnk commented 2 weeks ago

Once a SalesSession ends, the draft order is being completed and can be fulfilled.

Does that happen automatically or do we need to finalise the order by updating the status?

Regarding formatting the dates: do you think you could stick to the provided example format?

That's serialised by the connector. It's a standard JSON encoding for dates.

mkllnk commented 2 weeks ago

Regarding formatting the dates: do you think you could stick to the provided example format?

Follow up: the standard JSON format raised a server error again. I tried a few different formats and found:

dupreesi commented 2 weeks ago

Once a SalesSession ends, the draft order is being completed and can be fulfilled.

Does that happen automatically or do we need to finalise the order by updating the status?

At the moment there is not automation for external connections in place (only within the two Shopify Apps). So to end a SalesSession (Draft)Order you need to manually send a PUT with an updated order status (example 4).

{
      "@id": "https://env-0105831.jcloud-ver-jpe.ik-server.com/api/dfc/Enterprises/test-hodmedod/Orders/1173026636083",
      "@type": "dfc-b:Order",
      "dfc-b:hasOrderStatus": {
        "@id": "dfc-v:Complete"
      }

Great that the dates are working. Thanks for checking!

RaggedStaff commented 3 days ago

@dupreesi - I think we will need to standardise date formats (to ISO) at some point. I'll create an issue for that on the backlog.

mkllnk commented 3 days ago

@dupreesi, I have trouble updating an existing order. I tried a lot of different things but can't get it to work. And now suddenly the server is responding error 500 when listing orders. Something is broken again.

Anyway, here's the body of the PUT update request I tried:

JSON ```json { "@context" : "https://www.datafoodconsortium.org", "@graph" : [ { "@id" : "https://env-0105831.jcloud-ver-jpe.ik-server.com/api/dfc/Enterprises/test-hodmedod/Orders/1175203184947", "@type" : "dfc-b:Order", "dfc-b:date" : "", "dfc-b:hasOrderStatus" : "dfc-v:Held", "dfc-b:hasPart" : [ "https://env-0105831.jcloud-ver-jpe.ik-server.com/api/dfc/Enterprises/test-hodmedod/Orders/1175203184947/orderLines/117", "https://env-0105831.jcloud-ver-jpe.ik-server.com/api/dfc/Enterprises/test-hodmedod/Orders/1175203184947/orderLines/2" ], "dfc-b:orderNumber" : "" }, { "@id" : "https://env-0105831.jcloud-ver-jpe.ik-server.com/api/dfc/Enterprises/test-hodmedod/Orders/1175203184947/orderLines/117", "@type" : "dfc-b:OrderLine", "dfc-b:concerns" : "https://env-0105831.jcloud-ver-jpe.ik-server.com/api/dfc/Enterprises/test-hodmedod/Offers/44519466467635", "dfc-b:description" : "", "dfc-b:hasPrice" : { "@type" : "dfc-b:Price", "dfc-b:VATrate" : 0, "dfc-b:hasUnit" : "dfc-m:PoundSterling", "dfc-b:value" : "2.09" }, "dfc-b:quantity" : "3" }, { "@id" : "https://env-0105831.jcloud-ver-jpe.ik-server.com/api/dfc/Enterprises/test-hodmedod/Orders/1175203184947/orderLines/2", "@type" : "dfc-b:OrderLine", "dfc-b:concerns" : "https://env-0105831.jcloud-ver-jpe.ik-server.com/api/dfc/Enterprises/test-hodmedod/SuppliedProducts/44519466467635/Offer", "dfc-b:description" : "", "dfc-b:quantity" : 3 }, { "@id" : "https://env-0105831.jcloud-ver-jpe.ik-server.com/api/dfc/Enterprises/test-hodmedod/Offers/44519466467635", "@type" : "dfc-b:Offer", "dfc-b:offeredItem" : "https://env-0105831.jcloud-ver-jpe.ik-server.com/api/dfc/Enterprises/test-hodmedod/SuppliedProducts/44519466467635", "dfc-b:stockLimitation" : 0 }, { "@id" : "https://env-0105831.jcloud-ver-jpe.ik-server.com/api/dfc/Enterprises/test-hodmedod/SuppliedProducts/44519466467635/Offer", "@type" : "dfc-b:Offer", "dfc-b:hasPrice" : { "@type" : "dfc-b:Price", "dfc-b:VATrate" : "0", "dfc-b:hasUnit" : "dfc-m:Euro", "dfc-b:value" : "2.09" }, "dfc-b:offeredItem" : "https://env-0105831.jcloud-ver-jpe.ik-server.com/api/dfc/Enterprises/test-hodmedod/SuppliedProducts/44519466467635", "dfc-b:stockLimitation" : 0 }, { "@id" : "https://env-0105831.jcloud-ver-jpe.ik-server.com/api/dfc/Enterprises/test-hodmedod/SuppliedProducts/44519466467635", "@type" : "dfc-b:SuppliedProduct", "dfc-b:alcoholPercentage" : 0, "dfc-b:description" : "", "dfc-b:lifetime" : "", "dfc-b:name" : "", "dfc-b:totalTheoreticalStock" : 0, "dfc-b:usageOrStorageCondition" : "" }, { "@id" : "https://env-0105831.jcloud-ver-jpe.ik-server.com/api/dfc/Enterprises/test-hodmedod/SuppliedProducts/44519466467635", "@type" : "dfc-b:SuppliedProduct", "dfc-b:alcoholPercentage" : 0, "dfc-b:description" : "\n\n\n\n\n\n
They're back!
\n

Think baked beans are British? They are now! We use only British-grown fava beans - Britain's original bean, grown here since the Iron Age. Our Baked British Beans are deliciously different, with large meaty fava beans in a tasty tomato sauce.

\n

What are fava beans? Find out here...

\n

Complete Product Details

Our Baked British Beans are cooked and ready to eat, hot or cold. They're good served on toast but also delicious added to stews, curries or casseroles. Or even in a pie.

\n
Cooking instructions
\n

Cooking on the Hob
Empty contents into saucepan. Heat gently for 4-5 minutes while stirring. For best flavour do not boil or overcook. Do not reheat.

\n

Microwave Cooking
Empty contents into a non-metallic bowl and cover. Heat for 2 to 3 minutes, stirring halfway. Check the food is hot, stir well and serve. Do not reheat.

\n
To Store
\n

Store in a cool, dry place. Once opened, transfer contents to a non-metallic container, cover refrigerate and use with 2 days.

\n
Ingredients
\n

Fava Beans (Broad Beans) (42%), Water, Tomato Puree, Sugar, Modified Maize Starch, Salt, Herbs & Spices, Concentrated Lemon Juice

\n
Allergy information
\n

No Allergens

\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
Typical valuesPer 100g
Energy292kJ (69kcal)
Fat0.4g
of which saturates0.1g
Carbohydrate10.1g
of which sugars4.6g
Fibre5g
Protein4g
Salt0.6g
More
\n

Delicious, nutritious and good for the soil, fava beans are a variety of broad bean, Vicia faba, left to ripen and dry before harvest. They’re also known as field beans, horse beans, Windsor beans or ful.

\n

Suitable for vegans and vegetarians

\n", "dfc-b:hasQuantity" : { "@type" : "dfc-b:QuantitativeValue", "dfc-b:hasUnit" : "dfc-m:Kilogram", "dfc-b:value" : "0.4" }, "dfc-b:image" : "https://cdn.shopify.com/s/files/1/0731/8483/7939/products/Pack-Can-Baked-Beans-1800x6_983x656_513758e6-2616-4687-a8b2-ba6dde864923.jpg?v=1677760778", "dfc-b:lifetime" : "", "dfc-b:name" : "Baked British Beans - Retail can, 400g (can)", "dfc-b:referencedBy" : "https://env-0105831.jcloud-ver-jpe.ik-server.com/api/dfc/Enterprises/test-hodmedod/SuppliedProducts/44519466467635/CatalogItem", "dfc-b:totalTheoreticalStock" : 0, "dfc-b:usageOrStorageCondition" : "" } ] } ``` Can you spot what's wrong?
ajluker commented 2 days ago

Hi Maikel,

The system is currently expecting each line item to correspond to a different product. It looks like it's not gracefully handling the situation where multiple line items are mapped to the same product, which is then causing a consistency error in the database. This should have been handled better and at least validated at the point it entered the system, but here we are.

This had a knock on effect to the orders endpoint, which has an edge case where it barfs when it encounters an fdc order with a line that isn't in the database, which was causing the 500 you've seen. We could probably just skip over an order when see this, or ignore the line item. But both of those options could have harmful consequences to business applications. Hmm.

For now, I've removed the FDC tag from the offending draft order so things work again.

Alex

On Thu, Sep 5, 2024 at 6:43 AM Maikel @.***> wrote:

@dupreesi https://github.com/dupreesi, I have trouble updating an existing order. I tried a lot of different things but can't get it to work. And now suddenly the server is responding error 500 when listing orders. Something is broken again.

Anyway, here's the body of the PUT update request I tried:

{ @." : "https://www.datafoodconsortium.org", @." : [ { @." : "https://env-0105831.jcloud-ver-jpe.ik-server.com/api/dfc/Enterprises/test-hodmedod/Orders/1175203184947", @." : "dfc-b:Order", "dfc-b:date" : "", "dfc-b:hasOrderStatus" : "dfc-v:Held", "dfc-b:hasPart" : [ "https://env-0105831.jcloud-ver-jpe.ik-server.com/api/dfc/Enterprises/test-hodmedod/Orders/1175203184947/orderLines/117", "https://env-0105831.jcloud-ver-jpe.ik-server.com/api/dfc/Enterprises/test-hodmedod/Orders/1175203184947/orderLines/2" ], "dfc-b:orderNumber" : "" }, { @." : "https://env-0105831.jcloud-ver-jpe.ik-server.com/api/dfc/Enterprises/test-hodmedod/Orders/1175203184947/orderLines/117", @." : "dfc-b:OrderLine", "dfc-b:concerns" : "https://env-0105831.jcloud-ver-jpe.ik-server.com/api/dfc/Enterprises/test-hodmedod/Offers/44519466467635", "dfc-b:description" : "", "dfc-b:hasPrice" : { @." : "dfc-b:Price", "dfc-b:VATrate" : 0, "dfc-b:hasUnit" : "dfc-m:PoundSterling", "dfc-b:value" : "2.09" }, "dfc-b:quantity" : "3" }, { @." : "https://env-0105831.jcloud-ver-jpe.ik-server.com/api/dfc/Enterprises/test-hodmedod/Orders/1175203184947/orderLines/2", @." : "dfc-b:OrderLine", "dfc-b:concerns" : "https://env-0105831.jcloud-ver-jpe.ik-server.com/api/dfc/Enterprises/test-hodmedod/SuppliedProducts/44519466467635/Offer", "dfc-b:description" : "", "dfc-b:quantity" : 3 }, { @." : "https://env-0105831.jcloud-ver-jpe.ik-server.com/api/dfc/Enterprises/test-hodmedod/Offers/44519466467635", @." : "dfc-b:Offer", "dfc-b:offeredItem" : "https://env-0105831.jcloud-ver-jpe.ik-server.com/api/dfc/Enterprises/test-hodmedod/SuppliedProducts/44519466467635", "dfc-b:stockLimitation" : 0 }, { @." : "https://env-0105831.jcloud-ver-jpe.ik-server.com/api/dfc/Enterprises/test-hodmedod/SuppliedProducts/44519466467635/Offer", @." : "dfc-b:Offer", "dfc-b:hasPrice" : { @." : "dfc-b:Price", "dfc-b:VATrate" : "0", "dfc-b:hasUnit" : "dfc-m:Euro", "dfc-b:value" : "2.09" }, "dfc-b:offeredItem" : "https://env-0105831.jcloud-ver-jpe.ik-server.com/api/dfc/Enterprises/test-hodmedod/SuppliedProducts/44519466467635", "dfc-b:stockLimitation" : 0 }, { @." : "https://env-0105831.jcloud-ver-jpe.ik-server.com/api/dfc/Enterprises/test-hodmedod/SuppliedProducts/44519466467635", @." : "dfc-b:SuppliedProduct", "dfc-b:alcoholPercentage" : 0, "dfc-b:description" : "", "dfc-b:lifetime" : "", "dfc-b:name" : "", "dfc-b:totalTheoreticalStock" : 0, "dfc-b:usageOrStorageCondition" : "" }, { @." : "https://env-0105831.jcloud-ver-jpe.ik-server.com/api/dfc/Enterprises/test-hodmedod/SuppliedProducts/44519466467635", @." : "dfc-b:SuppliedProduct", "dfc-b:alcoholPercentage" : 0, "dfc-b:description" : "<table width=\"100%\">\n\n<tr style=\"border: 0px;\">\n<td bgcolor=\"#d6fbed\" style=\"color: #000000; border: 0px;\">They're back!\n\n\n\n

Think baked beans are British? They are now! We use only British-grown fava beans - Britain's original bean, grown here since the Iron Age. Our Baked British Beans are deliciously different, with large meaty fava beans in a tasty tomato sauce.

\n

<a title=\"What are fava beans? Aren't they just broad beans?\" href=\"/blogs/news/what-are-fava-beans-are-they-just-broad-beans\" data-mce-fragment=\"1\" data-mce-href=\"/blogs/news/what-are-fava-beans-are-they-just-broad-beans\">What are fava beans? Find out here...

\n

Complete Product Details

Our Baked British Beans are cooked and ready to eat, hot or cold. They're good served on toast but also delicious added to stews, curries or casseroles. Or even in a pie.

\n<h5 class=\"product-detail-title\">Cooking instructions\n

Cooking on the Hob
Empty contents into saucepan. Heat gently for 4-5 minutes while stirring. For best flavour do not boil or overcook. Do not reheat.

\n

Microwave Cooking
Empty contents into a non-metallic bowl and cover. Heat for 2 to 3 minutes, stirring halfway. Check the food is hot, stir well and serve. Do not reheat.

\n<h5 class=\"product-detail-title\">To Store\n

Store in a cool, dry place. Once opened, transfer contents to a non-metallic container, cover refrigerate and use with 2 days.

\n<h5 class=\"product-detail-title\">Ingredients\n

Fava Beans (Broad Beans) (42%), Water, Tomato Puree, Sugar, Modified Maize Starch, Salt, Herbs & Spices, Concentrated Lemon Juice

\n<h5 class=\"product-detail-title\">Allergy information\n

No Allergens

\n<table width=\"100%\">\n\n\nTypical values\nPer 100g\n\n\nEnergy\n292kJ (69kcal)\n\n\nFat\n0.4g\n\n\nof which saturates\n0.1g\n\n\nCarbohydrate\n10.1g\n\n\nof which sugars\n4.6g\n\n\nFibre\n5g\n\n\nProtein\n4g\n\n\nSalt\n0.6g\n\n\n<h5 class=\"product-detail-title\">More\n

Delicious, nutritious and good for the soil, fava beans are a variety of broad bean, Vicia faba, left to ripen and dry before harvest. They’re also known as field beans, horse beans, Windsor beans or ful.

\n

Suitable for vegans and vegetarians

\n", "dfc-b:hasQuantity" : { @.***" : "dfc-b:QuantitativeValue", "dfc-b:hasUnit" : "dfc-m:Kilogram", "dfc-b:value" : "0.4" }, "dfc-b:image" : "https://cdn.shopify.com/s/files/1/0731/8483/7939/products/Pack-Can-Baked-Beans-1800x6_983x656_513758e6-2616-4687-a8b2-ba6dde864923.jpg?v=1677760778", "dfc-b:lifetime" : "", "dfc-b:name" : "Baked British Beans - Retail can, 400g (can)", "dfc-b:referencedBy" : "https://env-0105831.jcloud-ver-jpe.ik-server.com/api/dfc/Enterprises/test-hodmedod/SuppliedProducts/44519466467635/CatalogItem", "dfc-b:totalTheoreticalStock" : 0, "dfc-b:usageOrStorageCondition" : "" } ] }

Can you spot what's wrong?

— Reply to this email directly, view it on GitHub https://github.com/openfoodfoundation/openfoodnetwork/issues/12178#issuecomment-2330648376, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAGOKLP7IK6M2S4MKW2Q26DZU7VQZAVCNFSM6AAAAABDQ3NTO2VHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDGMZQGY2DQMZXGY . You are receiving this because you were mentioned.Message ID: @.***>

mkllnk commented 2 days ago

Thank you for explaining that. My code didn't see that the existing line item was for the same product. And the reason is that I was comparing by Offer. But your API uses different ids for offers in different endpoints.

SuppliedProducts contains:

https://env-0105831.jcloud-ver-jpe.ik-server.com/api/dfc/Enterprises/test-hodmedod/SuppliedProducts/44519466467635/Offer

Orders contains:

https://env-0105831.jcloud-ver-jpe.ik-server.com/api/dfc/Enterprises/test-hodmedod/Offers/44519466467635

So when placing a new order, I use the id from the supplied products, of course. But then when I retrieve the order again, I get a different id. I'll try to solve this by matching by product instead. But be aware that this means that we are now limited to single a single offer per product. Maybe no problem in your scenario but we are trying to implement code that will work with other DFC APIs as well.

@RaggedStaff, this should probably go in your list for the next iteration.

mkllnk commented 2 days ago

I successfully added quantity to an existing order! :tada:

mkllnk commented 2 days ago

@ajluker, does your API support deleting orders? I sent a delete request to the order id but got a 400 error back.

I just thought it would be nice to clean up my test data automatically in my tests.

mkllnk commented 2 days ago

:heavy_check_mark: Complete an open order.

So the most important API interactions are working.

Question: How do you distinguish between orders from different platforms? The API doesn't expose anything to determine if I placed that order or if someone else did it. The client field is empty.