⼀个⼤致思路:拉出将所有积分变动数据 进⾏计算namespace App\\Service;use App\\Models\\TbaIntegralLog;use App\\Models\\User;
/**
* 计算剩余积分: *
* 1.将有 有效期的积分 按顺序排列
* 2.将 扣积分的数据 按照时间顺序排列
* 3.遍历扣积分的数据,依次从有效期顺序的积分中扣除
* 4.不够扣的到下⼀个有效期积分中扣,扣没了就直接累计负数 */
class CalculateBalance{ /**
* $income_score = [ * '2022-01-31' => 150, * '2022-02-26' => 150, * '2022-03-31' => 150, * ];
* $used_score = [
* '2021-10-01' => 100, * '2021-10-03' => 150, * ]; */
// 收⼊的积分
public $income_score; // 消耗的积分
public $used_score;
// 字段⽤于income_score不够扣了,将不够扣的⾦额累计到borrow中 public $borrow = 0;
// 初始化积分数据 和消费数据
public function __construct(User $user) {
$income_score = []; $used_score = [];
TbaIntegralLog::select([\"user_id\ ->where(\"user_id\
->whereIn(\"type\ ->orderBy(\"expire_at\ ->get()
->each(function ($item) use (&$income_score) { if (empty($income_score[$item->expire_at])) { $income_score[$item->expire_at] = 0; }
$income_score[$item->expire_at] = bcadd($income_score[$item->expire_at], $item->amount, 2); });
TbaIntegralLog::select([\"user_id\ ->where(\"user_id\
->whereIn(\"type\ ->orderBy(\"at\ ->get()
->each(function ($item) use (&$used_score) { if (empty($used_score[$item->at])) { $used_score[$item->at] = 0; }
$used_score[$item->at] = bcsub($used_score[$item->at], $item->amount, 2); });
$this->income_score = $income_score; $this->used_score = $used_score; } /**
* 输⼊消费⽇期和消费积分
* 按积分过期顺序实时抵消(消费时还未过期的)收⼊积分 *
* @return void */
protected function hedgeFund($date, $score) {
$income_arr = &$this->income_score; $current = $score;
foreach ($income_arr as $expire_at => $income) {
if ($income > 0 && $current > 0 && $expire_at > $date) { if ($income >= $current) {
$income_arr[$expire_at] = bcsub($income, $current, 2);
$current = '0.00'; } else {
$income_arr[$expire_at] = '0.00';
$current = bcsub($current, $income, 2); } }
if ($current === '0.00') { break; } }
// 积分不够的时候就要借了 if ($current > 0) {
$this->borrow = bcadd($this->borrow, $current, 2); } }
public function run() {
foreach ($this->used_score as $used_at => $used) { $this->hedgeFund($used_at, $used); }
// 获取最终积分余额 if ($this->borrow > 0) {
return bcsub(0, $this->borrow, 2); }
$now = date(\"Y-m-d\"); $sum = 0;
foreach ($this->income_score as $expire_at => $score) { if ($now < $expire_at) {
$sum = bcadd($sum, $score, 2); } }
return $sum; }}
因篇幅问题不能全部显示,请点此查看更多更全内容