Looking for ideas for better Cashout Count Reporting


#1

I have this Workperiod Screen that contains Editor Widgets (orange) for counts of different Tenders when doing a closeout for the day. Some Label Widgets contain expressions to sum the Counts (blue) of all the Count boxes. It also contains a Report (yellow) that shows Tender over/short values, and Totals for over/short.

The Editor Widgets (orange) invoke storage to Program Settings for each Tender and the Total of the Currency or CC. The Program Settings are stored in the DB and are overwritten when a Count is changed.

The Report (below) reads the Program Settings, and compares Tender Count Totals to Account Balances to determine if the Tender is over/short/balanced:

[Cashout Report:1, 1, 1, 1, 1]
>>Tender|Count|(-Float)|Account|+/-
HNL|[=F(TN('{SETTING:HNLcountTotal}'),'0.00')]|[=F(TN('{SETTING:HNLcountTotal}')-TN('{SETTING:HNLfloat}'),'0.00')]|[=F(TN('{ACCOUNT TOTAL:Cash HNL}')*TN('{SETTING:XR_USDtoHNL}'),'0.00')]|[=F(TN('{SETTING:HNLcountTotal}')-TN('{SETTING:HNLfloat}')-(TN('{ACCOUNT TOTAL:Cash HNL}')*TN('{SETTING:XR_USDtoHNL}')),'0.00')]
USD|[=F(TN('{SETTING:USDcountTotal}'),'0.00')]|[=F(TN('{SETTING:USDcountTotal}')-TN('{SETTING:USDfloat}'),'0.00')]|[=F(TN('{ACCOUNT TOTAL:Cash USD}'),'0.00')]|[=F(TN('{SETTING:USDcountTotal}')-TN('{SETTING:USDfloat}')-TN('{ACCOUNT TOTAL:Cash USD}'),'0.00')]
CC HNL|[=F(TN('{SETTING:CCcountTotal}'),'0.00')]|-|[=F(TN('{ACCOUNT TOTAL:Credit Card HNL}')*TN('{SETTING:XR_USDtoHNL}'),'0.00')]|[=F(TN('{SETTING:CCcountTotal}')-(TN('{ACCOUNT TOTAL:Credit Card HNL}')*TN('{SETTING:XR_USDtoHNL}')),'0.00')]
CC USD|[=F(TN('{SETTING:CCUSDcountTotal}'),'0.00')]|-|[=F(TN('{ACCOUNT TOTAL:Credit Card USD}'),'0.00')]|[=F(TN('{SETTING:CCUSDcountTotal}')-TN('{ACCOUNT TOTAL:Credit Card USD}'),'0.00')]
>>Account|HNL|USD|-|TTL USD
Tips HNL|[=F(TN('{ACCOUNT TOTAL:Tips}')*TN('{SETTING:XR_USDtoHNL}'))]|[=F(TN('{ACCOUNT TOTAL:Tips}'))]|-|[=F(TN('{ACCOUNT TOTAL:Tips}'))]
Round|[=F(TN('{ACCOUNT TOTAL:Rounding HNL}'))]|[=F(TN('{ACCOUNT TOTAL:Rounding USD}'))]|-|[=F(TN('{ACCOUNT TOTAL:Rounding USD}')+TN('{ACCOUNT TOTAL:Rounding HNL}'))]
>XR/TTL|[=F(TN('{SETTING:XR_USDtoHNL}'),'0.00')]|[=F(TN('{SETTING:XR_HNLtoUSD}'),'0.000000')]|-|[=F(TN('{ACCOUNT TOTAL:Tips}')+TN('{ACCOUNT TOTAL:Rounding USD}')+TN('{ACCOUNT TOTAL:Rounding HNL}'))]

>>TOTALS|Count|(-Float)|Account|+/-
HNL|[=F(TN('{SETTING:HNLcountTotal}')+TN('{SETTING:CCcountTotal}')+TN('{SETTING:CCUSDcountTotal}')*TN('{SETTING:XR_USDtoHNL}')+TN('{SETTING:USDcountTotal}')*TN('{SETTING:XR_USDtoHNL}'),'0.00')]|[=F( TN('{SETTING:HNLcountTotal}')-TN('{SETTING:HNLfloat}') + TN('{SETTING:USDcountTotal}')*TN('{SETTING:XR_USDtoHNL}')-TN('{SETTING:USDfloat}')*TN('{SETTING:XR_USDtoHNL}') + TN('{SETTING:CCcountTotal}') + TN('{SETTING:CCUSDcountTotal}')*TN('{SETTING:XR_USDtoHNL}'),'0.00')]|[=F((TN('{ACCOUNT TOTAL:Cash HNL}')+TN('{ACCOUNT TOTAL:Cash USD}')+TN('{ACCOUNT TOTAL:Credit Card HNL}')+TN('{ACCOUNT TOTAL:Credit Card USD}')+TN('{ACCOUNT TOTAL:Tips}'))*TN('{SETTING:XR_USDtoHNL}'),'0.00')]|[=F(TN('{SETTING:HNLcountTotal}')-TN('{SETTING:HNLfloat}') + TN('{SETTING:USDcountTotal}')*TN('{SETTING:XR_USDtoHNL}')-TN('{SETTING:USDfloat}')*TN('{SETTING:XR_USDtoHNL}') + TN('{SETTING:CCcountTotal}') + TN('{SETTING:CCUSDcountTotal}')*TN('{SETTING:XR_USDtoHNL}') - ((TN('{ACCOUNT TOTAL:Cash HNL}')+TN('{ACCOUNT TOTAL:Cash USD}')+TN('{ACCOUNT TOTAL:Credit Card HNL}')+TN('{ACCOUNT TOTAL:Credit Card USD}')+TN('{ACCOUNT TOTAL:Tips}')))*TN('{SETTING:XR_USDtoHNL}'),'0.00')]
USD|[=F(((TN('{SETTING:HNLcountTotal}')+TN('{SETTING:CCcountTotal}'))/TN('{SETTING:XR_USDtoHNL}'))+TN('{SETTING:CCUSDcountTotal}')+TN('{SETTING:USDcountTotal}'),'0.00')]|[=F( ((TN('{SETTING:HNLcountTotal}')-TN('{SETTING:HNLfloat}'))/TN('{SETTING:XR_USDtoHNL}')) + TN('{SETTING:USDcountTotal}')-TN('{SETTING:USDfloat}') + (TN('{SETTING:CCcountTotal}')/TN('{SETTING:XR_USDtoHNL}')) + TN('{SETTING:CCUSDcountTotal}'),'0.00')]|[=F(TN('{ACCOUNT TOTAL:Cash HNL}')+TN('{ACCOUNT TOTAL:Cash USD}')+TN('{ACCOUNT TOTAL:Credit Card HNL}')+TN('{ACCOUNT TOTAL:Credit Card USD}')+TN('{ACCOUNT TOTAL:Tips}'),'0.00')]|[=F(TN('{SETTING:HNLcountTotal}')/TN('{SETTING:XR_USDtoHNL}')-TN('{SETTING:HNLfloat}')/TN('{SETTING:XR_USDtoHNL}') + TN('{SETTING:USDcountTotal}')-TN('{SETTING:USDfloat}') + TN('{SETTING:CCcountTotal}')/TN('{SETTING:XR_USDtoHNL}') + TN('{SETTING:CCUSDcountTotal}') - (TN('{ACCOUNT TOTAL:Cash HNL}')+TN('{ACCOUNT TOTAL:Cash USD}')+TN('{ACCOUNT TOTAL:Credit Card HNL}')+TN('{ACCOUNT TOTAL:Credit Card USD}')+TN('{ACCOUNT TOTAL:Tips}')),'0.00')]

The problem that I have realized is that this does not provide sufficient historical Reporting for Cashout Counts, because the Program Settings are overwritten from day to day. So I want to store the values in a different manner. You can also see that the Report uses a Program Setting to read the Exchange Rate, but in this case, it will use the “current” Exchange Rate when I would really like to use an XR for the day the Cashout was done since it may change over time.


It seems to me that using Tasks would be a good way to go for this, as I assume {REPORT TASK DETAILS:X} would be date-aware for things like Today, Yesterday, etc or any other Date Range that I could provide as a filter. @emre, if this is not true, then please let me know.

So I guess I am looking for ideas on how to set up the Task Types:

  • Should I use a single Task Type for each Tender (Cash USD, Cash HNL, CC) and have Custom Fields for each Denomination of that Tender (HNL500, HNL100, HNL50, USD100, USD50, etc) and a Custom Field for the Total of Tender (HNLTTL, USDTTL, CCTTL)?

  • Or should I use a single Task for each Denomination (HNL500, HNL100, HNL50, USD100, USD50, etc) and another Task Type for the Tender Total (HNLTTL, USDTTL, CCTTL)?

The first idea would look like the following… seem like a good way to go?


Cashup Screen sambapos v5
#2

I think this is going to work very well.

And am I ever glad I built a Task Editor into GQL Modules… it makes testing so much easier! :stuck_out_tongue_winking_eye:

Now I am wondering if maybe I should just build a Cashout Count Module for GQL Modules instead of using an Entity Screen? Hmmm… need to think about that some more…


#3

I just can’t get past the name “Tasks” - it like it needs to do something? Q you are using it because of the Custom Fields ability and Date storage right…


#4

Yes, I am using it because of the Custom Fields and Date filtering.

Originally, the “Tasks” and “Task Types” was created pretty much for making “To Do” Lists and then you could fulfill the Task and check it off your List by marking it “Completed”.

The Kitchen Display uses Tasks in a conventional manner, where you create a Task for “Make this Sandwich” and when you are finished making it, you “Mark the Sandwich Task” as “Completed”.

However, a Task can be anything you want it to be. It doesn’t need to “do something”; it is just a convenient Storage mechanism for more complex data sets that a Program Setting does not handle so well.

I also used Tasks for the Timeclock. The original way was to use EntityStateLogs since they could also handle more complex data sets. But that requires an Entity Type and Entity to use EntityStateLogs.

And again, I use Tasks for Timeclock Policies like storing Hour Limits for Overtime Rates, Holiday Dates for Double-Pay, etc.

I could use Program Settings for any of this, but then you would have a ton of Rows in the DB when you start storing Date-centric values because the Name of the Program Setting would need to include the Date. And there is no Reporting support for Program Settings either.

Using Tasks instead simplifies data storage, especially Date-centric things, and complex data sets, since it can store subsets of data in JSON format that you can naturally read with GraphQL and Custom Reports’ {REPORT TASK DETAILS:X}

I have been working on this for most of the day, setting up the JScript Functions using gql.Exec() and it looks (so far) that this is going to be easy and work very very well.


#5

I’m with you @pauln

It was only when I read the tutorial on keeping a list of cash drawer openings that I started to understand the true functionality! The name definitely through me at first!

Open Cash Drawer Report Log


#6

I have run into a bit of a snag. I has to do with Reporting and Date Ranges.

I was about to show screenshots of how the Task Data was stored and could be displayed in different ways, but it turns out {REPORT TASK DETAILS:X} is giving me trouble.

Here it is in the DB:

The CustomData (green) is JSON, and looks like this:

[{"N":"Count20","V":"6"},{"N":"Total","V":"210"},{"N":"Count1","V":"15"},{"N":"Count100","V":"0"},{"N":"Float","V":"200"},{"N":"Count5","V":"5"},{"N":"Balance","V":"10"},{"N":"Count50","V":"0"},{"N":"Count10","V":"5"},{"N":"Account","V":"10.00"},{"N":"PlusMinus","V":"0"}]

Here is the same Task Data in the GQL Modules Task Editor Module… again, the CustomData (green) is shown in an easy to read format:


I have a Report, for now, showing only Cash USD - it is showing me nothing right now, even though we have Task Data:

[CO Tasks:1,1, 1, 1, 1, 1, 1, 1, 1]
{REPORT TASK DETAILS:T.TaskType,T.Name,TSC.Count500,TSC.Count100,TSC.Count50,TSC.Count20,TSC.Count10,TSC.Count5,TSC.Count1:(TST=CO Cash USD)}

The problem is that the Workperiod was closed before the Tasks were created, and so the Task Dates are outside the Workperiod Range. That is, the Task Dates are “higher” than the Workperiod EndDate.

I have a way to get around it in the future by ensuring the Tasks are created soon after the Workperiod Starts, and from that point forward use updateTask() mutation instead of addTask(), which is what I should be doing anyway :stuck_out_tongue_winking_eye:

Nevertheless, I thought I would ask @emre if would be possible to “stretch” the Report Explorer End Date rather than limiting it to the Date/Time when the last Workperiod was closed.

Problem in Image:


#7

Did you tried entering time for start / end filters?


#8

Ok, cool, I thought we might be able to do that. Date with Time works! Thanks @emre!

The trick is that the End must not be in the future. If you try to use Date/Time beyond CURRENT Date/Time (ie “future”), then Report End will “snap” to last Workperiod End.


#9

#Task Types


#10

#Script

Name: CO Cashout Functions
Handler: co

###Script:###

var foreignCurrencyName = 'HNL'; // for Exchange Rate Task Type

var currencyFormat = '0.00'; // for Helper.ToNumber(num,format)

var nowDate = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff");

// Task Start/End Dates
var openDate  = getWorkPeriodData('start');
var closeDate = getWorkPeriodData('end');

// Task Default parameters
var userName = 'Admin';
var isCompleted = '';
var customData = [];
var content = '';
var state = '';

// Task Filter parameters
var startFilter = getWorkPeriodData('start');
var endFilter = getWorkPeriodData('end');

// gets Last Workperiod Data
function getWorkPeriodData(dataType) {
	var SQL = "SELECT [Id],convert(varchar(25),[StartDate],126),convert(varchar(25),[EndDate],126),[StartDescription],[EndDescription] FROM [WorkPeriods] WHERE 1=1 AND [Id] = (SELECT MAX([Id]) FROM [WorkPeriods])";
	var res = sql.Exec(SQL);
	var	wpdata = res[0].split(',');
	var retval = '';
	switch (dataType) {
		case 'id':
			retval = wpdata[0];
			break;
		case 'start':
			retval = wpdata[1].replace('T',' ');
			break;
		case 'end':
			retval = wpdata[2].replace('T',' ');
			break;
		case 'isOpen':
			retval = wpdata[1]==wpdata[2] ? true : false;
			break;
		case 'descStart':
			retval = wpdata[3];
			break;
		case 'descEnd':
			retval = wpdata[4];
			break;
		default:
			retval = wpdata[0];
			break;
	}
	return retval;
}

// gets Count or Total data for a Task
function getCount(tenderType,denom,ct,countDate) {
	// getCount('Cash HNL','100')
	// getCount('Cash HNL','100','countTotal')
	// getCount('Cash HNL','100','denomTotal')
	// getCount('Cash HNL','Float')
	// getCount('Cash HNL','Balance')
	
	countDate = typeof(countDate)==='undefined' || countDate=='' ?  openDate : countDate;
	denom = typeof(denom)==='undefined' || denom=='' ? 'tenderTotal' : denom;
	ct = typeof(ct)==='undefined' || ct=='' ? 'countTotal' : ct;
	
	var taskType = 'CO ' + tenderType;
	var taskName = tenderType + ' ' + countDate;
	
	var msg = '';

	// special Counts for Credit Cards
	var isCard = tenderType.indexOf('Card') > -1 ? true : false;
	//var isNeg = denom.indexOf('DEVO')>-1 || denom.indexOf('TIPS')>-1 ? true : false;
	var isDEVO = denom.indexOf('DEVO')>-1 ? true : false;
	
	// getTasks(taskType, completedFilter, nameLike, startFilter, endFilter, contentLike, fieldFilter, stateFilter, callback)
	var counts = gqlEXEC(getTasks(taskType,isCompleted,taskName));
	    //return counts;
	    counts = JSON.parse(counts);
	    //return counts.errors;
		if (counts.errors) {
		var parm = "tenderType:"+tenderType+", denom:"+denom+", ct:"+ct;
			throwError('getCount()',taskType,taskName,'',parm,true)
			//dlg.ShowMessage(msg);
			return -1;
		}
	    counts = counts.data.tasks;
	    
	var denomTotal = 0;
	var tenderTotal = 0;
	var floatTotal = 0;
	var retVal = -1;
	
	var taskCount = counts.length;

	if (taskCount==0) {
			//msg = 'getCount() WARNING !!!\r\n\r\n';
			//msg+= 'No value found for Denom ['+denom+'] of Task Type ['+taskType+'] with Task Name ['+taskName+']';
			var parm = "tenderType:"+tenderType+", denom:"+denom+", ct:"+ct;
			throwError('getCount()',taskType,taskName,'',parm,true)
			//dlg.ShowMessage(msg);
			//return -1;
	}
	
	for (var c=0; c<taskCount; c++) {
		var countFields = counts[c].customData;
		var fieldCount = countFields.length;
		for (var f=0; f<fieldCount; f++) {
			if (countFields[f].name.indexOf('Count') > -1) {
				var denomName = countFields[f].name.substr(5,5);
				var denomCount = countFields[f].value;

				if (!parseInt(denomName)) {
					denomTotal = Number(denomCount);
				} else {
					denomTotal = Number(denomName) * Number(denomCount);
				}
				
				//isNeg = countFields[f].name.indexOf('DEVO') > -1 || countFields[f].name.indexOf('TIPS') > -1 ? true : false;
				isDEVO = countFields[f].name.indexOf('DEVO') > -1 ? true : false;
				isTIPS = countFields[f].name.indexOf('TIPS') > -1 ? true : false;
				
				if (isDEVO) {
					floatTotal += denomTotal;
				} else if (isTIPS) {
					tenderTotal += 0;
				} else {
					tenderTotal += denomTotal;
				}
				
				if (denom==denomName) {
					if (ct=='countTotal') {
						retVal = denomCount;
					} else {
						retVal = Helper.Format(denomTotal,currencyFormat);
					}
				}
			} else if (countFields[f].name.indexOf('Float') > -1 && denom=='Float') {
				retVal = Helper.Format(countFields[f].value,currencyFormat);
			} else if (countFields[f].name.indexOf('Balance') > -1 && denom=='Balance') {
				retVal = Helper.Format(countFields[f].value,currencyFormat);
			} else if (countFields[f].name.indexOf('Account') > -1 && denom=='Account') {
				retVal = Helper.Format(countFields[f].value,currencyFormat);
			} else if (countFields[f].name.indexOf('PlusMinus') > -1 && denom=='PlusMinus') {
				retVal = Helper.Format(countFields[f].value,currencyFormat);
			}
		}
	}
	
	if (denom=='Float' && isCard) {
		retVal = Helper.Format(floatTotal,currencyFormat);
	}

	if (denom=='tenderTotal') {
		retVal = Helper.Format(tenderTotal,currencyFormat);
	}

	if (retVal==-1) {
			//msg = 'getCount() WARNING !!!\r\n\r\n';
			//msg+= 'No value found for Denom ['+denom+'] of Task Type ['+taskType+'] with Task Name ['+taskName+']';
			var parm = "tenderType:"+tenderType+", denom:"+denom+", ct:"+ct;
			//throwError('getCount()',taskType,taskName,'',parm,true)
			//dlg.ShowMessage(msg);
			//return -1;
			
			retVal = ct=='countTotal' ? 0 : Helper.Format(0,currencyFormat);
	}

	return retVal;
}

// sets Count or Total data for a Task
function setCount(tenderType,countName,countValue,countDate){
	// setCount('Cash HNL','100','5')
	// setCount('Cash HNL','Float','2500')
	// setCount('Cash HNL','Account','{ACCOUNT TOTAL:Cash HNL}')
	// setCount('Cash HNL','PlusMinus','0')
	// setCount('Cash USD','20','6')
	// setCount('Cash USD','Account','10')
	// setCount('Card USD','VISA','100')
	
	openDate  = getWorkPeriodData('start');

	countName = countName=='Total' || countName=='Float' || countName=='Balance' || countName=='Account' || countName=='PlusMinus' ? countName : 'Count'+countName;
	
	countValue = typeof(countValue)==='undefined' || countValue=='' ?  '0' : countValue;
	countValue = tenderType.indexOf('Card') > -1 || countName.indexOf('Float') > -1 ? Helper.Format(countValue,currencyFormat) : countValue;

	countDate = typeof(countDate)==='undefined' || countDate=='' ?  openDate : countDate;
	
	var isCard = tenderType.indexOf('Card') > -1 ? true : false;
	
	var msg = '';
	
	msg+='setCount()';
	msg+="\r\ntenderType:"+tenderType;
	msg+="\r\ncountName:"+countName;
	msg+="\r\ncountValue:"+countValue;
	//dlg.ShowMessage(msg);
	
	var ident = tenderType + '_' + countDate;
	var taskType = 'CO ' + tenderType;
	var taskName = tenderType + ' ' + countDate;
	
	var isCompleted = '';
	var userName = 'Admin';
	var content = '';
	var state = '';
	
	var customData = [];
		customData.push({name:"Id",value:ident});
		customData.push({name:countName,value:countValue});

	var startFilter = getWorkPeriodData('start');
	var endFilter = getWorkPeriodData('end');

	// getTasks(taskType, completedFilter, nameLike, startFilter, endFilter, contentLike, fieldFilter, stateFilter, callback)
	var tasks = gqlEXEC(getTasks(taskType,isCompleted,taskName));
		//return tasks;
		tasks = JSON.parse(tasks);
		//return tasks.errors[0].message;
	var taskExists = tasks.errors ? false : true;//tasks.data.tasks.length > 0 ? true : false;
	//return taskExists;
	
	if (!taskExists) {
		var parm = "tenderType:"+tenderType+", countName:"+countName+", countValue:"+countValue;
		throwError('setCount()',taskType,taskName,'',parm,true)

		return -1;
	} else {
		var counts = gqlEXEC(updateTaskByIdentifier([taskType], [ident], isCompleted, taskName, customData, content, state));
	}
	//return counts;

	var tenderFloat   = Number(getTotal(tenderType,'Float').replace(',',''));
	var tenderAccount = Number(getTotal(tenderType,'Account').replace(',',''));
	var tenderTotal   = Number(getTotal(tenderType).replace(',',''));
	//return tenderTotal;
	
	if (isCard) {
		var DEVO = Number(getTotal(tenderType,'DEVO').replace(',',''));
		var TIPS = Number(getTotal(tenderType,'TIPS').replace(',',''));
		//tenderFloat = DEVO + TIPS;
		tenderFloat = (-1 * DEVO); // this is NOT really a Float, but a value that is removed from the CC Close Report, so we add it back in by negating it
	}
	
	if (tenderTotal==-1) {
		var parm = "tenderType:"+tenderType+", countName:"+countName+", countValue:"+countValue;
		throwError('setCount()',taskType,taskName,taskIdent,parm,true)
		return -1;
	}
	//return tenderTotal;
	
	customData.push({name:"Total",value:Helper.Format(tenderTotal,currencyFormat)});

	var tenderBalance = tenderTotal - tenderFloat;
	customData.push({name:"Balance",value:Helper.Format(tenderBalance,currencyFormat)});

	var tenderPlusMinus = tenderBalance - tenderAccount;
	customData.push({name:"PlusMinus",value:Helper.Format(tenderPlusMinus,currencyFormat)});

	//dlg.AskQuestion(updateTaskByIdentifier([taskType], [ident], isCompleted, taskName, customData, content, state),"Ok");
	var upd = gqlEXEC(updateTaskByIdentifier([taskType], [ident], isCompleted, taskName, customData, content, state));
	//return upd;
	
	return tenderTotal;
}

// gets Total data for a Task via getCount()
function getTotal(tenderType,countName,countDate) {
	// getTotal('Card HNL')
	// getTotal('Card HNL','AMEX')
	// getTotal('Cash HNL')
	// getTotal('Cash HNL','100')

	countDate = typeof(countDate)==='undefined' || countDate=='' ?  openDate : countDate;
	
	var total = getCount(tenderType,countName,'denomTotal',countDate);
	
	return Helper.Format(total,currencyFormat);
}

// initializes all Count and Total data to 0 for Tasks
function initCounts() {
	var cashAccounts = ['Cash USD','Cash HNL'];
	var cashDenoms   = [1000,500,100,50,20,10,5,2,1];
	
	for (var a=0; a < cashAccounts.length; a++) {
		for (var d=0; d < cashDenoms.length; d++) {
			setCount(cashAccounts[a],cashDenoms[d],0);
		}
		setCount(cashAccounts[a],'Float',0.00);
		setCount(cashAccounts[a],'Total',0.00);
		setCount(cashAccounts[a],'Balance',0.00);
		setCount(cashAccounts[a],'Account',0.00);
		setCount(cashAccounts[a],'PlusMinus',0.00);
	}
	setCount('Cash USD','Float',200.00);
	setCount('Cash HNL','Float',2500.00);
	
	var cardAccounts = ['Card USD','Card HNL'];
	var cardTypes    = ['AMEX','DISC','MAST','VISA','OTHR'];

	for (var a=0; a < cardAccounts.length; a++) {
		for (var d=0; d<cardTypes.length; d++) {
			setCount(cardAccounts[a],cardTypes[d],0);
		}
		setCount(cardAccounts[a],'Total',0.00);
		setCount(cardAccounts[a],'Account',0.00);
		setCount(cardAccounts[a],'PlusMinus',0.00);
	}
	
	return 0;
}

// starts (adds) a Count Task
function openCounts(countDate) {
	// create the Tasks
	openDate  = getWorkPeriodData('start');

	countDate = typeof(countDate)==='undefined' || countDate=='' ?  openDate : countDate;

	var accounts = ['Cash USD','Cash HNL','Card USD','Card HNL'];
	
	for (var a=0; a<accounts.length; a++) {
		var taskType = 'CO ' + accounts[a];
		var taskName = accounts[a] + ' ' + countDate;
		var ident    = accounts[a] + '_' + countDate;
		customData   = [{name:"Id",value:ident}];
		isCompleted  = 'false';

		var counts = gqlEXEC(addTasks([taskType],[taskName],isCompleted,customData,userName));
	}

	var xr = openXR();
	var wp = openWorkperiod();
	
	return 0;
}

// ends (completes) Count Tasks
function closeCounts(countDate) {
	// Complete the Tasks
	openDate  = getWorkPeriodData('start');

	countDate = typeof(countDate)==='undefined' || countDate=='' ?  openDate : countDate;

	var accounts = ['Cash USD','Cash HNL','Card USD','Card HNL'];
	
	for (var a=0; a<accounts.length; a++) {
		var taskType = 'CO ' + accounts[a];
		var taskName = accounts[a] + ' ' + countDate;
		var ident    = accounts[a] + '_' + countDate;
		customData   = [{name:"Id",value:ident}];
		isCompleted  = 'true';

		var counts = gqlEXEC(updateTaskByIdentifier([taskType], [ident], isCompleted, taskName, customData));
	}

	var xr = closeXR();
	var wp = closeWorkperiod();
	
	return 0;
}

// starts (adds) a Workperiod Task
function openWorkperiod(countDate) {
	// create the Tasks
	openDate  = getWorkPeriodData('start');

	countDate = typeof(countDate)==='undefined' || countDate=='' ?  openDate : countDate;

	var wpId      = getWorkPeriodData('id');
	var isOpen    = getWorkPeriodData('isOpen');
	var dateStart = getWorkPeriodData('start');
	var dateEnd   = getWorkPeriodData('end');
	var descStart = getWorkPeriodData('descStart');
	var descEnd   = getWorkPeriodData('descEnd');

	var taskType = 'Workperiod';
	var taskName = taskType + ' ' + countDate;
	var ident    = taskType + '_' + countDate;
	var isCompleted  = 'false';
	var customData = [];
		customData.push({name:"Id",value:ident});
		customData.push({name:"id",value:wpId});
		customData.push({name:"isOpen",value:isOpen});
		customData.push({name:"dateStart",value:dateStart});
		customData.push({name:"dateEnd",value:dateEnd});
		customData.push({name:"descStart",value:descStart});
		customData.push({name:"descEnd",value:descEnd});

	var counts = gqlEXEC(addTasks([taskType],[taskName],isCompleted,customData,userName));

	return 0;
}

// ends (completes) Workperiod Tasks
function closeWorkperiod(countDate) {
	// Complete the Tasks
	openDate  = getWorkPeriodData('start');

	countDate = typeof(countDate)==='undefined' || countDate=='' ?  openDate : countDate;

	var wpId      = getWorkPeriodData('id');
	var isOpen    = getWorkPeriodData('isOpen');
	var dateStart = getWorkPeriodData('start');
	var dateEnd   = getWorkPeriodData('end');
	var descStart = getWorkPeriodData('descStart');
	var descEnd   = getWorkPeriodData('descEnd');

	var taskType = 'Workperiod';
	var taskName = taskType + ' ' + countDate;
	var ident    = taskType + '_' + countDate;
	var isCompleted  = 'true';
	var customData = [];
		customData.push({name:"Id",value:ident});
		customData.push({name:"id",value:wpId});
		customData.push({name:"isOpen",value:isOpen});
		customData.push({name:"dateStart",value:dateStart});
		customData.push({name:"dateEnd",value:dateEnd});
		customData.push({name:"descStart",value:descStart});
		customData.push({name:"descEnd",value:descEnd});

	var counts = gqlEXEC(updateTaskByIdentifier([taskType], [ident], isCompleted, taskName, customData));

	return 0;
}

// starts (adds) Exchange Rate Task
function openXR(currencyName,countDate) {
	// create the Tasks
	openDate  = getWorkPeriodData('start');

	countDate = typeof(countDate)==='undefined' || countDate=='' ?  openDate : countDate;

	currencyName = typeof(currencyName)==='undefined' || currencyName=='' ? foreignCurrencyName : currencyName;
	
	var SQL = "SELECT [Id],[Name],[ExchangeRate],[InverseExchangeRate],[Rounding],[CurrencySymbol] FROM [ForeignCurrencies] WHERE [Name]='"+currencyName+"'";
	var res = sql.Exec(SQL);
	var	xrdata = res[0].split(',');
	
	var rateName = xrdata[1];
	var rate    = xrdata[2];
	var rateInv = 1/rate;
	var rateIsInverted = xrdata[3];
	
	var taskType = 'Exchange Rate';
	var taskName = taskType + ' ' + currencyName + ' ' + countDate;
	var ident    = taskType + '_' + currencyName + '_' + countDate;
	isCompleted  = 'false';
	customData   = [];
	customData.push({name:"Id",value:ident});
	customData.push({name:"rateName",value:rateName});
	customData.push({name:"rate",value:rate});
	customData.push({name:"rateInv",value:rateInv});
	customData.push({name:"rateIsInverted",value:rateIsInverted});
	customData.push({name:"rateDate",value:countDate});

	var xr = gqlEXEC(addTasks([taskType],[taskName],isCompleted,customData,userName));
	
	return 0;
}

// ends (completes) Exchange Rate Task
function closeXR(currencyName,countDate) {
	// Complete the Task
	openDate  = getWorkPeriodData('start');

	countDate = typeof(countDate)==='undefined' || countDate=='' ?  openDate : countDate;

	currencyName = typeof(currencyName)==='undefined' || currencyName=='' ? foreignCurrencyName : currencyName;

	var SQL = "SELECT [Id],[Name],[ExchangeRate],[InverseExchangeRate],[Rounding],[CurrencySymbol] FROM [ForeignCurrencies] WHERE [Name]='"+currencyName+"'";
	var res = sql.Exec(SQL);
	var	xrdata = res[0].split(',');
	
	var rateName = xrdata[1];
	var rate    = xrdata[2];
	var rateInv = 1/rate;
	var rateIsInverted = xrdata[3];
	
	var taskType = 'Exchange Rate';
	var taskName = taskType + ' ' + currencyName + ' ' + countDate;
	var ident    = taskType + '_' + currencyName + '_' + countDate;
	isCompleted  = 'true';
	customData   = [];
	customData.push({name:"Id",value:ident});
	customData.push({name:"rateName",value:rateName});
	customData.push({name:"rate",value:rate});
	customData.push({name:"rateInv",value:rateInv});
	customData.push({name:"rateIsInverted",value:rateIsInverted});
	customData.push({name:"rateDate",value:countDate});

	var xr = gqlEXEC(updateTaskByIdentifier([taskType], [ident], isCompleted, taskName, customData));
	
	return 0;
}

// updates Exchange Rate Task
function setXR(currencyName,countDate) {
	// Update the Task
	openDate  = getWorkPeriodData('start');

	countDate = typeof(countDate)==='undefined' || countDate=='' ?  openDate : countDate;

	currencyName = typeof(currencyName)==='undefined' || currencyName=='' ? foreignCurrencyName : currencyName;

	var SQL = "SELECT [Id],[Name],[ExchangeRate],[InverseExchangeRate],[Rounding],[CurrencySymbol] FROM [ForeignCurrencies] WHERE [Name]='"+currencyName+"'";
	var res = sql.Exec(SQL);
	var	xrdata = res[0].split(',');
	
	var rateName = xrdata[1];
	var rate    = xrdata[2];
	var rateInv = 1/rate;
	var rateIsInverted = xrdata[3];
	
	var taskType = 'Exchange Rate';
	var taskName = taskType + ' ' + currencyName + ' ' + countDate;
	var ident    = taskType + '_' + currencyName + '_' + countDate;
	isCompleted  = '';
	customData   = [];
	customData.push({name:"Id",value:ident});
	customData.push({name:"rateName",value:rateName});
	customData.push({name:"rate",value:rate});
	customData.push({name:"rateInv",value:rateInv});
	customData.push({name:"rateInv",value:rateInv});
	customData.push({name:"rateIsInverted",value:rateIsInverted});
	customData.push({name:"rateDate",value:countDate});

	var xr = gqlEXEC(updateTaskByIdentifier([taskType], [ident], isCompleted, taskName, customData));
	
	return 0;
}



function throwError(func,taskType,taskName,taskIdent,parm,halt) {
	func = typeof(func)==='undefined' || func=='' ? 'unknown' : func;
	taskType = typeof(taskType)==='undefined' || taskType=='' ? 'unknown' : taskType;
	taskName = typeof(taskName)==='undefined' || taskName=='' ? 'unknown' : taskName;
	taskIdent = typeof(taskIdent)==='undefined' || taskIdent=='' ? 'unknown' : taskIdent;
	parm = typeof(parm)==='undefined' || parm=='' ? 'unknown' : parm;
	halt = typeof(halt)==='undefined' || halt=='' ? true : halt;

	var errmsg = 'ERROR in '+func;
	errmsg += "\r\n"+'taskType: '+taskType;
	errmsg += "\r\n"+'taskName: '+taskName;
	errmsg += "\r\n"+'taskIdent: '+taskIdent;
	errmsg += "\r\n"+'parm: '+parm;
	errmsg += "\r\n"+'halt: '+halt;
	errmsg += '';
	
	dlg.AskQuestion(errmsg,"Ok");
}




// main GraphQL Execute Function
function gqlEXEC(query, callback) {
	//return query;
    var data = gql.Exec(query);  // returns JSON as String
    var dobj = JSON.parse(data); // converts JSON String to Object
    return data;
};

// Query for addTasks
function addTasks(taskTypes,taskNames,isCompleted,customData,userName,content,state) {
    var q = '';
        q+= 'mutation m{';
        for (var t=0; t<taskNames.length; t++) {
            var taskType = taskTypes[t];
            var taskName = taskNames[t];
            q += 'm'+t+': ';
            q+= 'addTask(';
            q+= 'task:{';
            q+= 'taskType:"'+taskType+'"';
            q+= ',name:"'+taskName+'"';
            q+= ',isCompleted:'+isCompleted;
            q+= ',userName:"'+userName+'"';
            q+= typeof(content)==='undefined' ? '' : ',content:' + '"'+content+'"';
            q+= typeof(state)==='undefined' ? '' : ',state:' + '"'+state+'"';
            q+= ',customData:[';
            if (customData) {
                for (var d=0; d<customData.length; d++) {
                    q+= (d==0 ? '' : ',');
                    q+= '{name:"'+customData[d].name+'",value:"'+customData[d].value+'"}';
                }
            }
            q+= ']';
            q+= '}';
            q+= ')';
            q+= '{id,name,identifier,content,isCompleted,userName,customData{name,value}}';
            q += ((t+1) != taskNames.length ? ', ' : '');
        }
        q+= '}';
    return q;
};

// Query for getTasks
function getTasks(taskType, completedFilter, nameLike, startFilter, endFilter, contentLike, fieldFilter, stateFilter, callback) {
    var q = '';
        q+= '{tasks:getTasks(';
        q+= 'taskType:"'+taskType+'"';
        q+= (startFilter ? ',startDate:"'+startFilter+'"' : '');
        q+= (endFilter ? ',endDate:"'+endFilter+'"' : '');
        q+= (completedFilter!='' ? ',isCompleted:'+completedFilter : '');
        q+= (nameLike ? ',nameLike:"'+nameLike+'"' : '');
        q+= (contentLike ? ',contentLike:"'+contentLike+'"' : '');
        q+= (stateFilter ? ',state:"'+stateFilter+'"' : '');
        q+= (fieldFilter ? ',customFields:[{name:"'+fieldFilter.name+'",value:"'+fieldFilter.value+'"}]' : '');
        q+= ')';
        q+= '{id,isCompleted,identifier,name,state,content,contentText,customData{name,value},stateLog{state,start,end},stateDuration{state,duration},startDate,endDate,userName}';
        q+= '}';
    return q;
};

// Query for updateTask (by identifier and taskType)
function updateTaskByIdentifier(taskTypes, taskIdents, isCompleted, taskName, customData, content, state){
    var q = 'mutation m {';
    for (var t=0; t<taskIdents.length; t++) {
        var taskIdent = taskIdents[t];
        var taskType = taskTypes[t];
        q += 'm'+t+': updateTask(';
        q += 'identifier:"'+taskIdent+'"';
        q += ', taskType:"'+taskType+'"';
        q += ', task:{';
        q += 'taskType:"'+taskType+'"';
        q += (isCompleted!='' ? ',isCompleted:'+isCompleted : '');
        q += (taskName ? ', name:"'+taskName+'"' : '');
        q += content ? ',content:"'+content+'"' : '';
        q += state ? ',state:"'+state+'"' : '';
        q += ',customData:[';
        if (customData) {
            for (var d=0; d<customData.length; d++) {
                q+= (d==0 ? '' : ',');
                q+= '{name:"'+customData[d].name+'",value:"'+customData[d].value+'"}';
            }
        }
        q+= ']';
        q += '}';
        q += ')';
        q+= '{id,isCompleted,identifier,name,state,content,contentText,customData{name,value},stateLog{state,start,end},stateDuration{state,duration},startDate,endDate,userName}';
        //q += '}';
        q += ((t+1) != taskIdents.length ? ', ' : '');

    }
    	q += '}';
    return q;
};

#11

#Actions


#12

#Rules


#13

#Reports


##CO Cashout Count Report [0] (Report)##

Report Name: CO Cashout Count Report
Page Size: 13cm
Display in Report Explorer: checked
Visual Printing: unchecked

Template:

[Cashout Count Report:1, 1, 1, 1, 1]
WP {REPORT TASK DETAILS:TSC.id:(TST=Workperiod)}\r[='{REPORT TASK DETAILS:TSC.isOpen:(TST=Workperiod)}'=='true' ? 'OPEN' : 'CLOSED']|[=FD('{REPORT TASK DETAILS:TSC.dateStart:(TST=Workperiod)}','yyyy-MM-dd')]|[=FD('{REPORT TASK DETAILS:TSC.dateStart:(TST=Workperiod)}','HH:mm')]|[=FD('{REPORT TASK DETAILS:TSC.dateEnd:(TST=Workperiod)}','yyyy-MM-dd')]|[=FD('{REPORT TASK DETAILS:TSC.dateEnd:(TST=Workperiod)}','HH:mm')]

>>CASH|Count|(-Float)|Account|+/-
HNL|[=F(TN('{REPORT TASK DETAILS:TSC.Total.Sum:(TST=CO Cash HNL)}'),'0.00')]|[=F(TN('{REPORT TASK DETAILS:TSC.Total.Sum:(TST=CO Cash HNL)}')-TN('{REPORT TASK DETAILS:TSC.Float.Sum:(TST=CO Cash HNL)}'),'0.00')]|[=F(TN('{ACCOUNT TOTAL:Cash HNL}')*TN('{REPORT TASK DETAILS:TSC.rate.Average:(TST=Exchange Rate)}'),'0.00')]|[=F(TN('{REPORT TASK DETAILS:TSC.Total.Sum:(TST=CO Cash HNL)}')-TN('{REPORT TASK DETAILS:TSC.Float.Sum:(TST=CO Cash HNL)}')-(TN('{ACCOUNT TOTAL:Cash HNL}')*TN('{REPORT TASK DETAILS:TSC.rate.Average:(TST=Exchange Rate)}')),'0.00')]
USD|[=F(TN('{REPORT TASK DETAILS:TSC.Total.Sum:(TST=CO Cash USD)}'),'0.00')]|[=F(TN('{REPORT TASK DETAILS:TSC.Total.Sum:(TST=CO Cash USD)}')-TN('{REPORT TASK DETAILS:TSC.Float.Sum:(TST=CO Cash USD)}'),'0.00')]|[=F(TN('{ACCOUNT TOTAL:Cash USD}'),'0.00')]|[=F(TN('{REPORT TASK DETAILS:TSC.Total.Sum:(TST=CO Cash USD)}')-TN('{REPORT TASK DETAILS:TSC.Float.Sum:(TST=CO Cash USD)}')-TN('{ACCOUNT TOTAL:Cash USD}'),'0.00')]

>>CC|Count|(+Devo)|Account|+/-
CC HNL|[=F(TN('{REPORT TASK DETAILS:TSC.Total.Sum:(TST=CO Card HNL)}'),'0.00')]|[=F(TN('{REPORT TASK DETAILS:TSC.Total.Sum:(TST=CO Card HNL)}')+TN('{REPORT TASK DETAILS:TSC.CountDEVO.Sum:(TST=CO Card HNL)}'),'0.00')]|[=F(TN('{ACCOUNT TOTAL:Credit Card HNL}')*TN('{REPORT TASK DETAILS:TSC.rate.Average:(TST=Exchange Rate)}'),'0.00')]|[=F(TN('{REPORT TASK DETAILS:TSC.Total.Sum:(TST=CO Card HNL)}')+TN('{REPORT TASK DETAILS:TSC.CountDEVO.Sum:(TST=CO Card HNL)}')-(TN('{ACCOUNT TOTAL:Credit Card HNL}')*TN('{REPORT TASK DETAILS:TSC.rate.Average:(TST=Exchange Rate)}')),'0.00')]
CC USD|[=F(TN('{REPORT TASK DETAILS:TSC.Total.Sum:(TST=CO Card USD)}'),'0.00')]|-|[=F(TN('{ACCOUNT TOTAL:Credit Card USD}'),'0.00')]|[=F(TN('{REPORT TASK DETAILS:TSC.Total.Sum:(TST=CO Card USD)}')-TN('{ACCOUNT TOTAL:Credit Card USD}'),'0.00')]

>>CC Tips|Count|Paid|Account|+/-
HNL|[=F(TN('{REPORT TASK DETAILS:TSC.CountTIPS.Sum:(TST=CO Card HNL)}') + (TN('{REPORT TASK DETAILS:TSC.CountTIPS.Sum:(TST=CO Card USD)}')*TN('{REPORT TASK DETAILS:TSC.rate.Average:(TST=Exchange Rate)}')),'0.00')]|[=F(TN('{ACCOUNT DEBIT TOTAL:Tips}')*TN('{REPORT TASK DETAILS:TSC.rate.Average:(TST=Exchange Rate)}'),'0.00')]|[=F(TN('{ACCOUNT TOTAL:Tips}')*TN('{REPORT TASK DETAILS:TSC.rate.Average:(TST=Exchange Rate)}'),'0.00')]|[=F((TN('{ACCOUNT CREDIT TOTAL:Tips}')-TN('{ACCOUNT DEBIT TOTAL:Tips}'))*TN('{REPORT TASK DETAILS:TSC.rate.Average:(TST=Exchange Rate)}'),'0.00')]

>>Account|HNL|USD|-|TTL USD
Round|[=F(TN('{ACCOUNT TOTAL:Rounding HNL}'))]|[=F(TN('{ACCOUNT TOTAL:Rounding USD}'))]|-|[=F(TN('{ACCOUNT TOTAL:Rounding USD}')+TN('{ACCOUNT TOTAL:Rounding HNL}'))]
XR|[=F(TN('{REPORT TASK DETAILS:TSC.rate.Average:(TST=Exchange Rate)}'),'0.00')]|[=F(TN('{REPORT TASK DETAILS:TSC.rateInv.Average:(TST=Exchange Rate)}'),'0.000000')]|-|-

>>TOTALS|Count|(-Float)|Account|+/-
HNL|[=F(TN('{REPORT TASK DETAILS:TSC.Total.Sum:(TST=CO Cash HNL)}')+TN('{REPORT TASK DETAILS:TSC.Total.Sum:(TST=CO Card HNL)}')+TN('{REPORT TASK DETAILS:TSC.CountDEVO.Sum:(TST=CO Card HNL)}')+TN('{REPORT TASK DETAILS:TSC.Total.Sum:(TST=CO Card USD)}')*TN('{REPORT TASK DETAILS:TSC.rate.Average:(TST=Exchange Rate)}')+TN('{REPORT TASK DETAILS:TSC.Total.Sum:(TST=CO Cash USD)}')*TN('{REPORT TASK DETAILS:TSC.rate.Average:(TST=Exchange Rate)}'),'0.00')]|[=F( TN('{REPORT TASK DETAILS:TSC.Total.Sum:(TST=CO Cash HNL)}')-TN('{REPORT TASK DETAILS:TSC.Float.Sum:(TST=CO Cash HNL)}') + TN('{REPORT TASK DETAILS:TSC.Total.Sum:(TST=CO Cash USD)}')*TN('{REPORT TASK DETAILS:TSC.rate.Average:(TST=Exchange Rate)}')-TN('{REPORT TASK DETAILS:TSC.Float.Sum:(TST=CO Cash USD)}')*TN('{REPORT TASK DETAILS:TSC.rate.Average:(TST=Exchange Rate)}') + TN('{REPORT TASK DETAILS:TSC.Total.Sum:(TST=CO Card HNL)}') + TN('{REPORT TASK DETAILS:TSC.CountDEVO.Sum:(TST=CO Card HNL)}') + TN('{REPORT TASK DETAILS:TSC.Total.Sum:(TST=CO Card USD)}')*TN('{REPORT TASK DETAILS:TSC.rate.Average:(TST=Exchange Rate)}'),'0.00')]|[=F((TN('{ACCOUNT TOTAL:Cash HNL}')+TN('{ACCOUNT TOTAL:Cash USD}')+TN('{ACCOUNT TOTAL:Credit Card HNL}')+TN('{ACCOUNT TOTAL:Credit Card USD}')+TN('{ACCOUNT TOTAL:Tips}'))*TN('{REPORT TASK DETAILS:TSC.rate.Average:(TST=Exchange Rate)}'),'0.00')]|[=F(TN('{REPORT TASK DETAILS:TSC.Total.Sum:(TST=CO Cash HNL)}')-TN('{REPORT TASK DETAILS:TSC.Float.Sum:(TST=CO Cash HNL)}') + TN('{REPORT TASK DETAILS:TSC.Total.Sum:(TST=CO Cash USD)}')*TN('{REPORT TASK DETAILS:TSC.rate.Average:(TST=Exchange Rate)}')-TN('{REPORT TASK DETAILS:TSC.Float.Sum:(TST=CO Cash USD)}')*TN('{REPORT TASK DETAILS:TSC.rate.Average:(TST=Exchange Rate)}') + TN('{REPORT TASK DETAILS:TSC.Total.Sum:(TST=CO Card HNL)}') + TN('{REPORT TASK DETAILS:TSC.CountDEVO.Sum:(TST=CO Card HNL)}') + TN('{REPORT TASK DETAILS:TSC.Total.Sum:(TST=CO Card USD)}')*TN('{REPORT TASK DETAILS:TSC.rate.Average:(TST=Exchange Rate)}') - ((TN('{ACCOUNT TOTAL:Cash HNL}')+TN('{ACCOUNT TOTAL:Cash USD}')+TN('{ACCOUNT TOTAL:Credit Card HNL}')+TN('{ACCOUNT TOTAL:Credit Card USD}')+TN('{ACCOUNT TOTAL:Tips}')))*TN('{REPORT TASK DETAILS:TSC.rate.Average:(TST=Exchange Rate)}'),'0.00')]
USD|[=F(((TN('{REPORT TASK DETAILS:TSC.Total.Sum:(TST=CO Cash HNL)}')+TN('{REPORT TASK DETAILS:TSC.Total.Sum:(TST=CO Card HNL)}'))/TN('{REPORT TASK DETAILS:TSC.rate.Average:(TST=Exchange Rate)}'))+(TN('{REPORT TASK DETAILS:TSC.CountDEVO.Sum:(TST=CO Card HNL)}')/TN('{REPORT TASK DETAILS:TSC.rate.Average:(TST=Exchange Rate)}'))+TN('{REPORT TASK DETAILS:TSC.Total.Sum:(TST=CO Card USD)}')+TN('{REPORT TASK DETAILS:TSC.Total.Sum:(TST=CO Cash USD)}'),'0.00')]|[=F( ((TN('{REPORT TASK DETAILS:TSC.Total.Sum:(TST=CO Cash HNL)}')-TN('{REPORT TASK DETAILS:TSC.Float.Sum:(TST=CO Cash HNL)}'))/TN('{REPORT TASK DETAILS:TSC.rate.Average:(TST=Exchange Rate)}')) + TN('{REPORT TASK DETAILS:TSC.Total.Sum:(TST=CO Cash USD)}')-TN('{REPORT TASK DETAILS:TSC.Float.Sum:(TST=CO Cash USD)}') + (TN('{REPORT TASK DETAILS:TSC.Total.Sum:(TST=CO Card HNL)}')/TN('{REPORT TASK DETAILS:TSC.rate.Average:(TST=Exchange Rate)}')+(TN('{REPORT TASK DETAILS:TSC.CountDEVO.Sum:(TST=CO Card HNL)}')/TN('{REPORT TASK DETAILS:TSC.rate.Average:(TST=Exchange Rate)}'))) + TN('{REPORT TASK DETAILS:TSC.Total.Sum:(TST=CO Card USD)}'),'0.00')]|[=F(TN('{ACCOUNT TOTAL:Cash HNL}')+TN('{ACCOUNT TOTAL:Cash USD}')+TN('{ACCOUNT TOTAL:Credit Card HNL}')+TN('{ACCOUNT TOTAL:Credit Card USD}')+TN('{ACCOUNT TOTAL:Tips}'),'0.00')]|[=F(TN('{REPORT TASK DETAILS:TSC.Total.Sum:(TST=CO Cash HNL)}')/TN('{REPORT TASK DETAILS:TSC.rate.Average:(TST=Exchange Rate)}')-TN('{REPORT TASK DETAILS:TSC.Float.Sum:(TST=CO Cash HNL)}')/TN('{REPORT TASK DETAILS:TSC.rate.Average:(TST=Exchange Rate)}') + TN('{REPORT TASK DETAILS:TSC.Total.Sum:(TST=CO Cash USD)}')-TN('{REPORT TASK DETAILS:TSC.Float.Sum:(TST=CO Cash USD)}') + TN('{REPORT TASK DETAILS:TSC.Total.Sum:(TST=CO Card HNL)}')/TN('{REPORT TASK DETAILS:TSC.rate.Average:(TST=Exchange Rate)}') +TN('{REPORT TASK DETAILS:TSC.CountDEVO.Sum:(TST=CO Card HNL)}')/TN('{REPORT TASK DETAILS:TSC.rate.Average:(TST=Exchange Rate)}') + TN('{REPORT TASK DETAILS:TSC.Total.Sum:(TST=CO Card USD)}') - (TN('{ACCOUNT TOTAL:Cash HNL}')+TN('{ACCOUNT TOTAL:Cash USD}')+TN('{ACCOUNT TOTAL:Credit Card HNL}')+TN('{ACCOUNT TOTAL:Credit Card USD}')+TN('{ACCOUNT TOTAL:Tips}')),'0.00')]


##CO Cashout Count Tasks [0] (Report)##

Report Name: CO Cashout Count Tasks
Page Size: 20cm
Display in Report Explorer: checked
Visual Printing: unchecked

Template:

[CO Tasks:1,2, 1, 1, 1, 1, 1, 1, 1, 1]
>>Type|Name|id|isOpen|start|end|descS|descE
{REPORT TASK DETAILS:T.TaskType,T.Name,TSC.id,TSC.isOpen,TSC.dateStart,TSC.dateEnd,TSC.descStart,TSC.descEnd:(TST=Workperiod)}

@Cash USD,Cash HNL
>>Type|Name|500|100|50|20|10|5|1|TTL
{REPORT TASK DETAILS:T.TaskType,T.Name,TSC.Count500,TSC.Count100,TSC.Count50,TSC.Count20,TSC.Count10,TSC.Count5,TSC.Count1,TSC.Count2:(TST=CO $1)}
> |TTL AMOUNT:|{CALL:co.getTotal('$1','500')}|{CALL:co.getTotal('$1','100')}|{CALL:co.getTotal('$1','50')}|{CALL:co.getTotal('$1','20')}|{CALL:co.getTotal('$1','10')}|{CALL:co.getTotal('$1','5')}|{CALL:co.getTotal('$1','1')}|{REPORT TASK DETAILS:TSC.Total:(TST=CO $1)}

>>Type|Name|AMEX|DISC|MAST|VISA|OTHR|DEVO|TIPS|TTL
{REPORT TASK DETAILS:T.TaskType,T.Name,TSC.CountAMEX;0.00;0.00,TSC.CountDISC,TSC.CountMAST,TSC.CountVISA,TSC.CountOTHR,TSC.CountDEVO,TSC.CountTIPS,[=F("{CALL:co.getTotal('Card HNL')}")]:(TST=CO Card HNL)}
{REPORT TASK DETAILS:T.TaskType,T.Name,TSC.CountAMEX;0.00;0.00,TSC.CountDISC,TSC.CountMAST,TSC.CountVISA,TSC.CountOTHR,TSC.CountDEVO,TSC.CountTIPS,[=F("{CALL:co.getTotal('Card USD')}")]:(TST=CO Card USD)}

>>Type|Name|rate|rateInv|rateDate
{REPORT TASK DETAILS:T.TaskType,T.Name,TSC.rate,TSC.rateInv,TSC.rateDate:(TST=Exchange Rate)}



#14

#Workperiod / Cashout Screen


#15

#DB Tools Import Files

Cashout Tasks.zip (9.3 KB)

###Contains:

  • CO_TaskTypes
  • CO_Script
  • CO_Reports
  • CO_Rules

#16

@emre, the Event for Before Work Period Ends is not being triggered.


I use the Action End Work Period to close a Workperiod when I click on a button …


If I change the Event to Work Period Ended, it triggers fine:


#17

Unfortunately before work period ends registered to end work period button located on original work period screen. That rule implemented before we implemented the End Work Period action. It is probably not useful anymore as you can execute any action before executing End Work Period action.


#18

Okie dokie :wink:


#19

Hi @QMcKay

This is all looking amazing. Any chance you could share the DBtools file for your upated entity screen?

I’m a little confused at how and when the values are recorded as tasks? I was wondering if we need a button to confirm and submit the various counts?

Also, I see there are tasks for the Exchange Rate, but I couldn’t work out where this gets set?

Finally, what do we need to do if money is confirmed to be missing? Do we just adjust the float and make a note of it ourselves?


#20

Hi @QMcKay - Did you see my question above?

I have been trying to deconstruct you entity screen from the other DB Tools file, but I can’t get it to work hand-in-hand with these new functions you have implemented. If you could give me a heads-up that would be great :slight_smile: