diff --git a/flows/actions/base_test.go b/flows/actions/base_test.go index 939bd8d45..b29e50dbc 100644 --- a/flows/actions/base_test.go +++ b/flows/actions/base_test.go @@ -32,6 +32,7 @@ import ( "github.com/nyaruka/goflow/test" "github.com/nyaruka/goflow/utils" "github.com/nyaruka/goflow/utils/smtpx" + "github.com/shopspring/decimal" "github.com/pkg/errors" "github.com/stretchr/testify/assert" @@ -217,6 +218,25 @@ func testActionType(t *testing.T, assetsJSON json.RawMessage, typeName string) { "audio/mp3:http://s3.amazon.com/bucket/test.mp3", }, ) + itemPrice, _ := decimal.NewFromString("20.99") + msg.SetOrder(&flows.Order{ + CatalogID: "CATALOG_ID", + Text: "order msg text", + ProductItems: []flows.ProductItem{ + { + Currency: "BRL", + ItemPrice: itemPrice, + ProductRetailerID: "RETAILER_ID_1", + Quantity: 1, + }, + { + Currency: "BRL", + ItemPrice: itemPrice, + ProductRetailerID: "RETAILER_ID_2", + Quantity: 1, + }, + }, + }) trigger = triggers.NewBuilder(env, flow.Reference(), contact).Msg(msg).Build() ignoreEventCount = 1 // need to ignore the msg_received event this trigger creates } diff --git a/flows/actions/send_wpp_message.go b/flows/actions/send_wpp_message.go index e9bd41f3a..e298bcaa7 100644 --- a/flows/actions/send_wpp_message.go +++ b/flows/actions/send_wpp_message.go @@ -173,14 +173,8 @@ func (a *SendWppMsgAction) Execute(run flows.FlowRun, step flows.Step, logModifi orderDetailsMessage := flows.OrderDetailsMessage{} if a.InteractionType == "order_details" { evaluatedReferenceID, _ := run.EvaluateTemplate(a.OrderDetails.ReferenceID) - evaluatedOrderItems, _ := run.EvaluateTemplate(a.OrderDetails.Items) - if evaluatedOrderItems == "" { - logEvent(events.NewErrorf("order items evaluated to empty string")) - return nil - } - - orderItems, err := parseOrderItems(a, run, evaluatedOrderItems, logEvent) + orderItems, err := parseOrderItems(a, run, a.OrderDetails.Items, logEvent) if err != nil { logEvent(events.NewErrorf("error parsing order items: %v", err)) return nil @@ -305,14 +299,26 @@ func (a *SendWppMsgAction) Execute(run flows.FlowRun, step flows.Step, logModifi return nil } -func parseOrderItems(a *SendWppMsgAction, run flows.FlowRun, evaluatedOrderItems string, logEvent flows.EventCallback) ([]flows.MessageOrderItem, error) { +func parseOrderItems(a *SendWppMsgAction, run flows.FlowRun, rawOrderItems string, logEvent flows.EventCallback) ([]flows.MessageOrderItem, error) { + evaluatedOrderItems, _ := run.EvaluateTemplate(rawOrderItems) + if evaluatedOrderItems == "" { + return nil, fmt.Errorf("order items evaluated to empty string") + } + tempOrderItems := []map[string]interface{}{} // try to parse it as an array of items err := json.Unmarshal([]byte(evaluatedOrderItems), &tempOrderItems) if err != nil { // try to parse it as an order-like structure + orderItemsXValue, _ := run.EvaluateTemplateValue(rawOrderItems) + + orderItemsJSON, err := orderItemsXValue.MarshalJSON() + if err != nil { + return nil, fmt.Errorf("error marshalling order items: %v", err) + } + order := flows.Order{} - err = json.Unmarshal([]byte(evaluatedOrderItems), &order) + err = json.Unmarshal(orderItemsJSON, &order) if err != nil { return nil, fmt.Errorf("error unmarshalling order items: %v", err) } @@ -443,6 +449,10 @@ func searchMetaForOrderItems(a *SendWppMsgAction, run flows.FlowRun, order flows } } + if len(orderItems) != len(order.ProductItems) { + logEvent(events.NewErrorf("not all provided order items were found in Meta, requested %d, found %d", len(order.ProductItems), len(orderItems))) + } + return orderItems, nil } diff --git a/flows/actions/testdata/send_whatsapp_msg.json b/flows/actions/testdata/send_whatsapp_msg.json index 05987f4b0..6ae7f385b 100644 --- a/flows/actions/testdata/send_whatsapp_msg.json +++ b/flows/actions/testdata/send_whatsapp_msg.json @@ -319,10 +319,10 @@ { "description": "WhatsApp Order Details message with order-like item list", "http_mocks": { - "http://127.0.0.1:49994/CATALOG_ID/products?access_token=system-user-token&fields=%5B%22category%22%2C%22name%22%2C%22retailer_id%22%2C%22availability%22%5D&filter=%7B%22or%22%3A%5B%7B%22and%22%3A%5B%7B%22retailer_id%22%3A%7B%22i_contains%22%3A%22123%22%7D%7D%5D%7D%5D%7D&summary=true": [ + "http://127.0.0.1:49994/CATALOG_ID/products?access_token=system-user-token&fields=%5B%22category%22%2C%22name%22%2C%22retailer_id%22%2C%22availability%22%5D&filter=%7B%22or%22%3A%5B%7B%22and%22%3A%5B%7B%22retailer_id%22%3A%7B%22i_contains%22%3A%22RETAILER_ID_1%22%7D%7D%5D%7D%2C%7B%22and%22%3A%5B%7B%22retailer_id%22%3A%7B%22i_contains%22%3A%22RETAILER_ID_2%22%7D%7D%5D%7D%5D%7D&summary=true": [ { "status": 200, - "body": "{\"data\":[{\"retailer_id\":\"123\",\"name\":\"item 1\",\"id\":\"456\"}],\"summary\":{\"total_count\":1}}" + "body": "{\"data\":[{\"retailer_id\":\"RETAILER_ID_1\",\"name\":\"item 1\",\"id\":\"456\"}],\"summary\":{\"total_count\":1}}" } ] }, @@ -337,7 +337,7 @@ "button_text": "Button text", "order_details": { "reference_id": "123456", - "item_list": "{\"catalog_id\":\"CATALOG_ID\",\"text\":\"msg text\",\"product_items\":[{\"product_retailer_id\":\"123\",\"quantity\":1,\"item_price\":20.99,\"currency\":\"BRL\"}]}", + "item_list": "@input.order", "tax": { "value": "2,99", "description": "tax" @@ -370,17 +370,23 @@ "step_uuid": "59d74b86-3e2f-4a93-aece-b05d2fdcde0c", "http_logs": [ { - "url": "http://127.0.0.1:49994/CATALOG_ID/products?access_token=****************&fields=%5B%22category%22%2C%22name%22%2C%22retailer_id%22%2C%22availability%22%5D&filter=%7B%22or%22%3A%5B%7B%22and%22%3A%5B%7B%22retailer_id%22%3A%7B%22i_contains%22%3A%22123%22%7D%7D%5D%7D%5D%7D&summary=true", + "url": "http://127.0.0.1:49994/CATALOG_ID/products?access_token=****************&fields=%5B%22category%22%2C%22name%22%2C%22retailer_id%22%2C%22availability%22%5D&filter=%7B%22or%22%3A%5B%7B%22and%22%3A%5B%7B%22retailer_id%22%3A%7B%22i_contains%22%3A%22RETAILER_ID_1%22%7D%7D%5D%7D%2C%7B%22and%22%3A%5B%7B%22retailer_id%22%3A%7B%22i_contains%22%3A%22RETAILER_ID_2%22%7D%7D%5D%7D%5D%7D&summary=true", "status_code": 200, "status": "success", - "request": "GET /CATALOG_ID/products?access_token=****************&fields=%5B%22category%22%2C%22name%22%2C%22retailer_id%22%2C%22availability%22%5D&filter=%7B%22or%22%3A%5B%7B%22and%22%3A%5B%7B%22retailer_id%22%3A%7B%22i_contains%22%3A%22123%22%7D%7D%5D%7D%5D%7D&summary=true HTTP/1.1\r\nHost: 127.0.0.1:49994\r\nUser-Agent: goflow-testing\r\nAccept-Encoding: gzip\r\n\r\n", - "response": "HTTP/1.0 200 OK\r\nContent-Length: 87\r\n\r\n{\"data\":[{\"retailer_id\":\"123\",\"name\":\"item 1\",\"id\":\"456\"}],\"summary\":{\"total_count\":1}}", + "request": "GET /CATALOG_ID/products?access_token=****************&fields=%5B%22category%22%2C%22name%22%2C%22retailer_id%22%2C%22availability%22%5D&filter=%7B%22or%22%3A%5B%7B%22and%22%3A%5B%7B%22retailer_id%22%3A%7B%22i_contains%22%3A%22RETAILER_ID_1%22%7D%7D%5D%7D%2C%7B%22and%22%3A%5B%7B%22retailer_id%22%3A%7B%22i_contains%22%3A%22RETAILER_ID_2%22%7D%7D%5D%7D%5D%7D&summary=true HTTP/1.1\r\nHost: 127.0.0.1:49994\r\nUser-Agent: goflow-testing\r\nAccept-Encoding: gzip\r\n\r\n", + "response": "HTTP/1.0 200 OK\r\nContent-Length: 97\r\n\r\n{\"data\":[{\"retailer_id\":\"RETAILER_ID_1\",\"name\":\"item 1\",\"id\":\"456\"}],\"summary\":{\"total_count\":1}}", "elapsed_ms": 0, "retries": 0, "created_on": "2018-10-18T14:20:30.000123456Z" } ] }, + { + "type": "error", + "created_on": "2018-10-18T14:20:30.000123456Z", + "step_uuid": "59d74b86-3e2f-4a93-aece-b05d2fdcde0c", + "text": "not all provided order items were found in Meta, requested 2, found 1" + }, { "type": "msg_wpp_created", "created_on": "2018-10-18T14:20:30.000123456Z", @@ -416,7 +422,7 @@ }, "name": "item 1", "quantity": 1, - "retailer_id": "123" + "retailer_id": "RETAILER_ID_1" } ], "shipping": {