fix(payment): refresh rebate metrics and unify withdrawal statuses
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
99f5c5e834
commit
50236b07fa
6 files changed
+59
-22
No files matched your search
@@ -71,7 +71,7 @@
|
|||||||
</n-card>
|
</n-card>
|
||||||
|
|
||||||
<n-card class="aksrt-section-card" title="提现统计">
|
<n-card class="aksrt-section-card" title="提现统计">
|
||||||
<n-grid :cols="4" :x-gap="12" :y-gap="12">
|
<n-grid :cols="6" :x-gap="12" :y-gap="12">
|
||||||
<n-grid-item>
|
<n-grid-item>
|
||||||
<div class="aksrt-revenue__stat">
|
<div class="aksrt-revenue__stat">
|
||||||
<strong>{{ withdrawalStats.total }}</strong>
|
<strong>{{ withdrawalStats.total }}</strong>
|
||||||
@@ -81,7 +81,13 @@
|
|||||||
<n-grid-item>
|
<n-grid-item>
|
||||||
<div class="aksrt-revenue__stat">
|
<div class="aksrt-revenue__stat">
|
||||||
<strong>{{ withdrawalStats.pending }}</strong>
|
<strong>{{ withdrawalStats.pending }}</strong>
|
||||||
<p>待审核</p>
|
<p>待处理</p>
|
||||||
|
</div>
|
||||||
|
</n-grid-item>
|
||||||
|
<n-grid-item>
|
||||||
|
<div class="aksrt-revenue__stat">
|
||||||
|
<strong>{{ withdrawalStats.processing }}</strong>
|
||||||
|
<p>处理中</p>
|
||||||
</div>
|
</div>
|
||||||
</n-grid-item>
|
</n-grid-item>
|
||||||
<n-grid-item>
|
<n-grid-item>
|
||||||
@@ -90,6 +96,12 @@
|
|||||||
<p>已完成</p>
|
<p>已完成</p>
|
||||||
</div>
|
</div>
|
||||||
</n-grid-item>
|
</n-grid-item>
|
||||||
|
<n-grid-item>
|
||||||
|
<div class="aksrt-revenue__stat">
|
||||||
|
<strong>{{ withdrawalStats.rejected }}</strong>
|
||||||
|
<p>已拒绝</p>
|
||||||
|
</div>
|
||||||
|
</n-grid-item>
|
||||||
<n-grid-item>
|
<n-grid-item>
|
||||||
<div class="aksrt-revenue__stat">
|
<div class="aksrt-revenue__stat">
|
||||||
<strong>{{ withdrawalStats.total_paid.toFixed(2) }}</strong>
|
<strong>{{ withdrawalStats.total_paid.toFixed(2) }}</strong>
|
||||||
@@ -108,7 +120,7 @@ import PaymentSectionPage from '@/pages/payment/PaymentSectionPage.vue'
|
|||||||
import api from '@/api'
|
import api from '@/api'
|
||||||
|
|
||||||
const revenueStats = ref({ total: 0, pending: 0, settled: 0, count: 0 })
|
const revenueStats = ref({ total: 0, pending: 0, settled: 0, count: 0 })
|
||||||
const withdrawalStats = ref({ total: 0, pending: 0, completed: 0, total_paid: 0 })
|
const withdrawalStats = ref({ total: 0, pending: 0, processing: 0, completed: 0, rejected: 0, total_paid: 0 })
|
||||||
const timeSeries = ref([])
|
const timeSeries = ref([])
|
||||||
const granularity = ref('day')
|
const granularity = ref('day')
|
||||||
|
|
||||||
@@ -151,7 +163,9 @@ async function loadRevenue() {
|
|||||||
withdrawalStats.value = {
|
withdrawalStats.value = {
|
||||||
total: Number(res.data.withdrawal.total || 0),
|
total: Number(res.data.withdrawal.total || 0),
|
||||||
pending: Number(res.data.withdrawal.pending || 0),
|
pending: Number(res.data.withdrawal.pending || 0),
|
||||||
|
processing: Number(res.data.withdrawal.processing || 0),
|
||||||
completed: Number(res.data.withdrawal.completed || 0),
|
completed: Number(res.data.withdrawal.completed || 0),
|
||||||
|
rejected: Number(res.data.withdrawal.rejected || 0),
|
||||||
total_paid: Number(res.data.withdrawal.total_paid || 0),
|
total_paid: Number(res.data.withdrawal.total_paid || 0),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -168,14 +168,16 @@ class PayMenus {
|
|||||||
|
|
||||||
if ($page !== 'aksrt_withdraw' && class_exists('\AKSRT\Payment\Withdrawal')) {
|
if ($page !== 'aksrt_withdraw' && class_exists('\AKSRT\Payment\Withdrawal')) {
|
||||||
$pending = (int) \AKSRT\Payment\Withdrawal::get_instance()->get_count(['status' => \AKSRT\Payment\Withdrawal::STATUS_PENDING]);
|
$pending = (int) \AKSRT\Payment\Withdrawal::get_instance()->get_count(['status' => \AKSRT\Payment\Withdrawal::STATUS_PENDING]);
|
||||||
if ($pending > 0) {
|
$processing = (int) \AKSRT\Payment\Withdrawal::get_instance()->get_count(['status' => \AKSRT\Payment\Withdrawal::STATUS_PROCESSING]);
|
||||||
|
$active = $pending + $processing;
|
||||||
|
if ($active > 0) {
|
||||||
$url = admin_url('admin.php?page=aksrt_withdraw&status=pending');
|
$url = admin_url('admin.php?page=aksrt_withdraw&status=pending');
|
||||||
echo '<div class="notice notice-info is-dismissible">';
|
echo '<div class="notice notice-info is-dismissible">';
|
||||||
echo '<h3>' . esc_html__('提现申请待处理', 'aksrt') . '</h3>';
|
echo '<h3>' . esc_html__('提现申请待处理', 'aksrt') . '</h3>';
|
||||||
echo '<p>' . esc_html(sprintf(
|
echo '<p>' . esc_html(sprintf(
|
||||||
/* translators: %d: pending withdrawal count */
|
/* translators: %d: open withdrawal count */
|
||||||
__('您有 %d 个提现申请待处理', 'aksrt'),
|
__('您有 %d 个提现申请待处理', 'aksrt'),
|
||||||
$pending
|
$active
|
||||||
)) . '</p>';
|
)) . '</p>';
|
||||||
echo '<p><a class="button button-primary" href="' . esc_url($url) . '">' . esc_html__('立即处理', 'aksrt') . '</a></p>';
|
echo '<p><a class="button button-primary" href="' . esc_url($url) . '">' . esc_html__('立即处理', 'aksrt') . '</a></p>';
|
||||||
echo '</div>';
|
echo '</div>';
|
||||||
|
|||||||
@@ -46,10 +46,12 @@ class PayWithdrawals {
|
|||||||
|
|
||||||
echo '<p>' . esc_html(sprintf(
|
echo '<p>' . esc_html(sprintf(
|
||||||
/* translators: 1: total 2: pending 3: completed 4: paid */
|
/* translators: 1: total 2: pending 3: completed 4: paid */
|
||||||
__('共 %1$d 条 · 待处理 %2$d · 已完成 %3$d · 已打款 %4$s', 'aksrt'),
|
__('共 %1$d 条 · 待处理 %2$d · 处理中 %3$d · 已完成 %4$d · 已拒绝 %5$d · 已打款 %6$s', 'aksrt'),
|
||||||
(int) ($stats['total'] ?? 0),
|
(int) ($stats['total'] ?? 0),
|
||||||
(int) ($stats['pending'] ?? 0),
|
(int) ($stats['pending'] ?? 0),
|
||||||
|
(int) ($stats['processing'] ?? 0),
|
||||||
(int) ($stats['completed'] ?? 0),
|
(int) ($stats['completed'] ?? 0),
|
||||||
|
(int) ($stats['rejected'] ?? 0),
|
||||||
number_format((float) ($stats['total_paid'] ?? 0), 2)
|
number_format((float) ($stats['total_paid'] ?? 0), 2)
|
||||||
)) . '</p>';
|
)) . '</p>';
|
||||||
|
|
||||||
@@ -59,7 +61,6 @@ class PayWithdrawals {
|
|||||||
$status_options = [
|
$status_options = [
|
||||||
'' => __('全部状态', 'aksrt'),
|
'' => __('全部状态', 'aksrt'),
|
||||||
'pending' => __('待处理', 'aksrt'),
|
'pending' => __('待处理', 'aksrt'),
|
||||||
'approved' => __('已通过', 'aksrt'),
|
|
||||||
'processing' => __('处理中', 'aksrt'),
|
'processing' => __('处理中', 'aksrt'),
|
||||||
'completed' => __('已完成', 'aksrt'),
|
'completed' => __('已完成', 'aksrt'),
|
||||||
'rejected' => __('已拒绝', 'aksrt'),
|
'rejected' => __('已拒绝', 'aksrt'),
|
||||||
|
|||||||
@@ -150,7 +150,7 @@ class PaymentController extends ControllerBase {
|
|||||||
$revenue_stats = \AKSRT\Payment\Revenue::get_instance()->get_stats();
|
$revenue_stats = \AKSRT\Payment\Revenue::get_instance()->get_stats();
|
||||||
}
|
}
|
||||||
|
|
||||||
$withdrawal_stats = ['total' => 0, 'pending' => 0, 'completed' => 0, 'total_paid' => 0];
|
$withdrawal_stats = ['total' => 0, 'pending' => 0, 'processing' => 0, 'completed' => 0, 'rejected' => 0, 'total_paid' => 0];
|
||||||
if (class_exists('\AKSRT\Payment\Withdrawal')) {
|
if (class_exists('\AKSRT\Payment\Withdrawal')) {
|
||||||
$withdrawal_stats = \AKSRT\Payment\Withdrawal::get_instance()->get_stats();
|
$withdrawal_stats = \AKSRT\Payment\Withdrawal::get_instance()->get_stats();
|
||||||
}
|
}
|
||||||
@@ -268,7 +268,7 @@ class PaymentController extends ControllerBase {
|
|||||||
$new_status = sanitize_key((string) ($params['status'] ?? ''));
|
$new_status = sanitize_key((string) ($params['status'] ?? ''));
|
||||||
$note = sanitize_textarea_field((string) ($params['note'] ?? ''));
|
$note = sanitize_textarea_field((string) ($params['note'] ?? ''));
|
||||||
|
|
||||||
$valid_statuses = ['pending', 'approved', 'processing', 'completed', 'rejected'];
|
$valid_statuses = ['pending', 'processing', 'completed', 'rejected'];
|
||||||
if (!in_array($new_status, $valid_statuses, true)) {
|
if (!in_array($new_status, $valid_statuses, true)) {
|
||||||
return $this->error('无效的提现状态');
|
return $this->error('无效的提现状态');
|
||||||
}
|
}
|
||||||
|
|||||||
+20
-2
@@ -18,6 +18,18 @@ class Rebate {
|
|||||||
const STATUS_SETTLED = 'settled';
|
const STATUS_SETTLED = 'settled';
|
||||||
const STATUS_CANCELLED = 'cancelled';
|
const STATUS_CANCELLED = 'cancelled';
|
||||||
|
|
||||||
|
private function refresh_user_metric(int $user_id): void {
|
||||||
|
if ($user_id <= 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
global $wpdb;
|
||||||
|
$total = (float) $wpdb->get_var($wpdb->prepare(
|
||||||
|
"SELECT COALESCE(SUM(amount), 0) FROM {$this->table()} WHERE user_id = %d AND status IN ('pending', 'settled')",
|
||||||
|
$user_id
|
||||||
|
));
|
||||||
|
update_user_meta($user_id, 'aksrt_pay_rebate_sum', round($total, 2));
|
||||||
|
}
|
||||||
|
|
||||||
public static function get_instance(): self {
|
public static function get_instance(): self {
|
||||||
if (null === self::$instance) {
|
if (null === self::$instance) {
|
||||||
self::$instance = new self();
|
self::$instance = new self();
|
||||||
@@ -62,7 +74,7 @@ class Rebate {
|
|||||||
'note' => $note,
|
'note' => $note,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$id = $result ? (int) $wpdb->insert_id : 0;
|
$id = $result ? (int) $wpdb->insert_id : 0;
|
||||||
if ($id > 0) {
|
if ($id > 0) {
|
||||||
do_action('aksrt_pay_rebate_added', $user_id, $amount, [
|
do_action('aksrt_pay_rebate_added', $user_id, $amount, [
|
||||||
'rebate_id' => $id,
|
'rebate_id' => $id,
|
||||||
@@ -123,6 +135,7 @@ class Rebate {
|
|||||||
}
|
}
|
||||||
|
|
||||||
$wpdb->query('COMMIT');
|
$wpdb->query('COMMIT');
|
||||||
|
$this->refresh_user_metric((int) $row['user_id']);
|
||||||
return true;
|
return true;
|
||||||
} catch (\Throwable $e) {
|
} catch (\Throwable $e) {
|
||||||
$wpdb->query('ROLLBACK');
|
$wpdb->query('ROLLBACK');
|
||||||
@@ -134,9 +147,14 @@ class Rebate {
|
|||||||
*/
|
*/
|
||||||
public function cancel(int $id): bool {
|
public function cancel(int $id): bool {
|
||||||
global $wpdb;
|
global $wpdb;
|
||||||
return (bool) $wpdb->update($this->table(), [
|
$updated = $wpdb->update($this->table(), [
|
||||||
'status' => self::STATUS_CANCELLED,
|
'status' => self::STATUS_CANCELLED,
|
||||||
], ['id' => $id, 'status' => self::STATUS_PENDING]);
|
], ['id' => $id, 'status' => self::STATUS_PENDING]);
|
||||||
|
if ($updated === 1) {
|
||||||
|
$row = $wpdb->get_row($wpdb->prepare("SELECT user_id FROM {$this->table()} WHERE id = %d", $id), ARRAY_A);
|
||||||
|
$this->refresh_user_metric((int) ($row['user_id'] ?? 0));
|
||||||
|
}
|
||||||
|
return $updated === 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
+12
-10
@@ -9,11 +9,10 @@ defined('ABSPATH') || exit;
|
|||||||
|
|
||||||
class Withdrawal {
|
class Withdrawal {
|
||||||
|
|
||||||
public const STATUS_PENDING = 'pending';
|
public const STATUS_PENDING = 'pending';
|
||||||
public const STATUS_APPROVED = 'approved';
|
public const STATUS_PROCESSING = 'processing';
|
||||||
public const STATUS_PROCESSING = 'processing';
|
public const STATUS_COMPLETED = 'completed';
|
||||||
public const STATUS_COMPLETED = 'completed';
|
public const STATUS_REJECTED = 'rejected';
|
||||||
public const STATUS_REJECTED = 'rejected';
|
|
||||||
|
|
||||||
private static $instance = null;
|
private static $instance = null;
|
||||||
|
|
||||||
@@ -99,7 +98,6 @@ class Withdrawal {
|
|||||||
$new_status = sanitize_key($new_status);
|
$new_status = sanitize_key($new_status);
|
||||||
$allowed = [
|
$allowed = [
|
||||||
self::STATUS_PENDING,
|
self::STATUS_PENDING,
|
||||||
self::STATUS_APPROVED,
|
|
||||||
self::STATUS_PROCESSING,
|
self::STATUS_PROCESSING,
|
||||||
self::STATUS_COMPLETED,
|
self::STATUS_COMPLETED,
|
||||||
self::STATUS_REJECTED,
|
self::STATUS_REJECTED,
|
||||||
@@ -195,7 +193,7 @@ class Withdrawal {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Whether user has open (pending/processing/approved) withdrawals.
|
* Whether user has open (pending/processing) withdrawals.
|
||||||
*/
|
*/
|
||||||
public function has_open_withdrawal(int $user_id): bool {
|
public function has_open_withdrawal(int $user_id): bool {
|
||||||
return $this->count_open($user_id) > 0;
|
return $this->count_open($user_id) > 0;
|
||||||
@@ -211,7 +209,7 @@ class Withdrawal {
|
|||||||
}
|
}
|
||||||
return (int) $wpdb->get_var($wpdb->prepare(
|
return (int) $wpdb->get_var($wpdb->prepare(
|
||||||
"SELECT COUNT(*) FROM {$this->table()}
|
"SELECT COUNT(*) FROM {$this->table()}
|
||||||
WHERE user_id = %d AND status IN ('pending','approved','processing')",
|
WHERE user_id = %d AND status IN ('pending','processing')",
|
||||||
$user_id
|
$user_id
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
@@ -226,7 +224,7 @@ class Withdrawal {
|
|||||||
}
|
}
|
||||||
$rows = $wpdb->get_results($wpdb->prepare(
|
$rows = $wpdb->get_results($wpdb->prepare(
|
||||||
"SELECT amount, account_info FROM {$this->table()}
|
"SELECT amount, account_info FROM {$this->table()}
|
||||||
WHERE user_id = %d AND status IN ('pending','approved','processing')",
|
WHERE user_id = %d AND status IN ('pending','processing')",
|
||||||
$user_id
|
$user_id
|
||||||
), ARRAY_A);
|
), ARRAY_A);
|
||||||
$total = 0.0;
|
$total = 0.0;
|
||||||
@@ -253,7 +251,7 @@ class Withdrawal {
|
|||||||
$params = [$user_id];
|
$params = [$user_id];
|
||||||
|
|
||||||
if (!empty($args['open_only'])) {
|
if (!empty($args['open_only'])) {
|
||||||
$where[] = "status IN ('pending','approved','processing')";
|
$where[] = "status IN ('pending','processing')";
|
||||||
} else {
|
} else {
|
||||||
$status = sanitize_key((string) ($args['status'] ?? ''));
|
$status = sanitize_key((string) ($args['status'] ?? ''));
|
||||||
if ($status !== '') {
|
if ($status !== '') {
|
||||||
@@ -326,6 +324,8 @@ class Withdrawal {
|
|||||||
"SELECT
|
"SELECT
|
||||||
COUNT(*) as total,
|
COUNT(*) as total,
|
||||||
SUM(CASE WHEN status = 'pending' THEN 1 ELSE 0 END) as pending,
|
SUM(CASE WHEN status = 'pending' THEN 1 ELSE 0 END) as pending,
|
||||||
|
SUM(CASE WHEN status = 'processing' THEN 1 ELSE 0 END) as processing,
|
||||||
|
SUM(CASE WHEN status = 'rejected' THEN 1 ELSE 0 END) as rejected,
|
||||||
SUM(CASE WHEN status = 'completed' THEN 1 ELSE 0 END) as completed,
|
SUM(CASE WHEN status = 'completed' THEN 1 ELSE 0 END) as completed,
|
||||||
COALESCE(SUM(CASE WHEN status = 'completed' THEN amount ELSE 0 END), 0) as total_paid
|
COALESCE(SUM(CASE WHEN status = 'completed' THEN amount ELSE 0 END), 0) as total_paid
|
||||||
FROM {$this->table()}",
|
FROM {$this->table()}",
|
||||||
@@ -335,6 +335,8 @@ class Withdrawal {
|
|||||||
return [
|
return [
|
||||||
'total' => (int) ($row['total'] ?? 0),
|
'total' => (int) ($row['total'] ?? 0),
|
||||||
'pending' => (int) ($row['pending'] ?? 0),
|
'pending' => (int) ($row['pending'] ?? 0),
|
||||||
|
'processing' => (int) ($row['processing'] ?? 0),
|
||||||
|
'rejected' => (int) ($row['rejected'] ?? 0),
|
||||||
'completed' => (int) ($row['completed'] ?? 0),
|
'completed' => (int) ($row['completed'] ?? 0),
|
||||||
'total_paid' => (float) ($row['total_paid'] ?? 0),
|
'total_paid' => (float) ($row['total_paid'] ?? 0),
|
||||||
];
|
];
|
||||||
|
|||||||
Reference in new issue
Block a user