我正在开发一个会计软件,在那里我必须创建凭证,然后该凭证应在创建后立即支付,这意味着该凭证的交易应作为一个账户的借方和另一个账户的贷方进行。
所以我把这两张桌子做成了。
凭证-->id,金额,从帐户id,到帐户id
交易-->ID,帐户ID,借方,贷方。
我制作了模型,为每个控制器添加了crud操作方法。
我已经为两者创建了api,并使用该api进行crud操作。
所以真正的问题现在就开始了。
凭一张凭单将发生两笔交易。
例如。
凭证记录:
ID=自动生成,金额=500,从帐户ID=8,到帐户ID=9
因此,根据这张凭证,我必须记录两笔交易如下。
交易记录:
ID=自动生成,借方=500,贷方=0,帐户ID=8
ID=自动生成,借方=0,贷方=500,帐户ID=9。
现在我完全手动处理上面的内容,也就是说我先添加凭证,然后创建两个事务对象,并根据数据分配值。
所以我正在用store凭证方法为3个模型编写代码。因此,我必须重新编写凭证store方法中添加交易的所有代码。那么,是否有任何方便且较少的代码/错误倾向于根据凭证自动调用这两个事务?
我也要同样的流程上更新,假设我已经更新了我的凭证以后,所以后面的交易应该自动更新。

最佳答案

您应该将控制器视为多个接口中的一个,理想情况下,您的控制器应该只关心http特定的任何东西。当您在控制器中编写代码时,请想一想“我是否需要这个控制器之外的功能?”如果答案是肯定的,那么功能就属于其他地方。
在这种情况下,你说的是你的模型的行为,你说的是“代金券(你的模型)应该支付(行为)”。这是一个很好的迹象,表明行为属于模型中的一种方法,可以在创建时(使用事件)调用,也可以在外部按需调用。例如在App\Voucher.php中:

/**
* Account that is debited by the voucher.
*
* @return \Illuminate\Database\Eloquent\Relations\HasOne
*/
public function from(): HasOne
{
    return $this->hasOne(Account::class, 'id', 'from_account_id');
}

/**
* Account that is credited by the voucher.
*
* @return \Illuminate\Database\Eloquent\Relations\HasOne
*/
public function to(): HasOne
{
    return $this->hasOne(Account::class, 'id', 'to_account_id');
}

/**
* Credit the voucher amount.
*
* @return void
*/
public function pay(): void
{
    $this->from()->transactions()->create([
        'debit' => $this->amount,
        'credit' => 0,
    ]);

    $this->to()->transactions()->create([
        'debit' => 0,
        'credit' => $this->amount,
    ]);
}

那么您的控制器方法如下所示:
/**
* Create the Voucher and pay it out.
*
* @param \Illuminate\Http\Request $request
*
* @return \Illuminate\Http\RedirectResponse
*/
public function store(Request $request): RedirectResponse
{
    $voucher = Voucher::create([
        'from_account_id' => $request->from,
        'to_account_id' => $request->to,
        'amount' => $request->amount,
    ]);

    $voucher->pay();

    return redirect()->route('vouchers.index')->with([
        'success' => "{$request->amount} has been credited to your recipient."
    ]);
}

然后,在任何其他需要支付凭证的时间,只需调用该凭证上的pay方法即可。如果您希望支付凭证的唯一时间是在创建时,则可以将pay方法设置为protected,而不是public,然后使用雄辩的事件侦听器在created事件上触发它,并防止它在任何其他时间被使用。
关于日后更新凭证:允许凭证可变是错误的,但如果必须这样做,则仍应将交易视为不可变,这意味着凭证中的任何更改都应与接收者和发送者创建等于金额的新交易,不应修改会计系统中的历史交易数据。
注意:如果我设计这个,我几乎肯定不会这样做,但我需要更好地理解您的应用程序的目的和功能,以正确地设计它,所以我在这里给出的是基于您共享的内容而不是完美的解决方案的最大努力。

10-08 07:06
查看更多