193 lines
5.6 KiB
PHP
193 lines
5.6 KiB
PHP
<?php
|
|
|
|
namespace App\Models;
|
|
|
|
use Carbon\Carbon;
|
|
use Exception;
|
|
use Illuminate\Database\Eloquent\Relations\HasMany;
|
|
use Illuminate\Database\Eloquent\Relations\MorphTo;
|
|
use Illuminate\Support\Facades\DB;
|
|
|
|
class Account extends Model
|
|
{
|
|
|
|
/**
|
|
* Notes:
|
|
* @Author: <C.Jason>
|
|
* @Date: 2019/11/28 1:28 下午
|
|
* @return MorphTo
|
|
*/
|
|
public function accountable(): MorphTo
|
|
{
|
|
return $this->morphTo();
|
|
}
|
|
|
|
/**
|
|
* Notes: 账户日志
|
|
* @Author: <C.Jason>
|
|
* @Date: 2019/11/28 1:28 下午
|
|
* @return HasMany
|
|
*/
|
|
public function logs(): HasMany
|
|
{
|
|
return $this->hasMany(AccountLog::class);
|
|
}
|
|
|
|
/**
|
|
* Notes: 账户可用余额
|
|
* @Author: <C.Jason>
|
|
* @Date: 2019/11/28 2:26 下午
|
|
* @return mixed
|
|
*/
|
|
protected function getBalanceUseAttribute()
|
|
{
|
|
$ltZero = $this->logs()->where('frozen', 1)->where('variable', '<', 0)->sum('variable');
|
|
|
|
return $this->balance + $ltZero;
|
|
}
|
|
|
|
/**
|
|
* Notes: 冻结金额
|
|
* @Author: <C.Jason>
|
|
* @Date: 2019/11/28 2:27 下午
|
|
* @return mixed
|
|
*/
|
|
protected function getFrozenAttribute()
|
|
{
|
|
return $this->logs()->where('frozen', 1)->sum(DB::raw('abs(variable)'));
|
|
}
|
|
|
|
/**
|
|
* Notes: 执行账户规则
|
|
* @Author: <C.Jason>
|
|
* @Date: 2019/11/28 1:24 下午
|
|
* @param $rule string|int
|
|
* @param float $variable
|
|
* @param bool $frozen
|
|
* @param array $source
|
|
* @return bool
|
|
* @throws Exception
|
|
*/
|
|
public function rule($rule, float $variable = 0, bool $frozen = true, array $source = [])
|
|
{
|
|
if (is_numeric($rule)) {
|
|
$rule = AccountRule::findOrFail($rule);
|
|
} else {
|
|
$rule = AccountRule::where('name', $rule)->firstOrFail();
|
|
}
|
|
|
|
if ($rule->trigger == 0) {
|
|
// 不限制执行的
|
|
return $this->accountExecute($rule, $variable, $frozen, $source);
|
|
} elseif ($rule->trigger > $this->logs()->where('rule_id', $rule->id)->whereDate('created_at', Carbon::today())->count()) {
|
|
// 每日执行 trigger 次
|
|
return $this->accountExecute($rule, $variable, $frozen, $source);
|
|
} elseif ($rule->trigger < 0 && !$this->logs()->where('rule_id', $rule->id)->first()) {
|
|
// 终身只能执行一次
|
|
return $this->accountExecute($rule, $variable, $frozen, $source);
|
|
}
|
|
|
|
throw new Exception('达到最大可执行次数');
|
|
}
|
|
|
|
/**
|
|
* Notes: 增加账户余额
|
|
* @Author: <C.Jason>
|
|
* @Date: 2019/11/28 1:25 下午
|
|
* @param $type
|
|
* @param $variable
|
|
* @return bool
|
|
*/
|
|
public function increase($type, $variable)
|
|
{
|
|
DB::transaction(function () use ($type, $variable) {
|
|
$this->increment($type, $variable);
|
|
$log = [
|
|
'rule_id' => 0,
|
|
'type' => $type,
|
|
'variable' => $variable,
|
|
'frozen' => 0,
|
|
'balance' => $this->{$type},
|
|
'source' => ['type' => 'increase'],
|
|
];
|
|
$this->logs()->create($log);
|
|
});
|
|
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Notes: 扣除账户金额
|
|
* @Author: <C.Jason>
|
|
* @Date: 2019/11/28 1:25 下午
|
|
* @param $type
|
|
* @param $variable
|
|
* @return bool
|
|
* @throws Exception
|
|
*/
|
|
public function decrease($type, $variable)
|
|
{
|
|
// 如果账户类型不可以为负数
|
|
if (config('account.can_minus')[$type] === false && ($this->$type + $variable < 0)) {
|
|
throw new Exception('【 ' . config('account.account_type')[$type] . ' 】 余额不足');
|
|
}
|
|
DB::transaction(function () use ($type, $variable) {
|
|
$this->decrement($type, $variable);
|
|
$log = [
|
|
'rule_id' => 0,
|
|
'type' => $type,
|
|
'variable' => -$variable,
|
|
'frozen' => 0,
|
|
'balance' => $this->{$type},
|
|
'source' => ['type' => 'deduct'],
|
|
];
|
|
$this->logs()->create($log);
|
|
});
|
|
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Notes: 执行账户规则
|
|
* @Author: <C.Jason>
|
|
* @Date: 2019/11/28 1:41 下午
|
|
* @param AccountRule $rule
|
|
* @param $variable
|
|
* @param $frozen
|
|
* @param $source
|
|
* @return bool
|
|
* @throws Exception
|
|
*/
|
|
protected function accountExecute(AccountRule $rule, $variable, $frozen, $source)
|
|
{
|
|
if ($variable != 0) {
|
|
$rule->variable = $variable;
|
|
}
|
|
|
|
// 账户余额不允许为负数的时候判断余额是否充足
|
|
if ((config('account.can_minus')[$rule->type] == false) && ($rule->variable < 0) && ($rule->variable + $this->{$rule->type} < 0)) {
|
|
throw new Exception('【 ' . config('account.account_type')[$rule->type] . ' 】 余额不足');
|
|
}
|
|
DB::transaction(function () use ($rule, $frozen, $source) {
|
|
// 如果是扣款,立即执行,如果非冻结,也立即执行
|
|
if (($rule->variable < 0 && config('account.deductions')) || $rule->deductions == 1 || $frozen === false) {
|
|
$this->increment($rule->type, $rule->variable);
|
|
$frozen = false;
|
|
}
|
|
$log = [
|
|
'rule_id' => $rule->id,
|
|
'type' => $rule->type,
|
|
'variable' => $rule->variable,
|
|
'frozen' => $frozen,
|
|
'balance' => $this->{$rule->type},
|
|
'source' => $source ?: [],
|
|
];
|
|
// 写入记录
|
|
$this->logs()->create($log);
|
|
});
|
|
|
|
return true;
|
|
}
|
|
|
|
}
|