Rounding and issuing change in multiple currencies

This is really complex lol :slight_smile: 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 :stuck_out_tongue_winking_eye:

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.

1 Like

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.

1 Like

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 :wink:

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! :stuck_out_tongue_winking_eye:

That is all.

EDIT: no wait - that is the point! This is why we need Rounding based on Remaining Amount (Balance)


I think? 
 ? :wink:

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, the Payment 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.

1 Like

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 :stuck_out_tongue_winking_eye:

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? :wink:

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.

1 Like

Excellent! It seems to do exactly what I want now! :smile:

Configuration:

Using a single Payment Processor to always Round UP to 10.


Operation:

:happydance: :wink: