This is really complex lol Rounding calculations does not produce static results as user may add orders / add discounts after settling part of ticket. It recalculates whenever ticket amount changes. So you want it to round amount when HNL Cash is settled. User still can settle part of remaining HNL amount, add orders or change amount so rounding should recalculate⊠Thatâs why it always works from ticket amount. Not from the remaining amount at the time cash amount processed. Hmm⊠No need to think about that. Iâll try adding another calculation method that works from remaining amount. Letâs see what happens.
I know. I get it. I understand. It is complex and it has been frustrating for me.
I was actually considering not using Payment Processor Calculation and using just Rules and/or scripts, and maybe even build my own custom Payment Screen.
My head continues to spin on this subject, and I really want to get it implemented soon. But I need to finalize my decisions on what I want, and then try to figure out how to make it work.
Ok, I will give that a shot when you refresh. That is what I was attempting to do with the ROUND Payment Processed Rule - take a look at it - maybe that is a better way to go, I donât know.
I think I almost might need an Ask Question action so I can determine the Customer Payment âintentâ on how they are going to pay, and process Rules based on that answer?
P.S. as of right now. I donât know why that Payment Processor Calculation is not firing AT ALL, even if paying in full, in HNL. I am so lost⊠it was working the other day
Select Calculation Type as âRound Ticket Total Exactlyâ to always round up.
Also remove script processor temporarily. It somehow disables the calculation. Iâll check that.
When a calculation works from ticket balance should it recalculate as balance changes? I can think cases we may want it to recalculate or not.
Ok, I can do that temporarily, but eventually I want to keep it there. In factâŠ
Can we invoke Calculations from JS? If I could move all of this processing into JS it would ultimately be more flexible and more controllable. But for now, I donât think we have enough âpowerâ in JS for all Payment operations (ie. we do not have access to certain values?)
I understand that now, however, I might change my mind about always rounding up, so I avoided using that
Besides, literally yesterday, the Processor was working fine as-is when tendering full payment, even with the Script in there. I donât know what I did to break it, because today it does not work at all. GrrâŠ
Yes probably having that choice would be good. My brain is starting to tangle again LOL.
Good grief. Shut down SambaPOS and restart it. Now it is working again, even with the Script in there. I am yanking my hair out nowâŠ
EDIT: no it is not working. Not rounding. But the values are appearing on the Paymnet buttons now anywayâŠ
@emre, I have a question. If I am using a Calculation Type solely in a Payment Processor or an Action (never using it with a selector), is it necessary to set the Amount or can I leave it as 0
?
I thought it was not necessary to set the amount because it will be overriden by the Processor (or action) Amount?
And what about the Amount used in an Update Ticket Calculation
action? It should override the amount as well, yes?
That calculation rounds 552 to 550 but your calculation type does not allow decreasing amount so it does not work. Thatâs why you need secondary calculation for negative values (-2). If ticket total is 559, it will round to 560 so it will work.
That makes sense, I suppose. No wonder it looks like it isnât working (because the value is 552). I had no idea it was attempting to round down, because that was not my intent, which is why I left the âDecrease Amountâ Calc Type out of the Processor. Thank you for pointing this out.
This is the type of âblack boxâ operation that I donât like, but I understand why it is done this way. So in this case it is almost easier, or at least âclearerâ if I use a Rule and a Script, because then I know I will get exactly what I want.
It is a verbage thing - a choice of terms. âRound Ticket Total Exactlyâ does not mean to me âALWAYS Round Upâ. Actually, the term chosen means nothing to me - I donât understand what the term is trying to say at all.
It might be a better choice to have a checkbox or radio buttons for âAlways Round UPâ and âAlways Round DOWNâ. That would be more clear and understandable.
In the meantime, I will change it to âRound Ticket Total Exactlyâ. Does that mean if I also choose âDecrease Amountâ that it will ALWAYS Round Down? Thanks for the clarification.
Ok so now it appears to be working because I get the prompt to continue. But it is not giving me correct value if I first make a partial payment in USD ⊠note that USD 3 has already been tendered.
It does what it expected to do. These calculations are ticket based so it rounds ticket total from 552 to 560. 69 settled as usd. 491 remains.
GAAAAAH!
That is all.
EDIT: no wait - that is the point! This is why we need Rounding based on Remaining Amount (Balance)âŠ
I think? ⊠?
I need to use a pre-processor I think. A scenario like finding out how much is being Tendered and in what Currency, and then apply rounding based on comparing Remaining Amount with the Tendered Amount.
That way we know whether or not to use the Exchange Rate during the calculation. If tendering in Foreign Currency for an âoddâ Amount, we round (in my case, by 10).
Using the previous example:
- Ticket Total: 24 USD (552 HNL)
- Tender Partial Payment USD: 3
- Remaining Amount: 21 USD (483 HNL)
- Switch Currency to HNL
- Remaining Amount: 483 HNL
- Tender Payment HNL: 500
- Round Remaining Amount (483) to nearest 10 (up or down, whatever), for example, UP to 490
- that step ^ needs to happen before displaying and choosing Change Amount, so a
Payment Processed
Rule will not work here because unfortunately, thePayment Processed
Rule does not fire until we select one of the Change buttons. Once it is clicked, then the Payment Processed Rule fires⊠no good - too late. - we apply a Calculation that Rounds from 483 to 490 ⊠a difference of 7 @23 = 0.304348 USD which should should increase the Balance to USD 21.304348 (490 HNL), or if going by Ticket Total, it increases the same amount making the Ticket Total 24.304348 USD (559 HNL)
- now the Change Amount should be 10
That is the logic I am going for. I think the only Payment Processor that can handle that might be Execute Script, because it clearly has a Pre-process Handler parameter. Is this correct @emre? Or do we have other options?
@emre can I make this work? My question is: how do I access (read) and modify (write) from within the JScript, the following values:
- Remaining Amount (read)
- Exchange Rate (read)
- Ticket Total (update), or Apply Calculation
My script does the following shown in screenshots the behavior I want described in my previous post, so I want to apply my result somehow ⊠master call is:
balance('HNL',10,'up')
Script:
(using hard-coded values for now)
function nearest(num,rnd,xr) {
// num : the number to round
// rnd : a value to round to
// xr : exchange rate
dlg.ShowMessage('Nearest:'+num+' by '+rnd+' with XR:'+xr);
if (xr<1) {
num = num / xr;
} else {
num = num * xr;
}
rnd = 1 / (rnd);
return Math.round(num * rnd) / rnd;
}
function up(num,rnd,xr) {
// num : the number to round
// rnd : a value to round to
// xr : exchange rate
dlg.ShowMessage('Up:'+num+' by '+rnd+' with XR:'+xr);
if (xr<1) {
num = num / xr;
} else {
num = num * xr;
}
rnd = 1 / (rnd);
return Math.ceil(num * rnd) / rnd;
}
function down(num,rnd,xr) {
// num : the number to round
// rnd : a value to round to
// xr : exchange rate
dlg.ShowMessage('Down:'+num+' by '+rnd+' with XR:'+xr);
if (xr<1) {
num = num / xr;
} else {
num = num * xr;
}
rnd = 1 / (rnd);
return Math.floor(num * rnd) / rnd;
}
function balance(currency,rnd,direction) {
// get exchange rate
var xr = 23;
// get Remaining Amount
var amt = 21;
// var for result
var res = 0;
dlg.ShowMessage('Balance:'+amt+'('+(amt*xr)+')'+' by '+rnd+' rounding '+(direction=='up' ? 'UP' : 'DOWN')+' with XR:'+xr);
// choose direction
switch (direction) {
case 'up':
res = up(amt,rnd,xr);
break;
case 'down':
res = down(amt,rnd,xr);
break;
default:
res = nearest(amt,rnd,xr);
break;
}
dlg.ShowMessage('RESULT:'+res+ '('+(res/xr)+')');
return res / xr;
}
I tried the following:
var tendered = Data.Get("tenderedAmount"); // this is the only one that works
var total = Data.Get("totalAmount"); // here down all return NULL
var remaining = Data.Get("remainingAmount");
var payment = Data.Get("paymentAmount");
var processed = Data.Get("processedAmount");
var change = Data.Get("changeAmount");
This is a common issue if someone will like to use SambaPOS like that. Iâd like to find a simple solution. Let me think about that. If I canât find a good idea we can think about script stuff. I donât want to rely on scripting too much.
The real problem is not calculating rounding. The problem is applying it to ticket. While applying it to ticket weâll probably add them as a calculation so we can reflect these amounts to accounting. However calculations does not store amounts and they re-evaluates from ticket total when needed. Using remaining amount (half paid amount) for a calculation is a little different. When ticket closes remaining amount becomes 0 so we wonât be able to re-evaluate remaining amount based calculations. This is not something that canât be solved but I have to find a good solution to be able to make it useful for everyone.
Ok, no worries. Let me know your ideas.
Yes, I agree, we want to apply a Calculation so we have a trace in Accounting. It is the âhow to calculate, and when to apply itâ that I think is the struggle - the problem to solve.
But, but, but⊠I LOVE Script
I have a question. Regarding your previous screen shots what should we do if operator tenders 485 HNL?
The simple answer is: they wonât, because we donât give them that option. The operator would inform the client that the remaining amount is 490.
If we assume that we round to nearest 5 instead of 10, then the client is informed that the remaining amount is 485, in which case we accept that.
The long answer:
This becomes a problem when there is a Customer Display, in which case the client can clearly see that they only owe 483. If that is the case, then we also accept exactly 483, or 485, or whatever. So how do we handle that?
Here is my idea:
Update (round) as soon as the currency button is clicked on the display only. I think that would be very beneficial. We tender 3 of the 24, click the currency button, and it updates the display with a rounded Foreign (HNL) value, for the operator on the Payment Screen, and for the client on the Customer Display, but without actually applying the calculation. The calculation is only applied once a Payment type is clicked. If the currency button is clicked again, the rounded HNL value is swapped out and it goes back to showing Default Currency (USD).
That would be a new feature for the currency switch button, like a pre-processor that changes the display, but does nothing internally (no Calcs) so it does not need to be reversed.
What do you think of that idea @emre?
I implemented something for the issue. I hope that helps.
Weâll use âAdd Serviceâ and âAdd Discountâ payment processors to solve that. The difference of these processors from âAdd Calculationâ processor is these processors works with Fixed Amount Calculation templates and once added their amount does not recalculate. For example if you add %10 discount with âAdd Calculationâ processor it will recalculate as ticket amount changes but when added with âAdd Discountâ processors it will calculate once and will not change.
To use it we need to change type of Rounding Calculation Types to âFixed Amountâ.
Change Negative Rounding (- Rounding) payment processor type as âAdd Discountâ processor and set it as follows.
Do the same thing for (+ Rounding). Change it as âAdd Serviceâ processor and set parameters as follows.
On this setup the amount will round to nearest value and apply when it fully paid.
To apply âalways upperâ or âalways lowerâ rounding youâll use a single payment processor to calculate the rounding and disable âRound to Nearestâ setting.