Skip to content

Commit

Permalink
feat: better order details fields parsing and validation
Browse files Browse the repository at this point in the history
  • Loading branch information
paulobernardoaf committed Oct 9, 2024
1 parent 8c77655 commit bac165d
Show file tree
Hide file tree
Showing 3 changed files with 217 additions and 34 deletions.
119 changes: 90 additions & 29 deletions flows/actions/send_wpp_message.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package actions
import (
"encoding/json"
"strconv"
"strings"

"github.com/nyaruka/gocommon/urns"
"github.com/nyaruka/goflow/assets"
Expand Down Expand Up @@ -163,34 +164,81 @@ func (a *SendWppMsgAction) Execute(run flows.FlowRun, step flows.Step, logModifi
return nil
}

if len(tempOrderItems) == 0 {
logEvent(events.NewErrorf("order items evaluated to empty array"))
return nil
}

orderItems := []flows.MessageOrderItem{}
for _, item := range tempOrderItems {
convertedQuantity, err := strconv.ParseFloat(item["quantity"].(string), 64)
if err != nil {
logEvent(events.NewErrorf("error converting order item quantity %s to int: %v", item["quantity"], err))
if item["quantity"] == nil {
logEvent(events.NewErrorf("order item quantity is nil"))
return nil
}
convertedQuantity, isFloat := item["quantity"].(float64)
if !isFloat {
logEvent(events.NewErrorf("error reading order item quantity: %v", item["quantity"]))
return nil
}

convertedAmount, err := strconv.ParseFloat(item["amount"].(string), 64)
if err != nil {
logEvent(events.NewErrorf("error converting order item amount %s to int: %v", item["amount"], err))
if item["amount"] == nil {
logEvent(events.NewErrorf("order item amount is required"))
return nil
}
var convertedAmount float64
var convertedOffset float64
itemAmount, ok := item["amount"].(map[string]interface{})
if !ok {
logEvent(events.NewErrorf("error reading order item amount: %v", item["amount"]))
return nil
}
convertedAmount, isFloat = itemAmount["value"].(float64)
if !isFloat {
logEvent(events.NewErrorf("error reading order item amount: %v", itemAmount["value"]))
return nil
}

convertedOffset, isFloat = itemAmount["offset"].(float64)
if !isFloat {
logEvent(events.NewErrorf("error reading order item amount offset: %v", itemAmount["offset"]))
return nil
}

orderItem := flows.MessageOrderItem{
Name: item["name"].(string),
Quantity: int(convertedQuantity),
Amount: int(convertedAmount),
RetailerID: item["retailer_id"].(string),
Name: item["name"].(string),
Quantity: int(convertedQuantity),
Amount: flows.MessageOrderAmountWithOffset{
Value: int(convertedAmount),
Offset: int(convertedOffset),
},
}

if item["sale_amount"] == nil {
convertedSaleAmount, err := strconv.ParseFloat(item["sale_amount"].(string), 64)
if err != nil {
logEvent(events.NewErrorf("error converting order item sale amount %s to int: %v", item["sale_amount"], err))
if item["sale_amount"] != nil {
itemSaleAmount, ok := item["sale_amount"].(map[string]interface{})
if !ok {
logEvent(events.NewErrorf("error reading order item sale amount: %v", item["sale_amount"]))
return nil
}
convertedSaleAmount, isFloat := itemSaleAmount["value"].(float64)
if !isFloat {
logEvent(events.NewErrorf("error converting order item sale amount %s: %v", itemSaleAmount["value"], err))
return nil
}

orderItem.SaleAmount = int(convertedSaleAmount)
convertedSaleAmountOffset, isFloat := itemSaleAmount["offset"].(float64)
if !isFloat {
logEvent(events.NewErrorf("error converting order item sale amount offset %s: %v", itemSaleAmount["offset"], err))
return nil
}

if convertedSaleAmount > 0 {
orderItem.SaleAmount = &flows.MessageOrderAmountWithOffset{
Value: int(convertedSaleAmount),
Offset: int(convertedSaleAmountOffset),
}
}

}

orderItems = append(orderItems, orderItem)
Expand All @@ -214,30 +262,43 @@ func (a *SendWppMsgAction) Execute(run flows.FlowRun, step flows.Step, logModifi
evaluatedOrderPixMerchantName, _ := run.EvaluateTemplate(a.OrderDetails.PaymentSettings.PixConfig.MerchantName)
evaluatedOrderPixCode, _ := run.EvaluateTemplate(a.OrderDetails.PaymentSettings.PixConfig.Code)

convertedOrderTax, err := strconv.ParseFloat(evaluatedOrderTax, 64)
if err != nil {
logEvent(events.NewErrorf("error converting order tax %s to int: %v", evaluatedOrderTax, err))
return nil
var convertedOrderTax float64
var convertedOrderShipping float64
var convertedOrderDiscount float64
err = nil
if evaluatedOrderTax != "" {
taxInRealFloatRepresentation := strings.Replace(evaluatedOrderTax, ",", ".", -1)
convertedOrderTax, err = strconv.ParseFloat(taxInRealFloatRepresentation, 64)
if err != nil {
logEvent(events.NewErrorf("error converting order tax %s to int: %v", evaluatedOrderTax, err))
return nil
}
}

convertedOrderShipping, err := strconv.ParseFloat(evaluatedOrderShipping, 64)
if err != nil {
logEvent(events.NewErrorf("error converting order shipping %s to int: %v", evaluatedOrderShipping, err))
return nil
if evaluatedOrderShipping != "" {
shippingInRealFloatRepresentation := strings.Replace(evaluatedOrderShipping, ",", ".", -1)
convertedOrderShipping, err = strconv.ParseFloat(shippingInRealFloatRepresentation, 64)
if err != nil {
logEvent(events.NewErrorf("error converting order shipping %s to int: %v", evaluatedOrderShipping, err))
return nil
}
}

convertedOrderDiscount, err := strconv.ParseFloat(evaluatedOrderDiscount, 64)
if err != nil {
logEvent(events.NewErrorf("error converting order discount %s to int: %v", evaluatedOrderDiscount, err))
return nil
if evaluatedOrderDiscount != "" {
discountInRealFloatRepresentation := strings.Replace(evaluatedOrderDiscount, ",", ".", -1)
convertedOrderDiscount, err = strconv.ParseFloat(discountInRealFloatRepresentation, 64)
if err != nil {
logEvent(events.NewErrorf("error converting order discount %s to int: %v", evaluatedOrderDiscount, err))
return nil
}
}

subTotalValue := 0
for _, item := range orderItems {
if item.SaleAmount != 0 {
subTotalValue += item.SaleAmount * item.Quantity
if item.SaleAmount != nil && item.SaleAmount.Value > 0 {
subTotalValue += item.SaleAmount.Value * item.Quantity
} else {
subTotalValue += item.Amount * item.Quantity
subTotalValue += item.Amount.Value * item.Quantity
}
}

Expand Down
116 changes: 116 additions & 0 deletions flows/actions/testdata/send_whatsapp_msg.json
Original file line number Diff line number Diff line change
Expand Up @@ -186,5 +186,121 @@
"waiting_exits": [],
"parent_refs": []
}
},
{
"description": "WhatsApp Order Details message",
"action": {
"type": "send_whatsapp_msg",
"uuid": "c67969d6-f400-4b5e-bb7c-e45115cd3aa4",
"header_type": "media",
"attachment": "image/jpeg:https://foo.bar/image.jpg",
"footer": "footer",
"interaction_type": "order_details",
"text": "Hi there!",
"button_text": "Button text",
"order_details": {
"reference_id": "123456",
"item_list": "[{\"retailer_id\":\"123\",\"name\":\"item 1\",\"quantity\":1,\"amount\":{\"value\":2000,\"offset\":100},\"sale_amount\":{\"value\":1000,\"offset\":100}}]",
"tax": {
"value": "2,99",
"description": "tax"
},
"shipping": {
"value": "9.99",
"description": "shipping"
},
"discount": {
"value": "5.99",
"description": "discount"
},
"payment_settings": {
"type": "digital-goods",
"payment_link": "https://www.foo.bar",
"pix_config": {
"key": "key",
"key_type": "key type",
"merchant_name": "merchant name",
"code": "code"
}
}
}
},
"localization": {},
"events": [
{
"type": "msg_wpp_created",
"created_on": "2018-10-18T14:20:30.000123456Z",
"step_uuid": "59d74b86-3e2f-4a93-aece-b05d2fdcde0c",
"msg": {
"uuid": "9688d21d-95aa-4bed-afc7-f31b35731a3d",
"urn": "tel:+12065551212?channel=57f1078f-88aa-46f4-a59a-948a5739c03d&id=123",
"channel": {
"uuid": "57f1078f-88aa-46f4-a59a-948a5739c03d",
"name": "My Android Phone"
},
"text": "Hi there!",
"footer": "footer",
"header_type": "media",
"attachments": [
"image/jpeg:https://foo.bar/image.jpg"
],
"interaction_type": "order_details",
"cta_message": {},
"list_message": {},
"flow_message": {},
"order_details_message": {
"order": {
"discount": {
"description": "discount",
"value": 599
},
"items": [
{
"amount": {
"offset": 100,
"value": 2000
},
"name": "item 1",
"quantity": 1,
"retailer_id": "123",
"sale_amount": {
"offset": 100,
"value": 1000
}
}
],
"shipping": {
"description": "shipping",
"value": 999
},
"subtotal": 1000,
"tax": {
"description": "tax",
"value": 299
}
},
"payment_settings": {
"payment_link": "https://www.foo.bar",
"pix_config": {
"code": "code",
"key": "key",
"key_type": "key type",
"merchant_name": "merchant name"
},
"type": "digital-goods"
},
"reference_id": "123456",
"total_amount": 1699
}
}
}
],
"inspection": {
"dependencies": [],
"issues": [],
"results": [],
"waiting_exits": [],
"parent_refs": []
}
}
]
16 changes: 11 additions & 5 deletions flows/msg_wpp.go
Original file line number Diff line number Diff line change
Expand Up @@ -102,12 +102,13 @@ type MessageOrder struct {
}

type MessageOrderItem struct {
RetailerID string `json:"retailer_id,omitempty"`
Name string `json:"name,omitempty"`
Amount int `json:"amount,omitempty"`
Quantity int `json:"quantity,omitempty"`
SaleAmount int `json:"sale_amount,omitempty"`
RetailerID string `json:"retailer_id,omitempty"`
Name string `json:"name,omitempty"`
Quantity int `json:"quantity,omitempty"`
Amount MessageOrderAmountWithOffset `json:"amount,omitempty"`
SaleAmount *MessageOrderAmountWithOffset `json:"sale_amount,omitempty"`
}

type MessageOrderAmountWithDescription struct {
Value int `json:"value,omitempty"`
Description string `json:"description,omitempty"`
Expand All @@ -119,6 +120,11 @@ type MessageOrderDiscount struct {
ProgramName string `json:"program_name,omitempty"`
}

type MessageOrderAmountWithOffset struct {
Value int `json:"value"`
Offset int `json:"offset"`
}

func NewMsgWppOut(urn urns.URN, channel *assets.ChannelReference, interactionType, headerType, headerText, text, footer string, ctaMessage CTAMessage, listMessage ListMessage, flowMessage FlowMessage, orderDetailsMessage OrderDetailsMessage, attachments []utils.Attachment, replyButtons []string, topic MsgTopic) *MsgWppOut {
return &MsgWppOut{
BaseMsg: BaseMsg{
Expand Down

0 comments on commit bac165d

Please sign in to comment.