Urgent ... Weird behaviour when incrementing system variable

#Actions


#Using a single Rule

message:

OSN:{SETTING:SerialNumberOLD}\rNSN:{SETTING:SerialNumber}\rTAG:{TICKET TAG:SerNum}\rRA:[:RemainingAmount]

#Using 2 Rules

message:

OSN:{SETTING:SerialNumberOLD}\rNSN:{SETTING:SerialNumber}\rTAG:{TICKET TAG:SerNum}\rRA:[:RemainingAmount]

As I surmised…

The Remaining Amount on the Payment Processed Rule is NOT 0 when Change is Due. The Remaining Amount is NEGATIVE when Change is Due. So this constraint DOES NOT WORK when Change is Due:

Remaining Amount Equals 0

You must use something like this:

Remaining Amount Less 0.01


This is DIFFERENT in a Before Ticket Closing Rule. Remaining Amount will be 0 even if Change is Due. That is how the Ticket Payment Check (default Rule) is set up.

1 Like

Thanks.

The goal is to debug?

###LESSONS:###

1) For a Payment Processed Rule, set the Rule Constraints to:

Remaining Amount Less 0.01

And set Action Constraints (if necessary) to:

[=TN('[:RemainingAmount]')] < 0.01

2) Use a Show Message Action to debug to ensure the values you are filtering are in fact what you think they are. It is your best trouble-shooting tool.

3) Make your Actions more “generic” by using [:variables] for Action Parameters.


@sukasem,

Can you please test RDP using the above information?

  1. it is/was setup like that

  2. yes

  3. ok but it is suposed to work the way I have it now. I did what you told me: using variable; i++ using {value+1}. I also separate the actions i++ and Tag in 2 different rules.


I’ll do it but system is live; I am running a restaurant; the waitresses (tablets) “will have to debug”, the message will appear on their tablet, of course they cannot, so me running behind them, the doubles appear when 2 waitresses uses SambaPOS, so between one modification and “testing in real life”, lots of time is lost, etc …

I don’t understand the point of going through automation command, I like simple not complicated. I like “I touch SambaPOS default configuration the minimum” and really I haven’t touch it a lot at all (printer template, report, entities), so one day, the update will be easier.


As an alternative to try to make it work I am looking for help with script (never did one yet).
I would like to make 1 actions:

Action SrNum++

Action type: script
Script = SQL SrNum FROM ProgramSettingValue; SrNum++; Update SrNum into ProgranSettingValue; return 0;

Ticket Tag Action in rule would be something like that (don’t know if possible):

(or a script instead of report stuff)


Finally I will miss time because once the problem is solved, I must correct all these tickets.

You can disable the Show Message action in the Rule at any time with an Action Constraint of: 1==2

You should not need multiple Rules; it was for demonstration only on how to setup up a multi-rule flow using Execute Automation Command action. This is the “normal” way to chain Rules together, and does not require re-ordering Rules in most cases.

Recommending using a [:variable] for an Action parameter has several advantages:

  • hard-coding values like {SETTING:SerialNumber} in an Action Parameter is a bad idea, and unreliable.
  • Actions become re-usable, and you can change the Parameters in the Rule at any time.
  • you don’t need to remove an Action from a Rule, Save, change the Action, add the Action back into the Rule, and Save again. Major PITA.

I could have suggested Scripting, but what you have should be working, so I did not want to throw another curve at you. You want simple, and scripts add complexity. If you want, I can show you how to set that up using Script.

#Script

This script has 2 functions. Either will work; they produce the same result.

  • update a Global Setting using SQL
  • update a Global Setting using GQL (GraphQL)

Name: Update Setting
Handler: setting

function updateGlobalSQL(settingName,settingValue) {
	settingName  = typeof settingName  === 'undefined' ? '' : settingName;
	settingValue = typeof settingValue === 'undefined' ? '' : settingValue;
	
	var qry = "";
	var res = "";
	var currentValue = "";
	var newValue = "";
	
	qry = "SELECT [Value] FROM [ProgramSettingValues] WHERE [Name] = '" + settingName + "'";
	res = sql.Exec(qry);
	currentValue = res[0];
	
	if (settingValue == 'increase') {
		newValue = Helper.ToNumber(currentValue) + 1;
	} else if (settingValue == 'decrease') {
		newValue = Helper.ToNumber(currentValue) - 1;
	} else {
		newValue = settingValue;
	}
	
	qry = "UPDATE [ProgramSettingValues] SET [Value]='" + newValue + "' WHERE [Name] = '" + settingName + "'";
	res = sql.Exec(qry);
	
	return newValue;
}

function updateGlobalGQL(settingName,settingValue) {
	settingName  = typeof settingName  === 'undefined' ? '' : settingName;
	settingValue = typeof settingValue === 'undefined' ? '' : settingValue;
	
	var qry = "";
	var res = "";
	var currentValue = "";
	var newValue = "";
	
	qry = '{setting:getGlobalSetting(name:"'+ settingName + '"){name,value}}';
	res = gql.Exec(qry);
	res = JSON.parse(res);
	currentValue = res.data.setting.value;
	
	if (settingValue == 'increase') {
		newValue = Helper.ToNumber(currentValue) + 1;
	} else if (settingValue == 'decrease') {
		newValue = Helper.ToNumber(currentValue) - 1;
	} else {
		newValue = settingValue;
	}
	
	qry = 'mutation m {setting:updateGlobalSetting(name:"'+ settingName + '",value:"' + newValue + '"){name,value}}';
	res = gql.Exec(qry);
	res = JSON.parse(res);
	newValue = res.data.setting.value;
	
	return newValue;
}

#Action


#Rule

handler.func() parameter can be either:

setting.updateGlobalSQL('SerialNumber','increase')

setting.updateGlobalGQL('SerialNumber','increase')


{REPORT SQL DETAILS:X}:

{REPORT SQL DETAILS:SELECT [Value] FROM [ProgramSettingValues] WHERE [Name]='SerialNumber':F.Value}


1 Like

It get weird. I can reproduce this.
setup:

  1. Action: Setting Name: [:Setting Name] , Settng Value: 1 , Update Type: Increase, Is Local: False
  2. Automation Command Show Message: {SETTING:SN}
  3. Rule with action Update program setting Setting Name: SN and Ticket Tag Value: {SETTING:SN} in the same rule
    Step:
  4. I settle (exeute rule to update SN) on RDP (Now SN = 10)
  5. I change database SN to 8 directly from SQL.
  6. Without logout POS (RDP terminal) (no cache reset), Use another automation command to show message SN, It read 8.
  7. Now settle but SN is 11 (Expected 9, it use last memory value of 10 + 1).
  8. chage database SN to 8 again
  9. logout POS (RDP terminal) and login
  10. click show message, read 8
  11. Now settle again SN is 9 (As Expected)

I don’t know why it use cache value except show message.

EDIT: hmmm it is not just RDP. It happen on Server as well.

Logout and in FROM RDP or FROM windows session?
If Just log out from RDP, what about SambaPOS, did you close it before log out or not?[quote=“sukasem, post:108, topic:15062”]
I don’t know why it use cache value except show message.
[/quote]

What is cache ? RDP cache something? no.

Logout POS in RDP session.

What I find I think, {SETTING:XXX} Show message actually read from Database but Update Program Setting Action keep using Local Setting Value to update.

So, I think I will try using Update Type: Update and use value+1 and see if {SETTING:SN} + 1 would force it to read from database.

it’s twice the same no?
I try it, thanks

Nope, first one is SQL, second one is GQL (GraphQL).

Pick one; the result is the same.

I just wanted to demo GraphQL as an alternative to using SQL, so I created 2 functions in the Script: 1 for each method.

That’s what I am doing without success.

So Is Local:False not working, no?

It tell SambaPOS to save value to Database. So it works because it has the setting in database.

The problem is when it update the value, i’m not sure now if it read from database if there is the value in the memory.

The restaurant is open now I have no time to set it up.

Understood your script.
(I don’t know what is GQL but it will be for much later)

I put everything in place, but I cannot test it now because lots of customers.
As soon as I have a low, I’ll put it.

setting (handler) is a prefix you attach to the function to locate it?

Thanks for your help, I am almost sure that will do it

Is local set to false works and it is easy to test that. I use that setting extensively in multiple different configurations so I know without a doubt it’s working. There is something specific to your setup that is not working as desired.

In fact I use it for the exact same thing your trying to do and it has never not worked. I call mine order # instead of serial number but it’s all the same. I think your issue is something to do with your RDP setup.

Yes, you can create many Scripts. And the Scripts can be JScript or SQL. And those scripts (JScript) can have multiple Functions/methods within them. One JScript script could contain Function(s) that have the same name as Functions in another JScript script.

The Handler is to know which Script you are referencing.

SQL Scripts always have this format for the Handler using leading @@:

@@handlerName

JScript Scripts just have a string for the Handler:

handlerName

Then to fire a Function in a JScript, you call it by invoking:

handlerName.functionName(funcParameters)

You can also “call” Scripts using the {CALL:X} Tag, for example, in a Printer or Report Template, or in a Rule:

{CALL:handlerName.functionName(funcParms)}

The result (return value) of the Script will be used in place of the {CALL:X}. So in the case of the JScript that I wrote above, this:

{CALL:setting.updateGlobalSQL('SerialNumber','increase')}

… will return the updated value of the SerialNumber, because the function returns newValue.

So you could reduce your Rule by 1 Action, to use {CALL:X} which will UPDATE and return the Updated Value …

[=TN("{CALL:setting.updateGlobalSQL('SerialNumber','increase')}")]


##No Change Due:

##Change Due:

1 Like

Hi kendash,

Forget about that rdp stuff; yesterday I ask the waitresses to setlle directly (no rdp) on the main computer, each of them using their windows user session without closing the windows session of the other - “cambiar usuario”. So change (windows) user and not close (windows) session.
That way 2 SambaPOS running for 2 users, I got the same result.


That is exactly what happens (thanks @sukasem ) and this is sukasem setup.

Update Program Setting

Is Local : False means SQL stored (QMcKay)

In case of Update, it should:

  1. Read the setting value - in our case we give {:GLOBAL SETTING:SerialNo}
  2. SQL update that value to database

And this is not the case if more than 1 SamPOS program is running.
(actually the same problem occurs with only one SambaPOS running but it will not create issue)

So,

  1. OR the value we pass is wrong - {:GLOBAL SETTING:SerialNo}
  2. OR the Program Setting Update does not SQL store that value in the database.
  3. OR once SambaPOS has read once from the database {:GLOBAL SETTING:SerialNo}, it is happy and works with that value in a variable. If this is the case, it would make sense (using programming vocabulary) to put Is Local = True , that way the variable that contains {:GLOBAL SETTING:SerialNo} will only be used once (local variable) by that action and the next time it execute that same action, it would have to re-read the database.

The guys who wrote that part could answer in a sec.

Before using QMcKay script to completly replace that action, I am doing a last try with that Update Program Setting action, giving the following as the Setting Value:
[=TN('{REPORT SQL DETAILS:SELECT [Value] FROM [ProgramSettingValues] WHERE [Name]='SerialNumber':F.Value}') + 1]

If I still see the problem, I can discard nº1 to be the problem, so it is nº2 or nº3.

Good to know. So you are claiming that this issue is a result of running more than a single Windows User Session. Interesting. Now I have a way for me to test this without RDP. Thanks for that.

EDIT: Hmm… seems I need to learn how to run SambaPOS in multiple User Sessions… right now, one session/instance is logged in and WP is started, but in the other session/instance, the WP is closed… why are they not “aware of each-other”? I even have the Terminals set uniquely in Local Settings in each session…

10 posts were split to a new topic: SambaPOS in multiple Windows User Sessions