Files
fdesk/app/common/traits/HasMoneyJournal.php
T
2025-09-04 10:26:28 +08:00

85 lines
2.7 KiB
PHP

<?php
namespace app\common\traits;
use app\common\model\VehMoneyValue;
use support\Db;
use Illuminate\Database\Eloquent\Relations\HasMany;
trait HasMoneyJournal
{
/**
* 【抽象方法】必须由使用该 trait 的模型实现
* 返回当前模型对应的金额“业务场景”标识
*
* @return string
*/
abstract protected static function moneyObjectScene(): string;
/** 所有关联金额记录(append-only 全部历史) */
public function moneyJournal(): HasMany
{
return $this->hasMany(VehMoneyValue::class, 'object_id')
->where('object_scene', static::moneyObjectScene());
}
/** 取某费项的“最新记录”(按时间/id 倒序) */
public function moneyLatest(string $field): ?VehMoneyValue
{
return $this->moneyJournal()
->where('field', $field)
->orderByDesc('created_at')
->orderByDesc('id')
->first();
}
/** 追加一行金额 */
public function addMoney(string $field, string $currency, $amount, ?string $rate = null, ?string $remark = null): VehMoneyValue
{
$now = time();
/** @var VehMoneyValue $row */
$row = $this->moneyJournal()->create([
'object_scene' => static::moneyObjectScene(),
'object_id' => $this->id,
'field' => $field,
'currency' => strtoupper($currency),
'amount' => (string)$amount,
'exchange_rate' => $rate,
'remark' => $remark,
'created_at' => $now,
'updated_at' => $now,
]);
return $row;
}
/** 批量追加:['unit_price'=>['currency'=>'USD','amount'=>'2199.00','rate'=>'7.2','remark'=>'...'], ...] */
public function addMoneyBatch(array $payload): array
{
return Db::transaction(function () use ($payload) {
$out = [];
foreach ($payload as $field => $cfg) {
$out[$field] = $this->addMoney(
$field,
$cfg['currency'] ?? 'CNY',
$cfg['amount'] ?? '0.00',
$cfg['rate'] ?? null,
$cfg['remark'] ?? null
);
}
return $out;
});
}
/** 把若干费项按各自汇率换到结算币并求和(无 rate 的跳过) */
public function sumToSettlement(array $fields, int $scale = 2): string
{
$sum = '0.00';
foreach ($fields as $f) {
$row = $this->moneyLatest($f);
if ($row) {
$v = $row->amountInSettlement($scale);
if ($v !== null) $sum = bcadd($sum, $v, $scale);
}
}
return $sum;
}
}