如何使用Laravel中的AOP或任何其他解决方案在内部自动调用其他控制器

时间:2019-03-09 19:25:15

标签: database laravel accounting

我正在使用一种会计软件,必须在其中创建凭证,然后该凭证应在创建后立即付款,这意味着对该凭证的交易应从一个帐户借记并贷记到另一个帐户。 / p>

所以我把两个表都做了。

  1. 代金券-> id,金额,from_account_id,to_account_id
  2. 交易-> id,account_id,借方,贷方。

我已经为每种模型制作了模型,控制器,并添加了CRUD操作方法。

我已经为两者创建了API,并且将其用于CRUD操作。

真正的问题从现在开始。

针对一张凭证将发生两笔交易。 例如。

凭证记录:

id =自动生成,金额= 500,from_account_id = 8,to_account_id = 9

因此,我必须使用此凭证记录以下两项交易。

交易记录:

id =自动生成,借方= 500,贷方= 0,account_id = 8

id =自动生成,借方= 0,贷方= 500,account_id = 9。

现在我要完全手动地处理上述问题,这意味着我要先添加凭证,然后创建两个交易对象并根据数据分配值。

因此,我正在使用store凭证方式编写3种模型的代码。因此,我必须重写凭证store方法中添加交易的所有代码。因此,是否有任何方便且较少代码/错误的情况可以针对该凭单自动调用两个交易?

我也想要相同的更新过程,假设我稍后再更新了凭单,那么后面的交易应自动更新。

1 个答案:

答案 0 :(得分:2)

您应该将控制器视为许多接口中的一个,理想情况下,控制器应该关心所有特定于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,然后使用Eloquent事件监听器在{上触发{1}}事件,并禁止其他时间使用它。

关于稍后更新凭证:允许可变的凭证是错误的,但是如果必须这样做,则仍应将交易视为不可变的,这意味着凭证中的任何更改都应与接收方和发送方建立新的交易那等于金额,您永远不要在会计系统中修改历史交易数据。


注意:如果我要设计这个,我几乎肯定不会这样做,但是我需要更好地了解您的应用程序的目的和功能以正确设计它,所以我在这里给出的是基于最大的努力。您分享的内容,但不是完美的解决方案。