Double Entry Accounting pagination issue

限于喜欢 提交于 2019-12-04 17:40:55

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.

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.

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.

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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!