Budibase / budibase

Low code platform for building business apps and workflows in minutes. Supports PostgreSQL, MySQL, MariaDB, MSSQL, MongoDB, Rest API, Docker, K8s, and more 🚀
https://budibase.com
Other
22.47k stars 1.55k forks source link

Automation javascript number methods not returning number #9009

Closed eyduh closed 1 year ago

eyduh commented 1 year ago

Hosting docker compose

Describe the bug I'm trying to feed stripe checkout session info into a table to keep track of payments from a public form.

I've managed to setup the stripe checkout plugin to properly create a checkout session and return some data, using a transformer I've filtered out the stuff I don't need.

I have then tried to set up an automation that runs the query and tries to feed the info into a table for later processing.

The query stage in automation outputs something like:

{
  "response": [
    {
      "payment_status": "unpaid",
      "amount_total": 25000,
      "customer_email": "blargh@bla.bla",
      "client_reference_id": "CustomerID12345",
      "id": "cs_test_string",
      "url": "https://checkout.stripe.com/c/pay/cs_test_longstring"
    }
  ],
  "info": {},
  "success": true
}

which I would like to store in a table until the payment is either successful or a fail and they are redirected to a url webhook to update the table status.

I've setup the next step in the automation to parse the input like so:

const prettyResults = $("steps.2.response");

let pertinentData = Object.values(prettyResults);

return pertinentData[n];

Except for the number step which I've tried to numberify in various ways, like return +pertinentData[1]; , return Number(pertinentData[1]); or return helper.plus(pertinentData[1], 0);

but the Update Row step keeps telling me it's not a number.

image

I've also tried to use {{steps.2.response.data.0.column_header }} or {{steps.2.response.row.0.column_header }} to access the info in the response.

The tricky part about being a noob is that I have no idea if I'm not doing something right or if it's a bug. At least I've learnt some more js this weekend lol.

aptkingston commented 1 year ago

Hey @eyduh. You've got pretty far already so you're well beyond the noob stage!

Judging by your screenshots (which are very helpful by the way - thanks), the correct way to return the "amount total" field using JS would be:

return $("steps.2.response")[0].amount_total

Taking your JS as an example, I'll explain why it doesn't work!

// $("steps.2.response") is an array, so pretty results here is now also an array:
// [{ payment_status: "unpaid", ... }]
const prettyResults = $("steps.2.response");

// I think you're accidentally running Object.values against the full array, rather than the first entry
// in the array! I think this should be: Object.values(prettyResults[0]);
let pertinentData = Object.values(prettyResults);

// pertinentData is currently the full results array, because running Object.values on an array will
// return the full array and not change the values at all. So doing "pertinentData[1]" here will be
// undefined rather than a number. If you made my change above, then pertinentData[1] will be
// the number you expect.
return pertinentData[n];

So there's a quick explanation about why your JS doesn't work at the moment. Having said that - it's a much better idea to use a binding like $("steps.2.response")[0].amount_total, rather than turn the object into an array and use a numerical index. It's already a number, so you won't need to cast/parse it again.

eyduh commented 1 year ago

Amazing!

image

I'll make sure to try and learn new stuff in the week next time so I don't spend the weekend pulling hair until you get into work on Monday morning c;

I'm surprised I didn't lose the data type using the transformer I cooked up in the query stage, but I guess that's exactly what Object.fromEntries is for?

I used this based on a few different bits of code I found around the net, MDN and javascript.info

const stripe_data = data;

let filterKeys = [
    'payment_status', 
    'amount_total',
    'customer_email',
    'client_reference_id',
    'id',
    'url', 
    ];

let pertinent_data = [];
let results = [];

    for (let filterKey of filterKeys) {
        pertinent_data = Object.entries(stripe_data).filter(([k]) => k == filterKey)
        results = results.concat(pertinent_data); 
};

let prettyResults = Object.fromEntries(
results.map(entry => [entry[0], entry[1]])
)

return prettyResults

My question is why I didn't already lose the data type using this transformer, seeing as one can't do operations like map or push or concat on objects like on arrays, I turn it into an array here then mapping it back into an object?

I couldn't get the filter example like in the docs working but using this new info maybe I can prettify the transformer as well.

Thank you for this amazing tool, I'll keep misusing in semi-noobie ways and coming back here for feedback and knowledge <3