首页 文章

双重入账会计分页问题

提问于
浏览
2

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

您可以使用此链接阅读simple Double Entry Accounting systems,就像我使用 LaravelAngularJS 一样 .

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

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个交易结束 .

Next page will have the problem 它不知道第一页上一个事务的最后余额是什么,所以它将从 $balanceYesterday 再次开始,使整个表有错误的计算 .

我首先要解决的问题是将最后一个事务 amount (在前端)作为参数传递给下一页,并将其作为起始量再次计算,这是我使用的最佳解决方案只有 << PREVNEXT >> 按钮,因此很容易修复它 .

enter image description here

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

enter image description here

What I am trying to do 正在找到一种方法 calculate the balance at a specific transaction ,天气是信用卡或借记卡,我想要添加新的 balancer 栏并保存其内部的 balancer ,用户正在不时对交易进行大量修改和编辑并且这将破坏一切,因为小额修改将影响所有余额,我不能依赖于任何方法中的交易ID,因为交易可能具有不同的随机日期,因此不会按ID排序但可能有订购通过其他字段,如日期或帐户所有者或类型或其他..

我一直在摸不着头脑约4个月,我在网上搜索并找不到解决方案,我希望经过这么长时间的解释后我的问题很明确,我希望有人可以帮我解决问题,请...

谢谢 .

2 回答

  • 1

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

    You can get this by finding the number of transactions that occurred between the start of your entire data set and the current page's transactions, retrieving them via LIMIT, and adding them up.

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

    $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循环中执行 . 尽可能多地利用数据库!

    将此余额添加到原始“昨天”余额中,您应该为分页交易准确的期初余额 .

    注意:从理论上伪编码的所有内容都可能需要调整 . 如果有问题或问题,很高兴修改 .

  • 2

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

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

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

相关问题