Calculate and Update Totals On Change of a Subrecord Select Field

🎀 Effectively manage totals on change of a subrecord field.

1. Overview

On change of a subrecord select field, this Interaction is designed to calculate subrecord totals and update totals.

2. Example

In the below example, the function ensures that whenever select fields change or an item is selected, the subrecord's totals are updated, ultimately impacting the parent record's total values. It targets the "recurring-services" subrecord and calculates totals based on the selected item's rate, quantity, and tax rate.

async function handler(C) {
    const index = C.getEventPayload().index;
    const value = C.getSubValueBasedOnIndex("recurring-services", index);

    const itemId = value.item[0];
    const frequencyId = value.frequency[0];
    const quantity = value.quantity;
    const total = C.getValue("recurring-total");
    function getParentUpdates({ net, tax, total }) {
        const lineValues = C.state.subValues["recurring-services"]; // Get all out subrecord lines
        let monthlyRecurringTotal = 0;
        _.forEach(lineValues, function (line) {
            // for loop to go through each line
            let frequency = line.frequency;
            let total = line.total;
            if (frequency[0] == "685744") { // monthly
                monthlyRecurringTotal += total;
            } else if (frequency[0] == "685743") { // fortnightly
                monthlyRecurringTotal += (total * 26) / 12;
            } else if (frequency[0] == "685742") { // weekly
                monthlyRecurringTotal += (total * 52) / 12;
            } else if (frequency[0] == "685747") { // quarterly
                monthlyRecurringTotal += total / 3;
            } else if (frequency[0] == "685746") { // bi annually
                monthlyRecurringTotal += total / 6;
            } else if (frequency[0] == "685745") { // annually
                monthlyRecurringTotal += total / 12;
            }
            // console.log("frequency", frequency);
            // console.log("monthlyRecurringTotal", monthlyRecurringTotal);
        });

        return C.mergeAll(C.setValue("recurring-total", monthlyRecurringTotal));
    }

    if (itemId !== undefined && itemId !== null) {
        const entry = await C.api.getEntry({
            id: [itemId],
            responseType: "iov",
            recordId: 463908,
        });
        // console.log("items entry: ", entry);
        let effectiveTax = 0;
        let taxRateSelectValue = [];
        try {
            taxRateSelectValue = JSON.parse(entry["tax-rate"]);
            const taxRateEntryId = taxRateSelectValue[0];
            if (taxRateEntryId) {
                const taxRateEntry = await C.api.getEntry({
                    id: [taxRateEntryId],
                    responseType: "iov",
                    recordId: 34148,
                });
                // console.log("tax rate entry id:", taxRateEntry);
                effectiveTax = +taxRateEntry["effective-tax-rate"];
            }
        } catch {}

        const net = (quantity || 0) * +(entry.rate || 0);
        const tax = (effectiveTax / 100) * net;
        const total = net + tax;
        const updatedLineValues = C.updateSubValueBasedOnIndex(
            "recurring-services",
            index,
            {
                description: entry.description,
                rate: +entry.rate,
                account: JSON.parse(entry["xero-account"]),
                "tax-rate": taxRateSelectValue,
                net,
                tax,
                total,
            }
        );

        // merged return value
        const returnValue = C.mergeAll(
            updatedLineValues,
            getParentUpdates({ net, tax, total })
        );

        // console.log("return value:", returnValue);
        return returnValue;
    }
    const updatedValues = C.updateSubValueBasedOnIndex(
        "recurring-services",
        index,
        {
            description: "",
            rate: null,
            account: [],
            frequency: [],
            "price-level": [],
            "tax-rate": [],
            quantity: 1,
            net: null,
        }
    );

    const returnValue = C.mergeAll(
        updatedValues,
        getParentUpdates({ net: 0, tax: 0, total: 0 })
    );
    return returnValue;
}

📌 Need Help?

If you require assistance or encounter any issues, please don't hesitate to contact us for further support.