85 lines
2.7 KiB
PHP
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;
|
|
}
|
|
} |