<ensure variable="att.function" value="get">
<var _function_list = "valid_txn_types,count,sum,get,record,pay"> <if listFindNoCase(_function_list,att.function) EQ 0><p>/routine-txn : invalid function '<b>#att.function#</b>'</p><BREAK></if>
<var o = "txn">
<var _txn_select = reReplace('
#o#.id,
#o#.title, ([Debit|Credit]: [Short Title])
#o#.name, (For |/tbl-idnum| tags)
#o#.notes,
#o#.so_dateinserted,
#o#.userid_unsignedint, (user who owns transaction)
#o#.party_unsignedint, (user who owning user transacted with)
#o#.sum_double, (transaction amount)
#o#.type, (see "valid_txn_types" function)
#o#.operation, ("debit" if sum_double is negative, "credit" if zero or positive)
#o#.invoice ("cash_in" transactions should store a copy of paypal invoice)
',"([[:space:]]|\([^\)]*\))","","all")>
<var _txn_where = "#o#.user_id = 7">
<if att.function EQ "valid_txn_types">
<return "iqtpi_cash_in,iqtpi_adorder,cash_in,pmt">
</if>
<if att.function EQ "count">
<ensure variable="att.whereclause" value="#o#.id > 1">
<var _ret = 0>
<set orb="#o#" select="count(#o#.id) AS idcount" where="#_txn_where# AND (#att.whereclause#)" maxrows="1"
is_proxy="1">
<setcrawl><var _ret = set.idcount></setcrawl>
</set>
<return _ret>
</if>
<if att.function EQ "sum">
<ensure variable="att.whereclause" value="#o#.id > 1">
<var _ret = 0>
<set orb="#o#" select="count(#o#.sum_double) AS sumcount" where="#_txn_where# AND (#att.whereclause#)" maxrows="1"
is_proxy="1">
<setcrawl><var _ret = set.sumcount></setcrawl>
</set>
<return _ret>
</if>
<if att.function EQ "get">
<ensure variable="att.select" value="#_txn_select#">
<ensure variable="att.whereclause" value="#o#.id > 1">
<ensure variable="att.orderby" value="">
<ensure variable="att.groupby" value="">
<var _ret = QueryNew('id')>
<set orb="#o#" select="#att.select#" where="#_txn_where# AND (#att.whereclause#)"
is_proxy="1"
orderby="#att.orderby#"
groupby="#att.groupby#"
maxrows="9999">
<var _ret = set>
</set>
<return _ret>
</if>
<if att.function EQ "pay">
<return 0>
<var _continue = 1>
<!--- what kind of transaction? --->
<ensure variable="att.type" value=""><var att.type = trim(lcase(att.type))>
<tag.txn function="valid_txn_types">
<var _txn_list = return>
<if listFindNoCase(_txn_list,att.type) EQ 0>
<p>/routine-txn : invalid transaction type "<b>#att.type#</b>".</p>
<p>
Valid types: #_txn_list#
</p>
<BREAK>
</if>
<ensure variable="att.title" value="#att.type# iqtpi transaction">
<ensure variable="att.notes" value="">
<ensure variable="att.name" value="">
<ensure variable="att.invoice" value="">
<!--- validate sum --->
<ensure variable="att.sum_double" value="0">
<if NOT (isNumeric(att.sum_double) AND att.sum_double GTE 0.01)>
<p>/routine-txn : invalid sum <b>#att.sum_double#</b></p>
<BREAK>
</if>
<!--- validate to and from users --->
<ensure variable="att.from_unsignedint" value="0"><if NOT isNumeric(att.from_unsignedint)><var att.from_unsignedint = 0></if>
<var _from_name = "">
<ensure variable="att.to_unsignedint" value="0"><if NOT isNumeric(att.to_unsignedint)><var att.to_unsignedint = 0></if>
<var _to_name = "">
<set j="/user-#att.from_unsignedint#-#att.to_unsignedint#">
<if set.recordcount EQ 1 AND att.to_unsignedint EQ att.from_unsignedint>
<!--- special case where to and from are same user --->
<setcrawl>
<var _to_name = set.name>
<var _from_name = set.name>
</setcrawl>
<elseif set.recordcount NEQ 2>
<if set.recordcount EQ 0>
<p>/routine-txn : could not find "from" user <b>#att.from_unsignedint#</b> or "to" user <b>#att.to_unsignedint#</b></p>
<else>
<if set.id EQ att.from_unsignedint>
<p>/routine-txn : could not find "to" user <b>#att.to_unsignedint#</b></p>
<else>
<p>/routine-txn : could not find "from" user <b>#att.from_unsignedint#</b></p>
</if>
</if>
<var _continue = 0>
<else>
<setcrawl>
<if set.id EQ att.to_unsignedint>
<var _to_name = set.name>
<else>
<var _from_name = set.name>
</if>
</setcrawl>
</if>
</set>
<if _continue EQ 0><BREAK></if>
<!--- make sure both of those users have accounts --->
<tag.account function="ensure" userid_unsignedint="#att.to_unsignedint#" user_name="#_to_name#">
<if return NEQ 1>
<p>/routine-txn : error creating account for "to" user <b>#att.to_unsignedint#</b> (#_to_name#)</p>
<BREAK>
</if>
<tag.account function="ensure" userid_unsignedint="#att.from_unsignedint#" user_name="#_from_name#">
<if return NEQ 1>
<p>/routine-txn : error creating account for "from" user <b>#att.from_unsignedint#</b> (#_from_name#)</p>
<BREAK>
</if>
<!--- make sure "from" user has enough money --->
<tag.account function="get_user_balance" userid_unsignedint="#att.from_unsignedint#">
<var _from_total = return>
<if att.sum_double GT _from_total>
<p>/routine-txn : "from" account has insufficient funds</p>
<BREAK>
</if>
<!--- record transactions (which debits/credits accounts) --->
<!--- debit "from" account --->
<tag.txn function="record"
sum_double="#0-att.sum_double#"
type="#att.type#"
title="#att.title#"
notes="#att.notes#"
name="#att.name#"
invoice="#att.invoice#"
userid_unsignedint="#att.from_unsignedint#"
party_unsignedint="#att.to_unsignedint#">
<!--- credit "to" account --->
<tag.txn function="record"
sum_double="#att.sum_double#"
type="#att.type#"
title="#att.title#"
notes="#att.notes#"
name="#att.name#"
invoice="#att.invoice#"
userid_unsignedint="#att.to_unsignedint#"
party_unsignedint="#att.from_unsignedint#">
<return 1>
</if>
<if att.function EQ "record">
<ensure variable="att.type" value=""><var att.type = trim(lcase(att.type))>
<tag.txn function="valid_txn_types">
<var _txn_list = return>
<if listFindNoCase(_txn_list,att.type) EQ 0>
<p>/routine-txn : invalid transaction type "<b>#att.type#</b>".</p>
<p>
Valid types: #_txn_list#
</p>
<BREAK>
</if>
<if att.sum_double LT 0>
<var _operation = "Debit">
<else>
<var _operation = "Credit">
</if>
<ensure variable="att.notes" value="">
<ensure variable="att.name" value="">
<ensure variable="att.invoice" value="">
<var _sum_double = att.sum_double * 100>
<var _sum_double = round(_sum_double)>
<var _sum_double = _sum_double / 100>
<insert orb="#o#" is_proxy="1"
title="#_operation#: #att.title#"
notes="#att.notes#"
name="#att.name#"
invoice="#att.invoice#"
userid_unsignedint="#att.userid_unsignedint#"
party_unsignedint="#att.party_unsignedint#"
sum_double="#_sum_double#"
type="#att.type#"
operation="#_operation#">
<tag.account userid_unsignedint="#att.userid_unsignedint#" function="#_operation#" sum_double="#_sum_double#">
<return return>
</if>