Refactored getTransactions, unified admin/user view

* Removed getAllTransactions method
* Unified getTransactions for users and admins
* Added filter abilities to user transaction view

This should speed up things a fair bit for transaction heavy pools.

Addresses #536
This commit is contained in:
Sebastian Grewe 2013-08-01 11:00:54 +02:00
parent 52f58807b0
commit 4eb6c59cb3
5 changed files with 90 additions and 152 deletions

View File

@ -33,42 +33,13 @@ class Transaction extends Base {
/**
* Get all transactions from start for account_id
* @param account_id int Account ID
* @param start int Starting point, id of transaction
* @param filter array Filter to limit transactions
* @param limit int Only display this many transactions
* @param account_id int Account ID
* @return data array Database fields as defined in SELECT
**/
public function getTransactions($account_id, $start=0) {
$this->debug->append("STA " . __METHOD__, 4);
$stmt = $this->mysqli->prepare("
SELECT
t.id AS id,
t.type AS type,
t.amount AS amount,
t.coin_address AS coin_address,
t.timestamp AS timestamp,
b.height AS height,
b.confirmations AS confirmations
FROM transactions AS t
LEFT JOIN " . $this->block->getTableName() . " AS b ON t.block_id = b.id
WHERE t.account_id = ?
ORDER BY id DESC");
if ($this->checkStmt($stmt)) {
if(!$stmt->bind_param('i', $account_id)) return false;
$stmt->execute();
$result = $stmt->get_result();
return $result->fetch_all(MYSQLI_ASSOC);
}
$this->debug->append('Unable to fetch transactions');
return false;
}
/**
* Fetch all transactions for all users
* Optionally apply a filter
* @param none
* @return mixed array or false
**/
public function getAllTransactions($start=0,$filter=NULL,$limit=30) {
public function getTransactions($start=0, $filter=NULL, $limit=30, $account_id=NULL) {
$this->debug->append("STA " . __METHOD__, 4);
$sql = "
SELECT
@ -124,6 +95,13 @@ class Transaction extends Base {
$sql .= " WHERE " . implode(' AND ', $aFilter);
}
}
if (is_int($account_id) && empty($aFilter)) {
$sql .= " WHERE a.id = ?";
$this->addParam('i', $account_id);
} else if (is_int($account_id)) {
$sql .= " AND a.id = ?";
$this->addParam('i', $account_id);
}
$sql .= "
ORDER BY id DESC
LIMIT ?,?
@ -132,15 +110,14 @@ class Transaction extends Base {
$this->addParam('i', $start);
$this->addParam('i', $limit);
$stmt = $this->mysqli->prepare($sql);
if ($this->checkStmt($stmt) && $stmt->bind_param('ii', $start, $limit) && $stmt->execute() && $result = $stmt->get_result()) {
if ($this->checkStmt($stmt) && call_user_func_array( array($stmt, 'bind_param'), $this->getParam()) && $stmt->execute() && $result = $stmt->get_result()) {
// Fetch matching row count
$num_rows = $this->mysqli->prepare("SELECT FOUND_ROWS() AS num_rows");
if ($num_rows->execute() && $row_count = $num_rows->get_result()->fetch_object()->num_rows)
$this->num_rows = $row_count;
if ($this->checkStmt($stmt) && call_user_func_array( array($stmt, 'bind_param'), $this->getParam()) && $stmt->execute() && $result = $stmt->get_result())
return $result->fetch_all(MYSQLI_ASSOC);
}
$this->debug->append('Unable to fetch transactions');
$this->debug->append('Failed to fetch transactions: ' . $this->mysqli->error);
return false;
}

View File

@ -3,9 +3,17 @@
// Make sure we are called from index.php
if (!defined('SECURITY')) die('Hacking attempt');
if ($user->isAuthenticated()) {
$aTransactions = $transaction->getTransactions($_SESSION['USERDATA']['id']);
$iLimit = 30;
empty($_REQUEST['start']) ? $start = 0 : $start = $_REQUEST['start'];
$aTransactions = $transaction->getTransactions($start, @$_REQUEST['filter'], $iLimit, $_SESSION['USERDATA']['id']);
$iCountTransactions = $transaction->num_rows;
$aTransactionTypes = $transaction->getTypes();
if (!$aTransactions) $_SESSION['POPUP'][] = array('CONTENT' => 'Could not find any transaction', 'TYPE' => 'errormsg');
$smarty->assign('LIMIT', $iLimit);
$smarty->assign('TRANSACTIONS', $aTransactions);
$smarty->assign('TRANSACTIONTYPES', $aTransactionTypes);
$smarty->assign('TXSTATUS', array('' => '', 'Confirmed' => 'Confirmed', 'Unconfirmed' => 'Unconfirmed', 'Orphan' => 'Orphan'));
$smarty->assign('COUNTTRANSACTIONS', $iCountTransactions);
}
$smarty->assign('CONTENT', 'default.tpl');
?>

View File

@ -12,9 +12,9 @@ if (!$user->isAuthenticated() || !$user->isAdmin($_SESSION['USERDATA']['id'])) {
if (!$smarty->isCached('master.tpl', $smarty_cache_key)) {
$iLimit = 30;
$debug->append('No cached version available, fetching from backend', 3);
$aTransactions = $transaction->getAllTransactions(@$_REQUEST['start'], @$_REQUEST['filter'], $iLimit);
$iCountTransactions = $transaction->num_rows;
empty($_REQUEST['start']) ? $start = 0 : $start = $_REQUEST['start'];
$aTransactions = $transaction->getTransactions($start, @$_REQUEST['filter'], $iLimit);
$iCountTransactions = $transaction->num_rows;
$aTransactionTypes = $transaction->getTypes();
if (!$aTransactions) $_SESSION['POPUP'][] = array('CONTENT' => 'Could not find any transaction', 'TYPE' => 'errormsg');
$smarty->assign('LIMIT', $iLimit);

View File

@ -1,40 +1,86 @@
{include file="global/block_header.tpl" BLOCK_HEADER="Transaction Log" BUTTONS=array(Confirmed,Unconfirmed,Orphan)}
<div class="block_content tab_content" id="Confirmed" style="clear:;">
{include file="global/block_header.tpl" ALIGN="left" BLOCK_STYLE="width: 23%" BLOCK_HEADER="Transaction Filter"}
<form action="{$smarty.server.PHP_SELF}">
<input type="hidden" name="page" value="{$smarty.request.page}" />
<input type="hidden" name="action" value="{$smarty.request.action}" />
<table cellpadding="1" cellspacing="1" width="100%">
<tbody>
<tr>
<td class="left">
{if $COUNTTRANSACTIONS / $LIMIT > 1}
{if $smarty.request.start|default:"0" > 0}
<a href="{$smarty.server.PHP_SELF}?page={$smarty.request.page}&action={$smarty.request.action}&start={$smarty.request.start|default:"0" - $LIMIT}{if $FILTERS|default:""}{$FILTERS}{/if}"><img src="{$PATH}/images/prev.png" /></a>
{else}
<img src="{$PATH}/images/prev.png" />
{/if}
{/if}
</td>
<td class="right">
{if $COUNTTRANSACTIONS / $LIMIT > 1}
{if $COUNTTRANSACTIONS - $smarty.request.start|default:"0" - $LIMIT > 0}
<a href="{$smarty.server.PHP_SELF}?page={$smarty.request.page}&action={$smarty.request.action}&start={$smarty.request.start|default:"0" + $LIMIT}{if $FILTERS|default:""}{$FILTERS}{/if}"><img src="{$PATH}/images/next.png" /></a>
{else}
<img src="{$PATH}/images/next.png" />
{/if}
{/if}
</td>
</tr>
<tr>
<td class="left">TX Type</td>
<td class="right">{html_options name="filter[type]" options=$TRANSACTIONTYPES selected=$smarty.request.filter.type|default:""}</td>
</tr>
<tr>
<td class="left">TX Status</td>
<td class="right">{html_options name="filter[status]" options=$TXSTATUS selected=$smarty.request.filter.status|default:""}</td>
</tr>
<tr>
<td class="center" colspan="2"><input type="submit" class="submit small" value="Filter"></td>
</tr>
</tbody>
</table>
</form>
{include file="global/block_footer.tpl"}
{include file="global/block_header.tpl" ALIGN="right" BLOCK_STYLE="width: 75%" BLOCK_HEADER="Transaction History"}
<div class="block_content" style="clear:;">
<center>
{include file="global/pagination.tpl"}
<table cellpadding="1" cellspacing="1" width="98%" class="pagesort">
<table cellpadding="1" cellspacing="1" width="100%">
<thead style="font-size:13px;">
<tr>
<th class="header" style="cursor: pointer;">TX #</th>
<th class="header" style="cursor: pointer;">Account</th>
<th class="header" style="cursor: pointer;">Date</th>
<th class="header" style="cursor: pointer;">TX Type</th>
<th class="header" style="cursor: pointer;">Status</th>
<th class="header" style="cursor: pointer;">Payment Address</th>
<th class="header" style="cursor: pointer;">Block #</th>
<th class="header" style="cursor: pointer;">Amount</th>
</tr>
</thead>
<tbody style="font-size:12px;">
{assign var=has_confirmed value=false}
{section transaction $TRANSACTIONS}
{if (
( ( $TRANSACTIONS[transaction].type == 'Credit' or $TRANSACTIONS[transaction].type == 'Bonus' or $TRANSACTIONS[transaction].type == 'Donation' or $TRANSACTIONS[transaction].type == 'Fee' ) and $TRANSACTIONS[transaction].confirmations >= $GLOBAL.confirmations )
or $TRANSACTIONS[transaction].type == 'Credit_PPS' or $TRANSACTIONS[transaction].type == 'Fee_PPS' or $TRANSACTIONS[transaction].type == 'Donation_PPS'
or $TRANSACTIONS[transaction].type == 'Debit_AP' or $TRANSACTIONS[transaction].type == 'Debit_MP' or $TRANSACTIONS[transaction].type == 'TXFee'
)}
{assign var=has_credits value=true}
<tr class="{cycle values="odd,even"}">
<td>{$TRANSACTIONS[transaction].id}</td>
<td>{$TRANSACTIONS[transaction].username}</td>
<td>{$TRANSACTIONS[transaction].timestamp}</td>
<td>{$TRANSACTIONS[transaction].type}</td>
<td>
{if $TRANSACTIONS[transaction].type == 'Credit_PPS' OR
$TRANSACTIONS[transaction].type == 'Fee_PPS' OR
$TRANSACTIONS[transaction].type == 'Donation_PPS' OR
$TRANSACTIONS[transaction].type == 'Debit_MP' OR
$TRANSACTIONS[transaction].type == 'Debit_AP' OR
$TRANSACTIONS[transaction].type == 'TXFee' OR
$TRANSACTIONS[transaction].confirmations >= $GLOBAL.confirmations
}<font color="green">Confirmed</font>
{else if $TRANSACTIONS[transaction].confirmations == -1}<font color="red">Orphaned</font>
{else}<font color="orange">Unconfirmed</font>{/if}
<font size="1px">({$TRANSACTIONS[transaction].confirmations|default:"n/a"})</font>
</td>
<td>{$TRANSACTIONS[transaction].coin_address}</td>
<td>{if $TRANSACTIONS[transaction].height == 0}n/a{else}{$TRANSACTIONS[transaction].height}{/if}</td>
<td>{if $TRANSACTIONS[transaction].height == 0}n/a{else}{if $GLOBAL.blockexplorer}<a href="{$GLOBAL.blockexplorer}{$TRANSACTIONS[transaction].blockhash}">{$TRANSACTIONS[transaction].height}</a>{else}{$TRANSACTIONS[transaction].height}{/if}{/if}</td>
<td><font color="{if $TRANSACTIONS[transaction].type == 'Credit' or $TRANSACTIONS[transaction].type == 'Credit_PPS' or $TRANSACTIONS[transaction].type == 'Bonus'}green{else}red{/if}">{$TRANSACTIONS[transaction].amount|number_format:"8"}</td>
</tr>
{/if}
{/section}
{if !$has_confirmed}
<tr><td class="center" colspan="6"><b><i>No data</i></b></td></tr>
{/if}
</tbody>
</table>
<p>
@ -44,97 +90,4 @@
</p>
</center>
</div>
<div class="block_content tab_content" id="Unconfirmed" style="">
<center>
{include file="global/pagination.tpl" ID=2}
<table cellpadding="1" cellspacing="1" width="98%" class="pagesort2">
<thead style="font-size:13px;">
<tr>
<th class="header" style="cursor: pointer;">TX #</th>
<th class="header" style="cursor: pointer;">Date</th>
<th class="header" style="cursor: pointer;">TX Type</th>
<th class="header" style="cursor: pointer;">Payment Address</th>
<th class="header" style="cursor: pointer;">Block #</th>
<th class="header" style="cursor: pointer;">Amount</th>
</tr>
</thead>
<tbody style="font-size:12px;">
{assign var=has_unconfirmed value=false}
{section transaction $TRANSACTIONS}
{if
(($TRANSACTIONS[transaction].type == 'Credit' or $TRANSACTIONS[transaction].type == 'Bonus' or $TRANSACTIONS[transaction].type == 'Donation' or $TRANSACTIONS[transaction].type == 'Fee') and $TRANSACTIONS[transaction].confirmations < $GLOBAL.confirmations and $TRANSACTIONS[transaction].confirmations >= 0)
}
{assign var=has_unconfirmed value=true}
<tr class="{cycle values="odd,even"}">
<td>{$TRANSACTIONS[transaction].id}</td>
<td>{$TRANSACTIONS[transaction].timestamp}</td>
<td>{$TRANSACTIONS[transaction].type}</td>
<td>{$TRANSACTIONS[transaction].coin_address}</td>
<td>{if $TRANSACTIONS[transaction].height == 0}n/a{else}{$TRANSACTIONS[transaction].height}{/if}</td>
<td><font color="{if $TRANSACTIONS[transaction].type == 'Credit' or $TRANSACTIONS[transaction].type == 'Bonus'}green{else}red{/if}">{$TRANSACTIONS[transaction].amount|number_format:"8"}</td>
</tr>
{if $TRANSACTIONS[transaction].type == 'Credit' or $TRANSACTIONS[transaction].type == 'Bonus'}
{assign var="credits" value="`$credits|default:"0"+$TRANSACTIONS[transaction].amount`"}
{else}
{assign var="debits" value="`$debits|default:"0"+$TRANSACTIONS[transaction].amount`"}
{/if}
{/if}
{/section}
{if !$has_unconfirmed}
<tr><td class="center" colspan="6"><b><i>No data</i></b></td></tr>
{/if}
<tr>
<td colspan="5"><b>Unconfirmed Totals:</b></td>
<td><b>{($credits|default - $debits|default)|number_format:"8"}</b></td>
</tr>
</tbody>
</table>
<p><font color="" sizeze="1">Listed are your estimated rewards and donations/fees for all blocks awaiting {$GLOBAL.confirmations} confirmations.</font></p>
</center>
</div>
<div class="block_content tab_content" id="Orphan" style="">
<center>
{include file="global/pagination.tpl"}
<table cellpadding="1" cellspacing="1" width="98%" class="pagesort3">
<thead style="font-size:13px;">
<tr>
<th class="header" style="cursor: pointer;">TX #</th>
<th class="header" style="cursor: pointer;">Date</th>
<th class="header" style="cursor: pointer;">TX Type</th>
<th class="header" style="cursor: pointer;">Payment Address</th>
<th class="header" style="cursor: pointer;">Block #</th>
<th class="header" style="cursor: pointer;">Amount</th>
</tr>
</thead>
<tbody style="font-size:12px;">
{assign var=has_orphaned value=false}
{section transaction $TRANSACTIONS}
{if ($TRANSACTIONS[transaction].type == 'Credit' or $TRANSACTIONS[transaction].type == 'Fee' or $TRANSACTIONS[transaction].type == 'Donation' or $TRANSACTIONS[transaction].type == 'Bonus') and $TRANSACTIONS[transaction].confirmations == -1}
<tr class="{cycle values="odd,even"}">
<td>{$TRANSACTIONS[transaction].id}</td>
<td>{$TRANSACTIONS[transaction].timestamp}</td>
<td>{$TRANSACTIONS[transaction].type}</td>
<td>{$TRANSACTIONS[transaction].coin_address}</td>
<td>{if $TRANSACTIONS[transaction].height == 0}n/a{else}{$TRANSACTIONS[transaction].height}{/if}</td>
<td><font color="{if $TRANSACTIONS[transaction].type == 'Credit' or $TRANSACTIONS[transaction].type == 'Bonus'}green{else}red{/if}">{$TRANSACTIONS[transaction].amount|number_format:"8"}</td>
</tr>
{if $TRANSACTIONS[transaction].type == 'Credit' or $TRANSACTIONS[transaction].type == 'Bonus'}
{assign var="orphan_credits" value="`$orphan_credits|default:"0"+$TRANSACTIONS[transaction].amount`"}
{else}
{assign var="orphan_debits" value="`$orphan_debits|default:"0"+$TRANSACTIONS[transaction].amount`"}
{/if}
{/if}
{/section}
{if !$has_orphaned}
<tr><td class="center" colspan="6"><b><i>No data</i></b></td></tr>
{/if}
<tr>
<td colspan="5"><b>Orphaned Totals:</b></td>
<td><b>{($orphan_credits|default - $orphan_debits|default)|number_format:"8"}</b></td>
</tr>
</tbody>
</table>
<p><font color="" sizeze="1">Listed are your orphaned transactions for blocks not part of the main blockchain.</font></p>
</center>
</div>
{include file="global/block_footer.tpl"}

View File

@ -1,4 +1,7 @@
{include file="global/block_header.tpl" ALIGN="left" BLOCK_STYLE="width: 23%" BLOCK_HEADER="Transaction Filter"}
<form action="{$smarty.server.PHP_SELF}">
<input type="hidden" name="page" value="{$smarty.request.page}" />
<input type="hidden" name="action" value="{$smarty.request.action}" />
<table cellpadding="1" cellspacing="1" width="100%">
<tbody>
<tr>
@ -21,9 +24,6 @@
{/if}
</td>
</tr>
<form action="{$smarty.server.PHP_SELF}">
<input type="hidden" name="page" value="{$smarty.request.page}" />
<input type="hidden" name="action" value="{$smarty.request.action}" />
<tr>
<td class="left">TX Type</td>
<td class="right">{html_options name="filter[type]" options=$TRANSACTIONTYPES selected=$smarty.request.filter.type|default:""}</td>
@ -43,9 +43,9 @@
<tr>
<td class="center" colspan="2"><input type="submit" class="submit small" value="Filter"></td>
</tr>
</form>
</tbody>
</table>
</form>
{include file="global/block_footer.tpl"}
{include file="global/block_header.tpl" ALIGN="right" BLOCK_STYLE="width: 75%" BLOCK_HEADER="Transaction History"}