|
|
@@ -3,6 +3,7 @@
|
|
|
namespace App\Services;
|
|
|
|
|
|
use App\Models\Backflow;
|
|
|
+use App\Support\BackflowPeriod;
|
|
|
use Carbon\Carbon;
|
|
|
use Exception;
|
|
|
|
|
|
@@ -30,35 +31,40 @@ class BackflowService extends BaseService
|
|
|
|
|
|
|
|
|
/**
|
|
|
- * 只记录当月充值/提现,回水金额由 rewards:sync-bases 按分类亏损和规则计算。
|
|
|
+ * 记录本期充值/提现供列表展示,回水金额按分类亏损和规则计算。
|
|
|
* @param $memberId string 会员ID
|
|
|
* @param $changeAmount float 充值或提现金额
|
|
|
* @return Backflow
|
|
|
*/
|
|
|
public static function updateOrCreate(string $memberId, float $changeAmount): Backflow
|
|
|
{
|
|
|
- $date = Carbon::now('Asia/Shanghai')->format('Y-m');
|
|
|
+ $date = BackflowPeriod::forDate(Carbon::now(BackflowPeriod::TIMEZONE)->toDateString(), BackflowPeriod::dailyFrom());
|
|
|
$field = $changeAmount > 0 ? 'recharge_amount' : 'withdrawal_amount';
|
|
|
- $backflow = static::$MODEL::firstOrCreate(['date' => $date, 'member_id' => $memberId]);
|
|
|
- if (in_array((int) $backflow->status, Backflow::OPEN_STATUSES, true)) $backflow->increment($field, $changeAmount);
|
|
|
+ $query = static::$MODEL::query();
|
|
|
+ if (strlen($date) === 10) $query->where('daily_date', $date);
|
|
|
+ $backflow = $query->firstOrCreate(['date' => $date, 'member_id' => $memberId]);
|
|
|
+ static::$MODEL::whereKey($backflow->id)->whereIn('status', Backflow::OPEN_STATUSES)->increment($field, $changeAmount);
|
|
|
return $backflow->refresh();
|
|
|
}
|
|
|
|
|
|
|
|
|
- /** 已发放 / 待发放 / 是否可发放(回水可在当月多次发放差额) */
|
|
|
- public static function grantFields(array $row): array
|
|
|
+ /** 已发放 / 待发放 / 是否可发放 */
|
|
|
+ public static function grantFields(array $row, ?string $dailyFrom = null, bool $hasUnsettled = false): array
|
|
|
{
|
|
|
$amount = bcadd((string) ($row['amount'] ?? 0), '0', 2);
|
|
|
$granted = bcadd((string) ($row['granted_amount'] ?? 0), '0', 2);
|
|
|
$open = in_array((int) ($row['status'] ?? 0), Backflow::OPEN_STATUSES, true);
|
|
|
$pending = $open && bccomp($amount, $granted, 2) > 0 ? bcsub($amount, $granted, 2) : '0.00';
|
|
|
- $month = Carbon::now('Asia/Shanghai')->format('Y-m');
|
|
|
+ $period = (string) ($row['date'] ?? '');
|
|
|
+ $today = Carbon::now(BackflowPeriod::TIMEZONE)->toDateString();
|
|
|
+ [, $end] = $period !== '' ? BackflowPeriod::bounds($period, $dailyFrom) : ['', $today];
|
|
|
+ $closed = $period !== '' && $today >= $end;
|
|
|
+ $waiting = $closed && $hasUnsettled && BackflowPeriod::waitsForSettlement($period, $dailyFrom);
|
|
|
return [
|
|
|
'amount' => $amount,
|
|
|
'granted_amount' => $granted,
|
|
|
'pending_amount' => $pending,
|
|
|
- // 当月需有差额才能发;往月未结清的记录即使差额为 0 也可点发放以结清
|
|
|
- 'can_grant' => $open && (bccomp($pending, '0', 2) > 0 || (string) ($row['date'] ?? '') < $month),
|
|
|
+ 'can_grant' => $open && !$waiting && ($closed || bccomp($pending, '0', 2) > 0),
|
|
|
'status_text' => [Backflow::STATUS_PENDING => '未发放', Backflow::STATUS_GRANTED => '已发放', Backflow::STATUS_PARTIAL => '部分发放'][(int) ($row['status'] ?? 0)] ?? '',
|
|
|
];
|
|
|
}
|
|
|
@@ -75,7 +81,8 @@ class BackflowService extends BaseService
|
|
|
}
|
|
|
|
|
|
if (isset($search['date']) && !empty($search['date'])) {
|
|
|
- $where[] = ['backflow.date', '=', $search['date']];
|
|
|
+ $period = $search['date'];
|
|
|
+ $where[] = strlen($period) === 7 ? ['backflow.date', 'like', $period . '%'] : ['backflow.date', '=', $period];
|
|
|
}
|
|
|
|
|
|
|
|
|
@@ -96,11 +103,11 @@ class BackflowService extends BaseService
|
|
|
public static function paginate(array $search = []): array
|
|
|
{
|
|
|
|
|
|
- // 当月(上海时间)的记录也展示实时统计;后台可手动提前发放,自动发放仍等到下个月,见 RewardGrantService::grant
|
|
|
- $month = Carbon::now('Asia/Shanghai')->format('Y-m');
|
|
|
+ $today = Carbon::now(BackflowPeriod::TIMEZONE)->toDateString();
|
|
|
+ $dailyFrom = BackflowPeriod::dailyFrom();
|
|
|
$query = static::$MODEL::join('users', 'users.member_id', '=', 'backflow.member_id')
|
|
|
->where(static::getWhere($search))
|
|
|
- ->where('backflow.date', '<=', $month);
|
|
|
+ ->where('backflow.date', '<=', $today);
|
|
|
\App\Support\MemberAudience::visibleUsers($query, 'users'); // 后台模拟会员只在模拟管理里出现
|
|
|
|
|
|
$paginator = $query->select("backflow.*", "users.first_name", "users.account", "users.admin_note as user_admin_note")->orderByDesc('date')->orderBy('status')
|
|
|
@@ -108,18 +115,20 @@ class BackflowService extends BaseService
|
|
|
// 未结清的记录按最新注单和当前规则实时重算(规则修改后存储值可能过期),与点“发放”时的计算一致
|
|
|
$tiers = $labels = null;
|
|
|
foreach ($paginator->items() as $item) {
|
|
|
+ $hasUnsettled = false;
|
|
|
if (in_array((int) $item->status, Backflow::OPEN_STATUSES, true)) {
|
|
|
$tiers ??= RewardRuleService::tiers('backflow');
|
|
|
$labels ??= RewardRuleService::categories('backflow');
|
|
|
$user = RewardBasisService::user((string) $item->member_id);
|
|
|
- $basis = $user ? RewardBasisService::backflowBasis($user, (string) $item->date) : [];
|
|
|
+ $basis = $user ? RewardBasisService::backflowBasis($user, (string) $item->date, $dailyFrom) : [];
|
|
|
$live = RewardBasisService::backflowReward($basis, $tiers, $labels);
|
|
|
+ $hasUnsettled = $live['has_unsettled'];
|
|
|
$item['amount'] = $live['amount'];
|
|
|
$item['loss_amount'] = $live['loss_amount'];
|
|
|
$item['need_flow'] = $live['need_flow'];
|
|
|
$item['details'] = $live['details'];
|
|
|
}
|
|
|
- foreach (self::grantFields($item->toArray()) as $field => $value) $item[$field] = $value;
|
|
|
+ foreach (self::grantFields($item->toArray(), $dailyFrom, $hasUnsettled) as $field => $value) $item[$field] = $value;
|
|
|
}
|
|
|
|
|
|
// $count = $query->count();
|