Issue with brackets in JavaScript strings

Yes, as in regional settings. I read that it is not possible to find out from JavaScript the characters used to separate thousands and decimals. Of course there are tricks to do it but I think that TN() is the right function.

Number() in JavaScript returns NaN (not a number) for “1,264.50”. It does work for “1264.50” though.

If only somebody could explain how to use TN() to pass a parameter to a script the problem would be solved.

Is it a bad idea to call Emre’s attention to this matter?

It seem TN() does not work in Call function. But you already call javascript so, why not use javascript to solve your problem.

Since you insist to use TN (which is you can write your own function in java anyway), I think you may have to store TN() in program setting and use {SETTING:x} in you call function.

EDIT: Maybe the reason is Emre think why would anyone use calculation function in call statement because there is much more option to do it in script.

Found this on stackexchange…

function parsePotentiallyGroupedFloat(stringValue) {
    stringValue = stringValue.trim();
    var result = stringValue.replace(/[^0-9]/g, '');
    if (/[,\.]\d{2}$/.test(stringValue)) {
        result = result.replace(/(\d{2})$/, '.$1');
    }
    return parseFloat(result);
}

That handles different locales and thousands separators (, or .) and assumes 2 decimal places.

I had to remove the trim function, but it otherwise works…

So your full script becomes:

function parseNum(stringValue) {
    //stringValue = stringValue.trim();
    var result = stringValue.replace(/[^0-9]/g, '');
    if (/[,\.]\d{2}$/.test(stringValue)) {
        result = result.replace(/(\d{2})$/, '.$1');
    }
    return parseFloat(result);
}
function getVerificationCode(number, key) {
    var num = parseNum(number);

    var r = "number:" + number + " of type " + typeof number + "\r\n";
        r+= "key:" + key + " of type " + typeof key + "\r\n";
        r+= "num:" + num + " of type " + typeof num + "\r\n";

    return r;
}


And in your Template, do:

{CALL:tests.getVerificationCode('{TICKET TOTAL}', "abc")}
2 Likes

Here is another option, using SQL …

function m(num) {
  var q = "SELECT TRY_PARSE( '" + num + "' AS NUMERIC(10,2) )";
  var r = sql.Query(q).First;
  return r;
}

You can also force a culture with:

SELECT TRY_PARSE( '123,45,6.70' AS NUMERIC(10,2) USING 'en-US')
SELECT TRY_PARSE( '123.45.6,70' AS NUMERIC(10,2) USING 'es-ES')
-- both return: 123456.70

.NET also has Parse() and TryParse() just like SQL, but I do not know how to expose those methods in SambaPOS script. I know Emre has exposed some .NET methods. Looking for a post on .NET exposure …

EDIT: here it is…

function n(num) {
  var s = host.type("System.Decimal");
  var r = s.Parse(num);
  return r;
}

If you need all decimal places, use JS toFixed() method, and your full script becomes:

function getVerificationCode(number, key) {
    var num = n(number).toFixed(2);

    var r = "number:" + number + " of type " + typeof number + "\r\n";
        r+= "key:" + key + " of type " + typeof key + "\r\n";
        r+= "num:" + num + " of type " + typeof num + "\r\n";

    return r;
}
function n(num) {
  var s = host.type("System.Decimal");
  var r = s.Parse(num);
  return r;
}

… that case, the routine returns 2 numbers after the decimal …

The equivalent of TN function in JScript code is Helper.ToNumber() function

https://forum.sambapos.com/t/error-while-merging-tickets-after-using-template-preview/4594/10

1 Like

And there you have it. The simplest solution, as always, provided by Emre !

function getVerificationCode(number, key) {
    //var num = n(number).toFixed(2);
    
	var num = Helper.ToNumber(number).toFixed(2);
	
    var r = "number:" + number + " of type " + typeof number + "\r\n";
        r+= "key:" + key + " of type " + typeof key + "\r\n";
        r+= "num:" + num + " of type " + typeof num + "\r\n";

    return r;
}

2 Likes

Thank you very much @emre. I still have problems with parameters from templates. I have tried many things without luck. I really do not understand what is going on.

In my Printer Template I am calling:

Test: {CALL:tests.toNumber(‘{TICKET TOTAL}’)}

And this is what does and does not work:

function toNumber(data) {
	//works well: string|20.00
	//return typeof data + "|" + data; 
	
	//works well: 1603.22
	//return Helper.ToNumber("1,603.22");
	//works well: 20
	//return Helper.ToNumber("20.00"); 
	
	//does not work
	//var x = data.trim();
	//return typeof x + "|" + x + "|"; 
	//does not work
	//return Helper.ToNumber(data);
	//does not work
	//var v = data.toString();
	//return Helper.ToNumber(v);
}

Does it make any sense? How came “data” is an string but ToNumber(data) does not work?

What I mean by “does not work” is that the template receives an empty string.

Function:

function toNum(data) {
  var r = Helper.ToNumber(data);
  return r;
}

Template:

<J10>TOTAL:|($[=F(TN('{TICKET TOTAL}')/{SETTING:XR_USDtoHNL})]) L{TICKET TOTAL}
<L00>{CALL:num.numToSpanish('{TICKET TOTAL}'.slice(0,-3))} Lempira
<L00>{CALL:tests.toNum('{TICKET TOTAL}')}

Preview:

This also works:

function toNum(data) {
  return Helper.ToNumber(data);
}

Maybe the name of your function (toNumber()) is causing conflict?

1 Like

I think trim() is not working. Leading/Trailing spaces is not issue for Helper.ToNumber(), it works without trim.

2 Likes

Correct. trim() is not an available function in the JScript (ES3) engine. If you test this in the script, you will see that trim throws an error. The trim function was introduced in ECMAScript 5.

My previous post mentions this:

Use the Test facility to check your scripts …

1 Like

I use wrong word. Actually, I did test it so, I should not use “I think trim() not working.”
I could save Q some times from testing it :wink:

Hi @QMcKay,

Thank you very much for your answer. The name function does not create any conflict. This is what I found out though:

This is the Printer Template that I am using:

[LAYOUT]
<T>TEST

{ENTITIES} 
[ENTITIES:Cliente]
<L00>Nombre: {ENTITY NAME} 
<L00>NIT/CI: {ENTITY DATA:NIT}

{ORDERS}
<J10>Total:|{TICKET TOTAL}
<L00>Test HelperToNumber: {CALL:tests.toNumber('{TICKET TOTAL}')}

If I remove these three lines:

[ENTITIES:Cliente]
<L00>Nombre: {ENTITY NAME} 
<L00>NIT/CI: {ENTITY DATA:NIT}

then tests.toNumber works. I guess I am doing something very wrong that is breaking future calls to JavaScript.

You should put your [ENTITIES:Cliente] and your formats below it near the end of your template not inline with it. Im not sure if that would fix it but its a good practice to do that you could cause your template to break otherwise.

1 Like

@Jesse is correct. Your Template should be like this:

[LAYOUT]
<T>TEST

{ENTITIES} 

{ORDERS}

<J10>Total:|{TICKET TOTAL}
<L00>Test HelperToNumber: {CALL:tests.toNumber('{TICKET TOTAL}')}

[ENTITIES:Cliente]
<L00>Nombre: {ENTITY NAME} 
<L00>NIT/CI: {ENTITY DATA:NIT}

Precisely @Jesse !!! That solved the issue, thank you all :slight_smile: