简体   繁体   English

重复输入会计分页问题

[英]Double Entry Accounting pagination issue

There is a really serious issue about Double Entry Accounting systems with pagination, I think it is common but I still didn't find any solution for my problem yet. 关于带有分页的Double Entry Accounting系统存在一个非常严重的问题,我认为这很普遍,但是我仍然没有找到解决我问题的方法。

You can use this link to read about the simple Double Entry Accounting systems just like the one I made with Laravel and AngularJS . 您可以使用此链接来阅读简单的Double Entry Accounting系统 ,就像我使用LaravelAngularJS创建的 系统一样。

In this system, the expected result (for example) is something like this: 在此系统中,预期结果(例如)如下所示:

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

It is very easy to track the balance inside a cumulative function if you were showing all the transactions in one page, the balance in the last transaction is your current balance at the end of the day. 如果将所有交易显示在一页中,则很容易在累积函数中跟踪余额,最后一笔交易的余额是一天结束时的当前余额。

For example, for a specific range of dates $fromDate -> $toDate , we do like: 例如,对于特定日期范围$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;

Now we have balance from yesterday, we depend on it to calculate the balance after that in a cumulative loop until the end of the process, reaching $toDate ; 现在我们有了昨天的余额,我们依靠它来计算累积循环中直到此过程结束为止的余额,直到$toDate

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

Now the real problem starts when you have a big amount of transactions, and you need to paginate them $journal = $journal->paginate(100); 现在,当您有大量交易时,真正的问题就开始了,您需要对它们进行分页$journal = $journal->paginate(100); , let's say 100 transactions per page, the system will work as expected for the first page, as we already can calculate the $balanceYesterday and depend on it to calculate the new balance after every transaction to the end of the 100 transactions in the first page. ,假设每页100笔交易,系统将按首页上的预期运行,因为我们已经可以计算$balanceYesterday并依靠它来计算每笔交易后到第一页100笔交易结束时的新余额。

Next page will have the problem that it doesn't know what was the last balance at the previous transaction in the first page, so it will start again from $balanceYesterday , making the whole table have wrong calculations. 下一页将出现一个问题 ,即它不知道第一页中上一个交易记录的最后一笔余额,因此它将再次从$balanceYesterday开始,从而使整个表的计算错误。

What I did first to fix, was transferring the last transaction amount (in front-end) to the next page as a parameter, and use it as a starting amount to calculate again, and that was the best solution I had as I was using only << PREV and NEXT >> buttons, so it was very easy to fix it like that. 我首先要解决的是将最后一笔交易amount (前端)作为参数传输到下一页,然后将其用作起始金额以再次进行计算,这是我一直使用的最佳解决方案只有<< PREVNEXT >>按钮,因此很容易修复它。

在此处输入图片说明

But I lately found out that this workaround will not work if I have a pagination with page numbers, as the user would like to go through pages to explore the journal, now it is impossible to know the last balance at a specific page, and the system will show wrong calculations. 但是我最近发现,如果我对页码进行分页,则此解决方法将不起作用,因为用户希望浏览各个页面以浏览日记,因此现在无法知道特定页面的最后余额,并且系统将显示错误的计算。

在此处输入图片说明

What I am trying to do is finding a way to calculate the balance at a specific transaction , weather it was a credit or debit, I'm looking for a way to know how much the balance was after a specific transaction is done in a specific date, I DON'T WANT TO ADD A NEW BALANCE COLUMN AND SAVE THE BALANCE INSIDE IT, THE USER IS DOING A LOT OF MODIFICATIONS AND EDITS TO THE TRANSACTIONS FROM TIME TO TIME AND THAT WILL BREAK EVERYTHING AS A SMALL AMOUNT MODIFICATION WILL AFFECT ALL THE BALANCES AFTER IT, I CAN NOT depend on IDs of transactions in any method because transactions might have different random dates, so there will be no ordering by ID but there might be ordering by other fields like date or account owner or type or whatever.. 我想做的是找到一种方法来计算特定交易的余额 ,无论是贷方还是借方,我正在寻找一种方法来知道在特定交易中完成特定交易后的余额是多少到目前为止,我不想添加新的余额列,也不想在其中保存余额,用户不时对交易进行了大量修改和编辑,而所有小额修改都会对所有交易造成破坏平衡之后,我不能以任何方式依赖交易ID,因为交易可能具有不同的随机日期,因此将不会按ID进行排序,但可能会按日期,帐户所有者或类型等其他字段进行排序。 。

I've been scratching my head on this for about 4 months, I searched online and found no solutions, I hope after this long explanation that my problem is clear, and I hope somebody can help me with a solution, please.. 我一直在这个问题上摸爬滚打大约4个月,我在网上搜索并没有找到解决方案,我希望在经过这么长时间的解释后,我的问题已经很清楚了,希望有人可以为我提供解决方案。

Thank you. 谢谢。

I believe the only thing you really need at this point is to calculate the sum of all transactions from the beginning of the paginated data set (all records, not just the current page's) until one before the first record displayed on the current page. 我相信,此时您真正需要的唯一一件事就是计算从分页数据集的开头(所有记录,而不仅仅是当前页面的记录)到当前页面上显示的第一条记录之前的所有事务的总和。

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. 通过查找整个数据集的开始与当前页面的事务之间发生的事务数,并通过LIMIT检索它们并将它们加起来,可以得到此结果。

The first thing you'll want to have is the exact constraints of your pagination query. 您首先要拥有的是分页查询的确切约束。 Since we want to grab another subset of paginated records besides the current page, you want to be sure the results of both queries are in the same order. 由于我们要获取除当前页面以外的其他分页记录子集,因此您需要确保两个查询的结果都在相同的顺序中。 Reusing the query builder object can help (adjust to match your actual pagination query): 重用查询构建器对象可以有所帮助(调整以匹配您的实际分页查询):

$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.

Then, fetch the paginated result set. 然后,获取分页的结果集。 This will perform two queries: one for the total count of records, and a second for the specific page's transactions. 这将执行两个查询:一个查询记录总数,第二个查询特定页面的事务。

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

From here, we can determine what records we need to retrieve the previous balance for. 从这里,我们可以确定检索先前余额所需的记录。 The pagination object returned is an instance of LengthAwarePaginator , which knows how many records in total, the number of pages, what current page its on, etc. 返回的分页对象是LengthAwarePaginator一个实例,该实例知道总共有多少条记录,页面数,其当前在哪个页面等。

Using that information, we just do some math to grab the number of records we need: 使用这些信息,我们可以做一些数学运算来获取所需的记录数:

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

Assuming the user is on page 5, they will see records 401 - 500, so we need to retrieve the previous 400 records. 假设用户在第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();

Now that we have the number of transactions that occurred within our data set but before the current page, we can retrieve and calculate the sum by again utilizing the base query: 现在我们有了在数据集中但在当前页面之前发生的事务数,我们可以再次使用基本查询来检索和计算总和:

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

Adding a highlight here to explain that using your database to perform the SUM calculations will be a big performance benefit, rather than doing it in a loop in PHP. 在此处添加一个亮点来说明使用数据库执行SUM计算将带来很大的性能优势,而不是在PHP中循环执行。 Take advantage of the DB as often as you can! 尽可能多地利用数据库!

Add this balance to your original "yesterday" balance, and you should have an accurate beginning balance for the paginated transactions. 将此余额添加到原始的“昨天”余额中,对于分页交易,您应该有一个准确的期初余额。

Note: everything pseudo-coded from theory, may need adjustments. 注意:理论上所有伪编码的内容都可能需要调整。 Happy to revise if there are questions or issues. 如有疑问或问题,很高兴进行修改。

You should be able to formulate a truth statement for the balance for each record as long as you can tell what the order is to calculate the sum for the balance at each point within that ordered list. 您应该能够为每个记录的余额制定一个真值陈述,只要您可以知道在该有序列表中的每个点上计算余额总和的顺序是什么。

For sure this come with a massive overhead as you need to query the whole table for each record you display, but first of all one must be able to do that. 确保这样做会带来巨大的开销,因为您需要查询整个表以显示每条记录,但是首先必须能够做到这一点。 As you've shown in the example, you are as long as you do not paginate. 如示例所示,只要不分页就可以。

What you could do for pagination is to pre-calculate the balance for each record and store it in relation to the original record. 对于分页,您可以做的是预先计算每条记录的余额并将其相对于原始记录进行存储。 This would de-normalize your data but with the benefit that creating the pagination is rather straight forward. 这样可以对数据进行非规范化,但是这样做的好处是创建分页非常简单。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM