You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用Laravel 9 Eloquent从日记账数据生成试算平衡表

使用Laravel 9 Eloquent生成试算平衡表

模型关联设置

首先在Voucher模型中定义与Account模型的双向关联,分别对应借方和贷方科目:

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class Voucher extends Model
{
    protected $table = 'vouchers';
    protected $fillable = ['voucher_date', 'debit', 'credit', 'amount'];

    // 关联借方科目
    public function debitAccount()
    {
        return $this->belongsTo(Account::class, 'debit');
    }

    // 关联贷方科目
    public function creditAccount()
    {
        return $this->belongsTo(Account::class, 'credit');
    }
}

Account模型保持基础定义即可:

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class Account extends Model
{
    protected $table = 'accounts';
    protected $fillable = ['name', 'desc', 'status'];
}

方案一:遍历凭证拆分条目

通过遍历所有凭证,将每笔凭证拆分为借方、贷方两个独立条目,再整理格式并计算汇总:

use App\Models\Voucher;

public function getTrialBalance()
{
    $vouchers = Voucher::with(['debitAccount', 'creditAccount'])->get();
    
    $items = [];
    $totalDebit = 0;
    $totalCredit = 0;

    foreach ($vouchers as $voucher) {
        // 添加借方条目
        $debitAmt = $voucher->amount;
        $items[] = [
            'date' => $voucher->voucher_date,
            'account' => $voucher->debitAccount->name,
            'debit' => number_format($debitAmt, 2),
            'credit' => number_format(0, 2)
        ];
        $totalDebit += $debitAmt;

        // 添加贷方条目
        $creditAmt = $voucher->amount;
        $items[] = [
            'date' => $voucher->voucher_date,
            'account' => $voucher->creditAccount->name,
            'debit' => number_format(0, 2),
            'credit' => number_format($creditAmt, 2)
        ];
        $totalCredit += $creditAmt;
    }

    // 按日期倒序排序
    usort($items, fn($a, $b) => strtotime($b['date']) - strtotime($a['date']));

    // 添加汇总行
    $items[] = ['date' => '', 'account' => '', 'debit' => '', 'credit' => ''];
    $items[] = [
        'date' => '',
        'account' => 'Balance',
        'debit' => number_format($totalDebit, 2),
        'credit' => number_format($totalCredit, 2)
    ];

    return $items;
}

方案二:用UNION查询合并条目

通过Eloquent的UNION查询,直接从数据库层面合并借方和贷方数据,减少内存处理:

use App\Models\Voucher;
use Illuminate\Support\Facades\DB;

public function getTrialBalance()
{
    // 查询借方条目
    $debitQuery = Voucher::select(
        'voucher_date as date',
        'accounts.name as account',
        DB::raw('amount as debit'),
        DB::raw('0 as credit')
    )->join('accounts', 'vouchers.debit', '=', 'accounts.id')
     ->where('accounts.status', 1);

    // 查询贷方条目
    $creditQuery = Voucher::select(
        'voucher_date as date',
        'accounts.name as account',
        DB::raw('0 as debit'),
        DB::raw('amount as credit')
    )->join('accounts', 'vouchers.credit', '=', 'accounts.id')
     ->where('accounts.status', 1);

    // 合并查询并排序
    $items = $debitQuery->union($creditQuery)
                        ->orderBy('date', 'desc')
                        ->get()
                        ->map(fn($item) => [
                            'date' => $item->date,
                            'account' => $item->account,
                            'debit' => number_format($item->debit, 2),
                            'credit' => number_format($item->credit, 2)
                        ]);

    // 计算汇总
    $totalDebit = $items->sum(fn($i) => (float)$i['debit']);
    $totalCredit = $items->sum(fn($i) => (float)$i['credit']);

    // 添加汇总行
    $items->push(['date' => '', 'account' => '', 'debit' => '', 'credit' => '']);
    $items->push([
        'date' => '',
        'account' => 'Balance',
        'debit' => number_format($totalDebit, 2),
        'credit' => number_format($totalCredit, 2)
    ]);

    return $items;
}

视图展示

将处理好的数据在Blade视图中渲染成表格:

<table border="1" cellpadding="8">
    <thead>
        <tr>
            <th>日期</th>
            <th>科目</th>
            <th style="text-align: right">借方</th>
            <th style="text-align: right">贷方</th>
        </tr>
    </thead>
    <tbody>
        @foreach($trialBalance as $item)
        <tr>
            <td>{{ $item['date'] }}</td>
            <td>{{ $item['account'] }}</td>
            <td style="text-align: right">{{ $item['debit'] }}</td>
            <td style="text-align: right">{{ $item['credit'] }}</td>
        </tr>
        @endforeach
    </tbody>
</table>

内容的提问来源于stack exchange,提问作者Maji Mazuri

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.14 18:35:30