database - 如何在 Laravel 中使用 AOP 或任何其他解决方案在内部自动调用其他 Controller

标签 database laravel accounting

我正在开发一款会计软件,我必须在其中创建凭单,然后凭单应在创建后立即支付,这意味着针对该凭单的交易应从一个账户借记并记入另一个账户。

所以我把这两个表做成了。

  1. vouchers --> id, amount, from_account_id, to_account_id
  2. 交易 --> id, account_id, debit, credit.

我分别制作了model,controller,并添加了CRUD操作方法。

我已经为两者创建了 API 并使用了 CRUD 操作的 API。

所以真正的问题现在开始了。

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

凭证记录:

id = auto_generated, amount = 500, from_account_id = 8, to_account_id = 9

因此我必须根据这张凭证记录以下两笔交易。

交易记录:

id = auto_generated, debit = 500, credit = 0, account_id = 8

id = auto_generated, debit = 0, credit = 500, account_id = 9.

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

所以我在 store 代金券方法中为 3 个模型编写代码。所以我必须重写在凭证 store 方法中添加交易的所有代码。那么是否有任何方便且代码/错误较少的代码来自动调用针对该凭证的两个交易?

我也想要相同的更新过程,假设我稍后更新了我的凭证,那么背后的交易应该会自动更新。

最佳答案

您应该将您的 Controller 视为许多接口(interface)中的一个,理想情况下您的 Controller 应该关心任何特定于 HTTP 的内容。当您在 Controller 中编写代码时,请考虑“我是否需要此 Controller 之外的此功能?”如果答案是肯定的,那么该功能属于其他地方。

在这种情况下,您是在谈论模型的行为,您是在说“应支付代金券(您的模型)(行为)”。这是一个好兆头,表明该行为作为一种方法属于您的模型,您可以在创建时(使用事件)或在外部按需调用。例如在 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,
    ]);
}

然后你的 Controller 方法看起来像这样:

/**
* 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 事件监听器在 created 事件上触发它并防止它在任何其他时间被使用。

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


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

关于database - 如何在 Laravel 中使用 AOP 或任何其他解决方案在内部自动调用其他 Controller ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55081108/

相关文章:

php - 在动态网站中快速加载图像

database - 使用两个 dfs 的唯一标识符将数据框中的所有列按不同数据框中的列划分

与缺少扩展相关的 PHP 错误/异常处理

php - 在 Laravel 中检索可填写字段

laravel - 在 laravel 5.4 中创建合约

sql - 如何从 sql 语句或存储过程连接到外部数据库?

database - ON CONFLICT DO UPDATE/DO NOTHING 不在 FOREIGN TABLE 上工作

django - 确保复式记账应用程序中交易平衡的最佳方法是什么?

python - OpenERP : Saving field value (amount) into an account

sql - 寻找简单的应收账款数据库设计