dao->be(['task_id' => $taskId, 'settle_type' => 'complete'])) { return $this->dao->getOne(['task_id' => $taskId, 'settle_type' => 'complete'])->toArray(); } $gross = $this->money($task['base_amount']); $settlement = $this->dao->save([ 'task_id' => $taskId, 'uid' => (int)$task['uid'], 'settle_type' => 'complete', 'gross_amount' => $gross, 'fee_rate' => '0.00', 'fee_amount' => '0.00', 'net_amount' => $gross, 'audit_status' => 1, 'audit_time' => time(), ])->toArray(); $brokerageId = $this->grantBrokerage((int)$task['uid'], $gross, $taskId, '推四免一任务完成结算,任务号:' . $task['task_no']); $this->dao->update((int)$settlement['id'], ['brokerage_id' => $brokerageId]); $this->taskDao->update($taskId, ['status' => 1, 'finish_time' => time()]); return $settlement; }); } public function applyCashout(int $uid, int $taskId): array { return Db::transaction(function () use ($uid, $taskId) { $task = $this->taskDao->get($taskId); if (!$task || (int)$task['uid'] !== $uid) { throw new ValidateException('推广任务不存在'); } if ((int)$task['status'] !== 0) { throw new ValidateException('当前任务状态不可提前兑现'); } $progress = (int)$task['progress_count']; if ($progress < 1 || $progress >= (int)$task['target_count']) { throw new ValidateException('当前进度不可提前兑现'); } if ($this->dao->be(['task_id' => $taskId, 'settle_type' => 'early_cashout'])) { throw new ValidateException('已提交提前兑现申请'); } [$gross, $fee, $net] = $this->calcEarlyCashout($task->toArray()); $settlement = $this->dao->save([ 'task_id' => $taskId, 'uid' => $uid, 'settle_type' => 'early_cashout', 'gross_amount' => $gross, 'fee_rate' => $this->money($task['fee_rate']), 'fee_amount' => $fee, 'net_amount' => $net, 'audit_status' => 0, ])->toArray(); $this->taskDao->update($taskId, ['status' => 5]); return $settlement; }); } public function auditCashout(int $settlementId, int $auditUid, int $status, string $remark = ''): void { Db::transaction(function () use ($settlementId, $auditUid, $status, $remark) { $settlement = $this->dao->get($settlementId); if (!$settlement || $settlement['settle_type'] !== 'early_cashout') { throw new ValidateException('提前兑现申请不存在'); } if ((int)$settlement['audit_status'] !== 0) { throw new ValidateException('申请已审核'); } $task = $this->taskDao->get((int)$settlement['task_id']); if (!$task || (int)$task['status'] !== 5) { throw new ValidateException('任务状态不可审核'); } if ($status === 1) { $brokerageId = $this->grantBrokerage((int)$settlement['uid'], (string)$settlement['net_amount'], (int)$task['id'], '推四免一提前兑现到账,任务号:' . $task['task_no']); $this->dao->update($settlementId, [ 'audit_status' => 1, 'audit_uid' => $auditUid, 'audit_remark' => $remark, 'audit_time' => time(), 'brokerage_id' => $brokerageId, ]); $this->taskDao->update((int)$task['id'], ['status' => 2, 'cashout_time' => time()]); } elseif ($status === 2) { $this->dao->update($settlementId, [ 'audit_status' => 2, 'audit_uid' => $auditUid, 'audit_remark' => $remark, 'audit_time' => time(), ]); $this->taskDao->update((int)$task['id'], ['status' => 0]); } else { throw new ValidateException('审核状态不正确'); } }); } public function listForUser(int $uid, int $page, int $limit): array { return $this->dao->getUserList($uid, $page, $limit); } public function adminList(array $where, int $page, int $limit): array { return $this->dao->getAdminList($where, $page, $limit); } private function calcEarlyCashout(array $task): array { $rates = json_decode((string)$task['reward_rates'], true); if (!is_array($rates)) { $rates = [10, 20, 30, 40]; } $step = max(1, (int)$task['progress_count']); $rate = (float)($rates[$step - 1] ?? 0); $gross = bcmul((string)$task['base_amount'], bcdiv((string)$rate, '100', 4), 2); $fee = bcmul($gross, bcdiv((string)$task['fee_rate'], '100', 4), 2); $net = bcsub($gross, $fee, 2); return [$gross, $fee, $net]; } private function grantBrokerage(int $uid, string $amount, int $taskId, string $mark): int { /** @var UserServices $userServices */ $userServices = app()->make(UserServices::class); $current = (string)($userServices->value(['uid' => $uid], 'brokerage_price') ?: '0'); $balance = bcadd($current, $amount, 2); $userServices->bcInc($uid, 'brokerage_price', $amount, 'uid'); /** @var UserBrokerageServices $brokerageServices */ $brokerageServices = app()->make(UserBrokerageServices::class); $row = $brokerageServices->income('syj_promote_settlement', $uid, [ 'number' => $amount, 'mark' => $mark, ], $balance, $taskId); if ($row && method_exists($row, 'getData')) { return (int)$row->getData('id'); } return 0; } private function money(float|string $amount): string { return number_format((float)$amount, 2, '.', ''); } }