双重会计会计分页问题

时间:2018-04-14 22:32:58

标签: php laravel laravel-5 accounting

关于双重会计系统的分页存在一个非常严重的问题,我认为这很常见,但我仍然没有找到解决我问题的方法。

您可以使用此链接阅读simple Double Entry Accounting systems,就像我使用 Laravel AngularJS 制作的那样。

在这个系统中,预期的结果(例如)是这样的:

ID      In       Out    Balance
1      100.00    0.00   100.00
2       10.00    0.00   110.00
3        0.00   70.00    40.00
4        5.00    0.00    45.00
5        0.00   60.00   -15.00
6       20.00    0.00     5.00

如果您在一个页面中显示所有交易,则很容易跟踪累积功能内的余额,最后一笔交易中的余额是您当天结束时的当前余额。

例如,对于特定范围的日期$fromDate - > $toDate,我们会这样做:

$balanceYesterday = DB::table('journal')->where('date', '<', $fromDate)
        ->join('transactions','transactions.journal_id','journal.id')->where('transactions.type', "=", 0) /* 0 means the account of the company */
        ->select(DB::raw('SUM(amount) as total_balance'))
        ->first()->total_balance;

现在我们从昨天开始有余额,我们依靠它来计算累积循环之后的余额,直到流程结束,达到$toDate;

$currentBalance = $currentBalance + $currentTransaction->amount;
$currentTransactionBalance = $currentBalance;

现在真正的问题在你有大量的交易开始时,你需要对它们进行分页$journal = $journal->paginate(100);,假设每页有100个交易,系统将按照预期的方式在第一页上工作,因为我们已经可以计算$balanceYesterday并依赖它来计算每笔交易到第一页100笔交易结束后的新余额。

下一页有问题,它不知道第一页上一次交易的最后余额是什么,所以它会从$balanceYesterday再次开始,整个表有错误的计算。

我首先要解决的问题是将最后一笔交易amount(在前端)作为参数转移到下一页,并将其作为起始金额再次计算,这是最好的因为我只使用&lt;&lt; PREV NEXT&gt;&gt; 按钮,因此很容易修复它。

enter image description here

但我最近发现,如果我对页码进行分页,这种解决方法将不起作用,因为用户希望通过页面浏览日志,现在无法知道特定页面的最后余额,系统将显示错误的计算。

enter image description here

我正在尝试做什么正在寻找一种方法计算特定交易的余额,天气是信用卡或借记卡,我正在寻找一个如何知道在特定日期完成特定交易后余额是多少,我不想添加新的平衡栏并保存其内部的平衡,用户正在对交易进行大量修改和编辑由于交易可能具有不同的随机日期,因此不会依赖于任何方法中的交易ID,因此不会在任何方法中影响所有余额可能有其他字段的订购,如日期或帐户所有者或类型或其他..

我一直在摸索这个问题大约4个月,我在网上搜索并找不到任何解决方案,我希望经过长时间的解释后我的问题很清楚,我希望有人可以帮我解决问题。

谢谢。

2 个答案:

答案 0 :(得分:2)

我认为此时您真正需要的唯一事情是计算从分页数据集开头(所有记录,而不仅仅是当前页面)到第一个记录之前的所有事务的总和显示在当前页面上。

您可以通过查找整个数据集的开头与当前页面的交易之间发生的交易数量,通过LIMIT检索并添加它们来获得此结果。

您希望拥有的第一件事是您的分页查询的确切约束。由于我们想要获取除当前页面之外的另一个分页记录子集,因此您需要确保两个查询的结果具有相同的顺序。重用查询构建器对象可以提供帮助(调整以匹配您的实际分页查询):

$baseQuery = DB::table('journal')
    ->join('transactions', 'transactions.journal_id', 'journal.id')
    ->where('date', '>', $fromDate)
    ->where('date', '<', $toDate)
    ->where('transactions.type', "=", 0)
    ->orderBy('date', 'asc');
    // Note that we aren't fetching anything here yet.

然后,获取分页结果集。这将执行两个查询:一个用于记录总数,另一个用于特定页面的事务。

$paginatedTransactions = $baseQuery->paginate(100);

从这里,我们可以确定我们需要哪些记录来检索以前的余额。返回的分页对象是LengthAwarePaginator的实例,它知道总共有多少条记录,页数,当前页面的内容等等。

使用这些信息,我们只是做一些数学来获取我们需要的记录数量:

total records needed = (current page - 1) * records per page

假设用户在第5页,他们将看到记录401 - 500,因此我们需要检索以前的400条记录。

// If we're on Page 1, or there are not enough records to
// paginate, we don't need to calculate anything.
if ($paginatedTransactions->onFirstPage() || ! $paginatedTransactions->hasPages()) {
    // Don't need to calculate a previous balance. Exit early here!
}

// Use helper methods from the Paginator to calculate
// the number of previous transactions.
$limit = ($paginatedTransactions->currentPage() - 1) * $paginatedTransactions->perPage();

既然我们在数据集中但在当前页面之前发生了多少事务,我们可以再次利用基本查询来检索和计算总和:

$previousBalance = $baseQuery->limit($limit)->sum('amount');
  

在此处添加一个突出显示,说明使用数据库执行SUM计算将是一个很大的性能优势,而不是在PHP循环中执行。尽可能多地利用数据库!

将此余额添加到您的原始&#34;昨天&#34;余额,您应该为分页交易准确的初始余额。

注意:从理论上伪编码的所有内容都可能需要调整。如果有问题或问题,请尽快修改。

答案 1 :(得分:1)

你应该能够为每条记录的余额制定一个真值陈述,只要你知道该顺序是什么来计算该有序列表中每个点的余额总和。

当然,这会带来巨大的开销,因为您需要查询整个表格中显示的每条记录,但首先必须能够做到这一点。正如您在示例中所示,只要您不进行分页,就可以了。

您可以为分页做的是预先计算每条记录的余额并将其存储在原始记录中。这会使您的数据无法正常化,但创造分页的好处是相当直接的。