Odd result from script to calculate days sales

I expect rounding will easily cover the very small variance however all prices are in 5p so dont understand where the variance comes from…

Script is quite long so have started with sales etc first;
Have only rang in a few products to test script;

Fosters 3.80 (Tax 1)
Kronie 4.10 (Tax 1)
Sausages 9.95 (Tax 0)

Tax setup is irrelevant as all i need to know is if taxed for not and set 0 or 1.
It has no impact on calculated price as all workings are in gross/tax inclusive product price.

Here is my accounts screen;

The response from my script is;

GLA: 10003 - Tax: 0 - Total: 0
GLA: 10003 - Tax: 1 - Total: 7.8999999999999995
GLA: 10002 - Tax: 0 - Total: 9.95
GLA: 10002 - Tax: 1 - Total: 0

Here is the script;

//Load NewBook Variables
var vars 								= script.Load("NewBookVariables","initialize");																							//Load NewBook Variables
vars.initialize();																																								//Instalise NewBook Variables

//Load Scripts
var NewBookRequests						= script.Load("NewBookRequests","postRoomCharge");																						//Load NewBook Room Post Script
var dbTools		 						= script.Load("dbTools","ticketOrderCount","ticketOrderList","orderDetails","uniqueListofTags","eodTicketIdCount","eodTicketIdList");	//Load dbTools Scripts
var JSONTools							= script.Load("JSONTools","searchTagArrayIndex","searchStateArrayIndex","searchTaxArrayIndex");											//Search JSON array for data name value

function eodSalesArray() {
	
	var runDate											= new Date()																					//Set script run time
	var startDate										= '2016-01-01';
	
	var ticketIdCount									= dbTools.eodTicketIdCount(startDate,roomPostPaymentName);
	var ticketIdList									= dbTools.eodTicketIdList(startDate,roomPostPaymentName);

	var posDepartmentList								= dbTools.uniqueListofTags(pmsDepartment);
	var posDepartmentCount								= posDepartmentList.length;
	var salesArray										= '';
	
	var taxList											= ["0","1"];
	var taxCount										= taxList.length;
	
	for (g = 0; g < posDepartmentCount ; g++)
		{
		var loopDepartment								= posDepartmentList[g];
		var loopDepartmentTotal							= 0;
		
		var chargeArray									= '';
			
		for (v = 0; v < taxCount ; v++)
			{
			var loopTax									= taxList[v];
			var taxTotal								= 0;
			
			for (t = 0; t < ticketIdCount ; t++)		
				{
				var loopTicket							= ticketIdList[t];
				
				var loopTicketOrderCount				= dbTools.ticketOrderCount(loopTicket);
				var loopTicketOrderList					= dbTools.ticketOrderList(loopTicket);
				
				var ticketTotal							= 0;
				
				for (o = 0; o < loopTicketOrderCount ; o++)
					{
					var loopOrder						= loopTicketOrderList[o];
					
					var orderRowString	 				= dbTools.orderDetails(loopOrder);
					var orderRowArray 					= orderRowString.split('~');
					
					var orderPrice 						= orderRowArray[4];  
					var orderQuantity					= orderRowArray[5];    
					var orderQuantityRounded			= +(Math.round(orderQuantity + "e+2")  + "e-2");
					
					var orderStateJsonRaw				= orderRowArray[7];
					var orderStateJson					= JSON.parse(orderStateJsonRaw);
					var stateArrayNumber				= JSONTools.searchStateArrayIndex(orderStateJson,pmsDepartment);
					var orderGLAccount					= orderStateJson[stateArrayNumber].S;
					
					var orderTaxJsonRaw					= orderRowArray[6];
					var orderTaxJson					= JSON.parse(orderTaxJsonRaw);
					var taxArrayNumber					= JSONTools.searchTaxArrayIndex(orderTaxJson,postTaxName);
					if (taxArrayNumber == '-1')
						{
						var orderTaxable				= 0;
						} else {
						var orderTaxable				= 1;
						}
									
					var orderGiftStateJsonRaw			= orderRowArray[7];
					var orderGiftStateJson				= JSON.parse(orderGiftStateJsonRaw);
					var giftStateArrayNumber			= JSONTools.searchStateArrayIndex(orderGiftStateJson,'GStatus');
					
					if (giftStateArrayNumber == '-1')
						{
						var giftStateMultiplier			= 1;
						} else {
						var giftStateMultiplier			= orderGiftStateJson[giftStateArrayNumber].SV;
						}
					
					var orderTotal = orderQuantityRounded * orderPrice * giftStateMultiplier;
					
					if (orderGLAccount == loopDepartment && orderTaxable == loopTax)
						{
						ticketTotal						+= orderTotal
						} 
					} 																												//order loop end
				
				taxTotal								+= ticketTotal
				} 																													//ticket loop end
			
			chargeArray									+= 'GLA: '+loopDepartment+' - Tax: '+loopTax+' - Total: '+taxTotal+'\r';
			} 																														//tax loop end
		
		salesArray										+= chargeArray;
		} 																															//department loop end
	
	return salesArray
	}

Pretty much its just compounded for loops which go through;

->Department/GLA (Only 10002 and 10003 at the moment
    |-->Tax (0 or 1)
           |-->Tickets (All tickets for work period)
                |-->Orders (All orders in tickets loop)

There are then a few ifs in the orders loop which only adds the value of orders which meet the Department && Tax from that cycle.

If I create a log of all parts of the loop where calculations are made I get this;
| 1 x 4.10 x 1 | 1 x 3.80 x 1 | 1 x 9.95 x 1

Well… after reading it 3 times I thought someone will understand the question and answer that. I think nobody could get it yet.

1 Like

I thought maybe his brain interfaced to the computer and we’re actually just seeing thoughts. Lol. I couldn’t understand what he was getting at.

At one point he started to think in code.

I’ll be honest I don’t see how all that is needed just to see the sales?

2 Likes

:hushed: << The moment I read interfaced as infected lol.

2 Likes

What is Tax 1 rate?

You will likely find that the data is stored in the table with that fine precision which produces the value you are getting.

Its a binary style for taxable or not.
0 tax free
1 taxable

All prices are handled in inclusive.

The only calculations performed are
Price x Quantity x 0
Price x Quantity x 1

0 Is the state value I have set for gift (calculate price = false) states to achive the same thing as calculate price

Your Tax Rate is not binary. What is your Tax 1 rate? I want to attempt proof of concept that is along the line of this:

If it is tax-inclusive, it backs the tax out of the price and posts that value to the table, along with the tax amount, then it gives a total of the two. This math is where all the decimals come from.

The priducts and ticket are set as tax inclusive.
The price in the orders table is the raw inclusive price with two decimals)

Tax rate isnt, all I have done in the script is to check the tax jason to see if that order has VAT as a mapped tax and if so sets the orderTax as 1 (1 being taxable and 0 being tax free)
the PMS tages total/inclusive price and is its tax free or not. it also works in inclusive prices.

The array to go out includes;

gl_account
desctiption
amount
tax_free (0 for tax free, 1 for includes tax)

I understand all that. I realize how you are creating the data and that it is Tax-inclusive, and that you are pulling the Price from the Orders table (if you are not pulling price from Orders table, you should be), and that you are using the order tags to determine if the product was taxed or not.

In any case, you still have not answered my question: What is your Tax Rate? Is it a secret?

I setup a log variable to show the values used in the calculation and the prices coume out as whole numbers.

That is QTY x PRICE x GIFTSTATE MULTIPLIER

(Gift state multipler is the state value for gstatus state where i have set the value for gift and void to be 0 but refund as 1 so that refund will still be counted, gift will be counted but the 0 will cause the price ro be 0 and added a state == void to skip voids.

LOL sorry, didnt see you were asking, its 20% vat

But the order price in the orders table will be to rax product price wouldnt it? the values in the table are round numbers no x.999999999999999 values.

Initialize your variable for Price as such to see if it helps:

var orderPrice = 0.00
1 Like

Ok, will try as soon as im home… :smile:

This is the only other posibility I can think of…
+(Math.round(orderQuantity + "e+2") + "e-2")
This was to round qty to a whole number so that is displayed in the description as whole number…
Maybe if i switch the order price calculation to use raw qty value ratherr than rounded.

Although that shouldnt effect the calculation as its only removing the training 0 decimals.

Hmm… I think I asked 3 times now, but thanks…

Anyway, this is the proof-of-concept that illustrates why you might be seeing what you are seeing:

3.80 / 1.20 = 3.1666666666666666666666666666667
4.10 / 1.20 = 3.4166666666666666666666666666667
     Total  = 6.58332
     x 1.2  = 7.899984

I understand that the Price field appears to be fixed at 2 decimals, so you would think that this has no bearing on your calculations. But the idea is there.

It is dealing with numbers with greater precision than it appears. The Price field for example is set to a type of decimal(16,2). And the quantity is decimal(16,3). When you multiply them, your decimal precision increases.

I have found with JScript that if you initialize your variables to a certain number of decimals, they will stay that way and perform rounding automatically, which is why you might want to try this:

var orderPrice = 0.00
var orderQuantity = 0
1 Like

This didnt help.
Is very odd…

Done some more testing and check this out…

Ok so there are 4 for loops and at the end of each one the total for that loop is added to a variable ie;
ticketTotal += orderTotal

Although for this example its within an if;

if (orderGLAccount == loopDepartment && orderTaxable == loopTax)
    {
    ticketTotal		+= orderTotal
    }

This means it only adds the total for orders which fit the parameters of this loop…

I tried adding the;

var orderPrice = 0.00
var orderQuantity = 0

But didnt help, so I have added a couple of ‘log’ variables to see at what point the .9999999 comes from and its well after the orderPrice has been calculated…

So;

orderTotallog;
| 1 x 4.10 x 1 = 4.1 | 1 x 3.80 x 1 = 3.8 | 1 x 9.95 x 1 = 9.95
each pipe represents a loop where the total was calculated.

ticketTotalLog;
| 0 | 0 | 0 | 4.1 | 3.8 | 0 | 0 | 0 | 9.95 | 0 | 0 | 0

taxTotalLog;
| 0 | 7.8999999999999995 | 9.95 | 0

Also, have just rand in a bunch more products to chec as there was only 1 product in 10003 department which was no tax mapped and now same issue on both;
| 0 | 23.849999999999998 | 31.849999999999998 | 0

Try initializing all your vars to 0.00, especially the xxxxTotal vars, and get rid of orderQuantityRounded Math.Round() function to eliminate that from the equation.

1 Like

Nope, no help, its in this last bit…

taxTotal		+= ticketTotal;

As the log shows that ticketTotals being used are;
| 0 | 0 | 0 | 4.1 | 3.8 | 0 | 0 | 0 | 9.95 | 0 | 0 | 0

Where these will be divided;
GLA: 10002 & Tax 0 = | 0 | 0 | 0
GLA: 10002 & Tax 1 = | 4.1 | 3.8 | 0
GLA: 10003 & Tax 0 =| 0 | 0 | 9.95
GLA: 10003 & Tax 1 =| 0 | 0 | 0

But somehow adding these gives; (first being Tax 0 and Second Tax 1)
GLA:10002 = | 0 | 7.8999999999999995
GLA:10003 = | 9.95 | 0

Oh well. It is coming from somewhere in the tax division, so round it yourself. Welcome to the quirkyness of JavaScript!

var num_with_2_decimals = Math.round(num_with_lots_of_decimals * 100) / 100