How to use sendFulfillmentEmail?

Question:
How would one use the wixStoresBackend.sendFulfillmentEmail? Would it be deprecated come September? If so, would there be an updated method or will this function be removed completely?

Product:
Wix Editor, Velo

What are you trying to achieve:
I would like to automatically send an email to fulfillers when customers make payments. Specifically, I would like to learn how to use the sendFulfillmentEmail function properly in case I need to do it programmatically (e.g. maybe create a button on my site for “managers” to send additional emails as reminders to fulfillers).

What have you already tried:
I have already set the option in settings to send email on customer payments but it does not seem to work.

I have tried to call the wixStoresBackend.sendFulfillmentEmail function in an onOrderPaymentStatusUpdate hook but it doesn’t seem to work either (yes, I’ve checked the order ID and the fulfiller ID, console.logged and checked that it corresponded to the correct items and fulfillers).

Additional information:
I have been testing using manually created orders followed by manual payments (couldn’t figure out how to enable test payments via manual payments on my store, the guide on Wix doesn’t line up with the current Wix Stores implementation). If the problem is that manual payments do not trigger the “send email on payment” setting then I guess this might not be as big of a problem as I imagined.

It’s being deprecated not removed which means it will continue to exist and work. Anything being completely removed will have the notice about September 2024:

There’s also Triggered Email functionality to send any emails you want on demand: Introduction - Velo API Reference - Wix.com

As for the issue with calling sendFulfillmentEmail if you think it’s a bug in Wix then the best place to report this is customer care: Contact Wix

If you want help from forum members with taking a look at the code then please share it.

1 Like

Hi Anthony, thanks for the response. Currently, this is what I’m trying:

// item is from a CMS table containing info on custom carriers to be used within this code block. Each item is tied to a single lineItem from an order.
const order = await orders.getOrder(item.orderRef)

const trackingInfo = {
                    trackingNumber: item.title, //uuid4 used to generate tracking link
                    shippingProvider: item.carrier,
                    trackingLink: "https://www.mysite.com" + item["link-order-tracking-title"],
                }

// Using the old createFulfillment due to troubles with new createFulfillment
const lineItems = [{
                    index: order.lineItems.findIndex((lineItem) => lineItem._id == orderItem._id) + 1
                }]

await wixStoresBackend.createFulfillment(order._id, { lineItems, trackingInfo })
                    .then((createdItem) => {
                        console.log("Fulfillment created", createdItem)
                        item.fulfilled = true
                        return wixStoresBackend.sendFulfillmentEmail(order._id, orderItem.fulfillerId)
                            .catch((error) => {
                                console.log("Error sending fulfillment email")
                                notifyError("Error sending fulfillment email, please send manually", error, { orderNumber: order.number })
                            })
                    })
                    .catch((error) => {
                        console.log("Error creating fulfillment:", error)
                        notifyError("Error creating fulfillment", error, { orderNumber: order.number })
                    })

My notifyError function sends the following information to my Wix dashboard via notifications.notify:

function notifyError(message, error, otherInfoJSON) {
    const errorNotificationOptions = {
        title: "Fulfillment Automation Error",
        recipients: { role: "All_Contributors" },
    }
    notifications.notify(`${message} | ${error.message} | Additional Info: ${JSON.stringify(otherInfoJSON)}`, ["Mobile", "Dashboard"], errorNotificationOptions)
}

Which gives me this when I catch the sending fulfilment error:

Error sending fulfillment email, please send manually | undefined | Additional Info: {“orderNumber”:“10049”}

I hope anyone can grant me any insight as to why this might have happened or what mistakes I have made or where to look to troubleshoot. Meanwhile, I’ll try to experiment more before contacting customer care.

Try logging the full error object instead of just the error.message which is undefined. It might provide additional info about what is going wrong.

I let the error through by throwing the error from my catches but the error logs are not very informative either:

As per my code above (minus the .notifyError(…)), the code makes it all the way to the console.log(“Fulfillment created”, createdItem), then the “Hook error.” occurs.


When I checked the error code (WDE0078) on Velo, it just mentions that an error was thrown from a data hook…

Next, I removed the catches/trycatches but obtained similar results:

I’m not really sure how to troubleshoot this any further and the last time I contacted Wix Customer Care, I was advised to “contact the person who created this custom code”…

Some possibilities:

  • I don’t see in the code above where orderItem is defined. Could this be null?
  • From this it seems that the order is already fulfilled and the fulfillment emails might only be sent to unfulfilled orders? I’m not sure but the docs code examples seem to imply this.

Hi Anthony, thanks for the reply again.

I’ve had my code (pasted below) throw an error if orderItem could not be found so orderItem would not have been null. I’ve also doublechecked CMS and via console log that fulfillerId exists and I’m guessing that’s supposed to be my custom fulfiller since after createFulfillment the order does get fulfilled by whatever custom fulfiller I had assigned to the product.

But I had thought sendFulfillment would’ve worked regardless of fulfilment status, similar to how one could manually send the order to assigned fulfillers via Wix Dashboard in the Orders page.

Also, I tried another test order and saw that the “Order is already Fulfilled” was due to the function being called a second time, another thing I’ll have to fix I guess…:pensive:

I’ll just throw the entire code block here, did not think to include most of it as I didn’t want to clutter the original post with code that might not directly relate to the problem.

export async function tracking_beforeUpdate(item, context) {
    console.log("Running")
    // Check if item was previously not active
    if (item.active && !context.currentItem.active) {
        console.log(item)
        console.log(context)
        // try {
            const order = await orders.getOrder(item.orderRef)
            // Check if item has yet to be fulfilled before proceeding
            if (["NOT_FULFILLED", "PARTIALLY_FULFILLED"].includes(order.fulfillmentStatus)) {
                const trackingInfo = {
                    trackingNumber: item.title, //uuid4 used to generate tracking link
                    shippingProvider: item.carrier, //Name str of custom shipping provider
                    trackingLink: domain + item["link-order-tracking-title"],
                }
                console.log("Order Items:", order.lineItems)
                // References to Stores/Products get saved as [product-id]-[variant-id]
                const itemProductFragments = item.productRef.split("-")
                const itemProductId = itemProductFragments.splice(0, 5).join("-")
                const itemVariantId = itemProductFragments.join("-")
                console.log(itemProductId, itemVariantId)
                const orderItem = order.lineItems.find((lineItem) => lineItem.catalogReference.catalogItemId == itemProductId &&
                    (lineItem.catalogReference.options?.variantId || "00000000-0000-0000-0000-000000000000") == itemVariantId)
                if (!orderItem) {
                    // Kill automation if orderItem cannot be found
                    throw new Error("Error getting orderItem")
                }

                console.log("Item", item)
                const lineItems = [{
                    index: order.lineItems.findIndex((lineItem) => lineItem._id == orderItem._id) + 1
                }]
                // const currentLineItem = order.lineItems.find((lineItem) => {
                //         return (lineItem.catalogReference.catalogItemId == itemProductId &&
                //             (lineItem.catalogReference.options?.variantId || "00000000-0000-0000-0000-000000000000") == itemVariantId)
                //     })
                // if (!currentLineItem) {
                //     throw new Error("Error getting lineItem")
                // }
                // const lineItems = [{
                //     _id: currentLineItem._id,
                // }]
                console.log("Line Items:", lineItems)
                console.log(order)

                const elevatedCreateFulfillment = elevate(orderFulfillments.createFulfillment)

                // Automatically fulfilling orders with stock delivery option
                await wixStoresBackend.createFulfillment(order._id, { lineItems, trackingInfo })
                    .then((createdItem) => {
                        console.log("Fulfillment created", createdItem)
                        item.fulfilled = true // Removing this line doesn't change error
                        return wixStoresBackend.sendFulfillmentEmail(createdItem.order._id, orderItem.fulfillerId)
                            })
                    })
                    // .catch((error) => { // Hook error is normally caught by this block
                    //   console.log("Error creating fulfillment:", error)
                    //    notifyError("Error creating fulfillment", error, { orderNumber: order.number })
                    // })
                console.log(`Order #${order.number} automatically tracked!`)
            } else {
                // Otherwise, if order is already fulfilled
                console.log("Order is already: ", order.fulfillmentStatus)
                // Maybe other way to handle logic, like updateFulfillment?
            }
        // } catch (error) {
        //    console.log(error.message)
        //    notifyError("Error generating fulfillment according to tracker", error, { trackingNumber: item.title })
        //    throw error
        // }

    }
    return item
}

Sorry I meant orderItem.fulfillerId. Not really sure what else could be going wrong.