积分与余额账务系统硬切重构

This commit is contained in:
2026-08-24 15:59:11 +08:00
parent ca12226b39
commit 5cae5b5c93
159 changed files with 7275 additions and 4718 deletions
+1 -1
View File
@@ -154,7 +154,7 @@ class AuthApply {
'msg' => (string) ($application['manual_reason'] ?? ''),
'type' => (string) ($application['type'] ?? ''),
'time' => (string) ($application['created_at'] ?? ''),
'fee' => (float) ($application['fee_amount'] ?? 0),
'fee' => (string) ($application['fee_amount'] ?? '0.00'),
'_application' => $application,
];
}
+19 -9
View File
@@ -609,9 +609,25 @@ class Badges {
if ($type === '' || $type === 'manually_add') {
continue;
}
$need = max(0, (float) ($item['get_val'] ?? 0));
$have = (float) self::metric_value($user_id, $type);
if ($have >= $need) {
if (in_array($type, ['creator_income', 'affiliate_commission'], true)) {
try {
$need_minor = \AKSRT\Ledger\AssetAmount::balance((string) ($item['get_val'] ?? '0'))->minor();
} catch (\InvalidArgumentException $e) {
continue;
}
$reason = $type;
$have_minor = \AKSRT\Ledger\LedgerQuery::get_instance()->sum_positive(
$user_id,
\AKSRT\Ledger\AssetType::BALANCE,
$reason
);
$qualified = $have_minor >= $need_minor;
} else {
$need = max(0, (float) ($item['get_val'] ?? 0));
$have = (float) self::metric_value($user_id, $type);
$qualified = $have >= $need;
}
if ($qualified) {
self::grant($user_id, $slug, 0);
$owned_map[$slug] = true;
}
@@ -678,12 +694,6 @@ class Badges {
}
return $sum;
case 'pay_income':
return (float) get_user_meta($user_id, 'aksrt_pay_income_sum', true);
case 'pay_rebate':
return (float) get_user_meta($user_id, 'aksrt_pay_rebate_sum', true);
default:
return 0.0;
}
+45 -33
View File
@@ -27,7 +27,7 @@ class BalanceAdmin {
add_filter('manage_users_columns', [$this, 'add_column']);
add_filter('manage_users_custom_column', [$this, 'render_column'], 10, 3);
add_filter('manage_users_sortable_columns', [$this, 'sortable']);
add_action('pre_get_users', [$this, 'sort_users']);
add_action('pre_user_query', [$this, 'sort_users']);
add_action('show_user_profile', [$this, 'render_section']);
add_action('edit_user_profile', [$this, 'render_section']);
add_action('personal_options_update', [$this, 'handle_update']);
@@ -38,8 +38,13 @@ class BalanceAdmin {
return current_user_can('manage_options');
}
private function enabled(): bool {
$cfg = class_exists('\\AKSRT\\Settings\\Settings') ? \AKSRT\Settings\Settings::get_payment_recharge_settings() : [];
return !empty($cfg['enabled']);
}
public function add_column(array $columns): array {
if (!class_exists('\AKSRT\Credits\Balance') || !\AKSRT\Credits\Balance::enabled()) {
if (!$this->enabled()) {
return $columns;
}
$columns['aksrt_wallet_balance'] = __('现金余额', 'aksrt');
@@ -50,10 +55,7 @@ class BalanceAdmin {
if ($column_name !== 'aksrt_wallet_balance') {
return $output;
}
if (!class_exists('\AKSRT\Credits\Balance')) {
return '—';
}
return '<strong>' . esc_html(\AKSRT\Credits\Balance::format(\AKSRT\Credits\Balance::balance($user_id))) . '</strong>';
return '<strong>' . esc_html(\AKSRT\Ledger\AssetAmount::from_minor(\AKSRT\Ledger\AssetType::BALANCE, \AKSRT\Ledger\LedgerService::get_instance()->balance($user_id, \AKSRT\Ledger\AssetType::BALANCE))->formatted()) . '</strong>';
}
public function sortable(array $columns): array {
@@ -62,38 +64,42 @@ class BalanceAdmin {
}
public function sort_users($query): void {
if (!is_admin() || $query->get('orderby') !== 'aksrt_wallet_balance') {
if (!is_admin() || ($query->query_vars['orderby'] ?? '') !== 'aksrt_wallet_balance') {
return;
}
$query->set('meta_key', 'aksrt_balance');
$query->set('orderby', 'meta_value_num');
global $wpdb;
$table = \AKSRT\Core\DBMigrator::table('asset_account');
$query->query_from .= $wpdb->prepare(" LEFT JOIN {$table} aksrt_cash_account ON aksrt_cash_account.user_id = {$wpdb->users}.ID AND aksrt_cash_account.asset = %s", \AKSRT\Ledger\AssetType::BALANCE->value);
$order = strtoupper((string) ($query->query_vars['order'] ?? 'DESC')) === 'ASC' ? 'ASC' : 'DESC';
$query->query_orderby = "ORDER BY COALESCE(aksrt_cash_account.balance_minor, 0) {$order}";
}
public function render_section(\WP_User $user): void {
if (!class_exists('\AKSRT\Credits\Balance') || !\AKSRT\Credits\Balance::enabled()) {
if (!$this->enabled()) {
return;
}
$balance = \AKSRT\Credits\Balance::balance((int) $user->ID);
$balance_minor = \AKSRT\Ledger\LedgerService::get_instance()->balance((int) $user->ID, \AKSRT\Ledger\AssetType::BALANCE);
$can = $this->can_manage();
$log = \AKSRT\Credits\Balance::get_log(['user_id' => (int) $user->ID, 'page' => 1, 'per_page' => 8]);
$log = \AKSRT\Ledger\LedgerQuery::get_instance()->history(['user_id' => (int) $user->ID, 'asset' => 'balance', 'page' => 1, 'per_page' => 8]);
?>
<a id="aksrt-user-wallet"></a>
<h2><?php esc_html_e('现金钱包(AKSRT)', 'aksrt'); ?></h2>
<table class="form-table" role="presentation">
<tr>
<th><?php esc_html_e('当前余额', 'aksrt'); ?></th>
<td><strong style="font-size:18px;"><?php echo esc_html(\AKSRT\Credits\Balance::format($balance)); ?></strong> <?php esc_html_e('元', 'aksrt'); ?></td>
<td><strong style="font-size:18px;"><?php echo esc_html(\AKSRT\Ledger\AssetAmount::from_minor(\AKSRT\Ledger\AssetType::BALANCE, $balance_minor)->formatted()); ?></strong> <?php esc_html_e('元', 'aksrt'); ?></td>
</tr>
<?php if ($can) : ?>
<tr>
<th><?php esc_html_e('调整余额', 'aksrt'); ?></th>
<td>
<?php wp_nonce_field('aksrt_user_balance_adjust_' . (int) $user->ID, '_aksrt_balance_nonce'); ?>
<label for="aksrt_balance_delta"><?php esc_html_e('变动金额(正数=增加,负数=扣减)', 'aksrt'); ?></label><br>
<input type="number" step="0.01" name="aksrt_balance_delta" id="aksrt_balance_delta" value="" class="regular-text" />
<?php wp_nonce_field('aksrt_user_cash_adjust_' . (int) $user->ID, '_aksrt_cash_nonce'); ?>
<input type="hidden" name="aksrt_cash_operation_key" value="<?php echo esc_attr(wp_generate_uuid4()); ?>">
<label for="aksrt_cash_delta"><?php esc_html_e('变动金额(正数=增加,负数=扣减)', 'aksrt'); ?></label><br>
<input type="number" step="0.01" name="aksrt_cash_delta" id="aksrt_cash_delta" value="" class="regular-text" />
<p>
<label for="aksrt_balance_reason"><?php esc_html_e('备注', 'aksrt'); ?></label><br>
<input type="text" name="aksrt_balance_reason" id="aksrt_balance_reason" class="regular-text" />
<label for="aksrt_cash_reason"><?php esc_html_e('备注', 'aksrt'); ?></label><br>
<input type="text" name="aksrt_cash_reason" id="aksrt_cash_reason" class="regular-text" />
</p>
<p class="description"><?php esc_html_e('保存用户资料时生效,并写入余额流水。', 'aksrt'); ?></p>
</td>
@@ -109,9 +115,9 @@ class BalanceAdmin {
<?php foreach ($log['items'] as $row) : ?>
<tr>
<td><?php echo esc_html(get_date_from_gmt((string) ($row['created_at'] ?? ''), 'Y-m-d H:i')); ?></td>
<td><?php echo esc_html(($row['delta'] > 0 ? '+' : '') . \AKSRT\Credits\Balance::format((float) $row['delta'])); ?></td>
<td><?php echo esc_html(\AKSRT\Credits\Balance::format((float) ($row['balance_after'] ?? 0))); ?></td>
<td><?php echo esc_html(\AKSRT\Credits\Balance::reason_label((string) ($row['reason'] ?? ''))); ?></td>
<td><?php echo esc_html(((int) $row['delta_minor'] > 0 ? '+' : '-') . \AKSRT\Ledger\AssetAmount::from_minor(\AKSRT\Ledger\AssetType::BALANCE, abs((int) $row['delta_minor']))->formatted()); ?></td>
<td><?php echo esc_html(\AKSRT\Ledger\AssetAmount::from_minor(\AKSRT\Ledger\AssetType::BALANCE, (int) ($row['balance_after_minor'] ?? 0))->formatted()); ?></td>
<td><?php echo esc_html(\AKSRT\Ledger\LedgerPresentation::reason_label((string) ($row['reason'] ?? ''))); ?></td>
</tr>
<?php endforeach; ?>
</tbody>
@@ -126,27 +132,33 @@ class BalanceAdmin {
}
public function handle_update(int $user_id): void {
if (!$this->can_manage() || !class_exists('\AKSRT\Credits\Balance') || !\AKSRT\Credits\Balance::enabled()) {
if (!$this->can_manage() || !$this->enabled()) {
return;
}
if (empty($_POST['_aksrt_balance_nonce']) || !wp_verify_nonce(sanitize_text_field(wp_unslash((string) $_POST['_aksrt_balance_nonce'])), 'aksrt_user_balance_adjust_' . $user_id)) {
if (!current_user_can('edit_user', $user_id)) {
return;
}
if (!isset($_POST['aksrt_balance_delta']) || $_POST['aksrt_balance_delta'] === '') {
if (empty($_POST['_aksrt_cash_nonce']) || !wp_verify_nonce(sanitize_text_field(wp_unslash((string) $_POST['_aksrt_cash_nonce'])), 'aksrt_user_cash_adjust_' . $user_id)) {
return;
}
$delta = round((float) wp_unslash($_POST['aksrt_balance_delta']), 2);
if (abs($delta) < 0.0001) {
if (!isset($_POST['aksrt_cash_delta']) || $_POST['aksrt_cash_delta'] === '') {
return;
}
$reason = isset($_POST['aksrt_balance_reason'])
? sanitize_text_field(wp_unslash((string) $_POST['aksrt_balance_reason']))
$raw_delta = trim((string) wp_unslash($_POST['aksrt_cash_delta']));
$negative = str_starts_with($raw_delta, '-');
try { $amount = \AKSRT\Ledger\AssetAmount::balance($negative ? substr($raw_delta, 1) : $raw_delta); }
catch (\InvalidArgumentException $e) { return; }
if ($amount->minor() <= 0) return;
$reason = isset($_POST['aksrt_cash_reason'])
? sanitize_text_field(wp_unslash((string) $_POST['aksrt_cash_reason']))
: __('管理员调整', 'aksrt');
if ($delta > 0) {
$result = \AKSRT\Credits\Balance::add($user_id, $delta, 'admin', ['type' => 'user', 'id' => get_current_user_id()], $reason);
} else {
$result = \AKSRT\Credits\Balance::deduct($user_id, abs($delta), 'admin', ['type' => 'user', 'id' => get_current_user_id()], $reason);
}
$request_key = isset($_POST['aksrt_cash_operation_key']) ? sanitize_text_field((string) wp_unslash($_POST['aksrt_cash_operation_key'])) : '';
if (!wp_is_uuid($request_key)) return;
$operation_key = \AKSRT\Ledger\OperationKey::deterministic('admin-balance-adjustment', [get_current_user_id(), $request_key]);
$ledger = \AKSRT\Ledger\LedgerService::get_instance();
$result = $negative
? $ledger->debit($user_id, \AKSRT\Ledger\AssetType::BALANCE, $amount->minor(), $operation_key, 'admin_adjustment', ['type' => 'user', 'id' => $user_id], $reason, get_current_user_id())
: $ledger->credit($user_id, \AKSRT\Ledger\AssetType::BALANCE, $amount->minor(), $operation_key, 'admin_adjustment', ['type' => 'user', 'id' => $user_id], $reason, get_current_user_id());
if (is_wp_error($result)) {
set_transient('aksrt_admin_notice_' . get_current_user_id(), [[
'type' => 'error',
+2 -1
View File
@@ -217,7 +217,8 @@ class Center {
$level_on = class_exists('\AKSRT\User\Level')
&& !empty(\AKSRT\User\Level::settings()['enabled']);
$credits_on = class_exists('\AKSRT\Settings\Settings') && \AKSRT\Settings\Settings::credits_enabled();
$balance_on = class_exists('\AKSRT\Credits\Balance') && \AKSRT\Credits\Balance::enabled();
$recharge = class_exists('\AKSRT\Settings\Settings') ? \AKSRT\Settings\Settings::get_payment_recharge_settings() : [];
$balance_on = !empty($recharge['enabled']);
$revenue_tab_on = class_exists('\AKSRT\Settings\Settings')
&& \AKSRT\Settings\Settings::referral_enabled();
$creator_tab_on = class_exists('\AKSRT\Settings\Settings')
+58 -70
View File
@@ -22,7 +22,7 @@ class CreditsAdmin {
add_filter('manage_users_columns', [$this, 'add_balance_column']);
add_filter('manage_users_custom_column', [$this, 'render_balance_column'], 10, 3);
add_filter('manage_users_sortable_columns', [$this, 'make_balance_sortable']);
add_action('pre_get_users', [$this, 'sort_users_by_credits']);
add_action('pre_user_query', [$this, 'sort_users_by_credits']);
add_filter('user_row_actions', [$this, 'add_row_actions'], 30, 2);
add_action('show_user_profile', [$this, 'render_user_credits_section']);
@@ -39,7 +39,7 @@ class CreditsAdmin {
public function add_balance_column(array $columns): array {
$currency_name = class_exists('\AKSRT\Settings\Settings') ? \AKSRT\Settings\Settings::get_currency_name() : __('积分', 'aksrt');
$columns['aksrt_credits_balance'] = sprintf(__('%s余额', 'aksrt'), $currency_name);
$columns['aksrt_points_balance'] = sprintf(__('%s余额', 'aksrt'), $currency_name);
$columns['aksrt_user_commerce'] = __('资产/分成', 'aksrt');
return $columns;
}
@@ -48,20 +48,14 @@ class CreditsAdmin {
if ($column_name === 'aksrt_user_commerce') {
return $this->render_commerce_column($user_id);
}
if ($column_name !== 'aksrt_credits_balance') {
if ($column_name !== 'aksrt_points_balance') {
return $output;
}
if (!class_exists('\AKSRT\Credits\Credits')) {
return '—';
}
$balance = \AKSRT\Credits\Credits::balance($user_id);
$balance = \AKSRT\Ledger\LedgerService::get_instance()->balance($user_id, \AKSRT\Ledger\AssetType::POINTS);
return '<strong>' . esc_html((string) $balance) . '</strong>';
}
/**
* Compact commerce snapshot: VIP, revenue, rebate, download logs link.
*/
/** Compact commerce snapshot: VIP, creator revenue, and operational links. */
private function render_commerce_column(int $user_id): string {
$bits = [];
if (function_exists('aksrt_get_user_vip_level')) {
@@ -74,34 +68,26 @@ class CreditsAdmin {
$stats = \AKSRT\Payment\Revenue::get_instance()->get_stats($user_id);
$cash = (array) ($stats['cash'] ?? []);
$points = (array) ($stats['points'] ?? []);
if ((float) ($cash['total'] ?? 0) > 0 || (float) ($cash['pending'] ?? 0) > 0) {
if ((string) ($cash['total'] ?? '0.00') !== '0.00' || (string) ($cash['pending'] ?? '0.00') !== '0.00') {
$bits[] = sprintf(
/* translators: 1 total 2 pending */
esc_html__('现金分成 ¥%1$s(待结 ¥%2$s)', 'aksrt'),
number_format((float) ($cash['total'] ?? 0), 2),
number_format((float) ($cash['pending'] ?? 0), 2)
(string) ($cash['total'] ?? '0.00'),
(string) ($cash['pending'] ?? '0.00')
);
}
if ((float) ($points['total'] ?? 0) > 0 || (float) ($points['pending'] ?? 0) > 0) {
if ((int) ($points['total'] ?? 0) > 0 || (int) ($points['pending'] ?? 0) > 0) {
$bits[] = sprintf(
/* translators: 1 total 2 pending */
esc_html__('积分分成 %1$s(待结 %2$s)', 'aksrt'),
number_format((float) ($points['total'] ?? 0), 0),
number_format((float) ($points['pending'] ?? 0), 0)
number_format_i18n((int) ($points['total'] ?? 0)),
number_format_i18n((int) ($points['pending'] ?? 0))
);
}
if ($bits) {
$bits[] = '<a href="' . esc_url(admin_url('admin.php?page=aksrt_income&user_id=' . $user_id)) . '">' . esc_html__('分成明细', 'aksrt') . '</a>';
}
}
if (class_exists('\AKSRT\Payment\Rebate')) {
$list = \AKSRT\Payment\Rebate::get_instance()->get_list(['user_id' => $user_id, 'limit' => 1]);
$total_r = (int) ($list['total'] ?? 0);
if ($total_r > 0) {
$bits[] = sprintf(esc_html__('返佣 %d 笔', 'aksrt'), $total_r);
$bits[] = '<a href="' . esc_url(admin_url('admin.php?page=aksrt_rebate&user_id=' . $user_id)) . '">' . esc_html__('返佣', 'aksrt') . '</a>';
}
}
$bits[] = '<a href="' . esc_url(admin_url('admin.php?page=aksrt_download_logs&user_id=' . $user_id)) . '">' . esc_html__('下载记录', 'aksrt') . '</a>';
$bits[] = '<a href="' . esc_url(admin_url('admin.php?page=aksrt_orders&user_id=' . $user_id)) . '">' . esc_html__('订单', 'aksrt') . '</a>';
@@ -112,19 +98,19 @@ class CreditsAdmin {
}
public function make_balance_sortable(array $columns): array {
$columns['aksrt_credits_balance'] = 'aksrt_credits_balance';
$columns['aksrt_points_balance'] = 'aksrt_points_balance';
return $columns;
}
public function sort_users_by_credits($query): void {
if (!is_admin()) {
if (!is_admin() || ($query->query_vars['orderby'] ?? '') !== 'aksrt_points_balance') {
return;
}
if ($query->get('orderby') !== 'aksrt_credits_balance') {
return;
}
$query->set('meta_key', 'aksrt_credits');
$query->set('orderby', 'meta_value_num');
global $wpdb;
$table = \AKSRT\Core\DBMigrator::table('asset_account');
$query->query_from .= $wpdb->prepare(" LEFT JOIN {$table} aksrt_points_account ON aksrt_points_account.user_id = {$wpdb->users}.ID AND aksrt_points_account.asset = %s", \AKSRT\Ledger\AssetType::POINTS->value);
$order = strtoupper((string) ($query->query_vars['order'] ?? 'DESC')) === 'ASC' ? 'ASC' : 'DESC';
$query->query_orderby = "ORDER BY COALESCE(aksrt_points_account.balance_minor, 0) {$order}";
}
// ========== 用户列表:行操作 ==========
@@ -155,11 +141,7 @@ class CreditsAdmin {
// ========== 用户编辑页:积分管理区块 ==========
public function render_user_credits_section(\WP_User $user): void {
if (!class_exists('\AKSRT\Credits\Credits')) {
return;
}
$balance = \AKSRT\Credits\Credits::balance((int) $user->ID);
$balance = \AKSRT\Ledger\LedgerService::get_instance()->balance((int) $user->ID, \AKSRT\Ledger\AssetType::POINTS);
$can_manage = $this->can_manage_credits();
$currency_name = class_exists('\AKSRT\Settings\Settings') ? \AKSRT\Settings\Settings::get_currency_name() : __('积分', 'aksrt');
?>
@@ -178,15 +160,16 @@ class CreditsAdmin {
<tr>
<th><?php echo esc_html(sprintf(__('调整%s', 'aksrt'), $currency_name)); ?></th>
<td>
<?php wp_nonce_field('aksrt_user_credits_adjust_' . (int) $user->ID, '_aksrt_credits_nonce'); ?>
<?php wp_nonce_field('aksrt_user_points_adjust_' . (int) $user->ID, '_aksrt_points_nonce'); ?>
<input type="hidden" name="aksrt_points_operation_key" value="<?php echo esc_attr(wp_generate_uuid4()); ?>">
<fieldset>
<label for="aksrt_credits_delta" style="display:block;margin-bottom:6px;">
<label for="aksrt_points_delta" style="display:block;margin-bottom:6px;">
<?php esc_html_e('变动数量(正数=增加,负数=扣减)', 'aksrt'); ?>
</label>
<input
type="number"
id="aksrt_credits_delta"
name="aksrt_credits_delta"
id="aksrt_points_delta"
name="aksrt_points_delta"
class="regular-text"
min="-100000"
max="100000"
@@ -197,16 +180,16 @@ class CreditsAdmin {
<?php esc_html_e('填写 0 不会执行任何变更。', 'aksrt'); ?>
</p>
<label for="aksrt_credits_reason" style="display:block;margin-bottom:6px;">
<label for="aksrt_points_reason" style="display:block;margin-bottom:6px;">
<?php esc_html_e('调整原因', 'aksrt'); ?>
</label>
<input
type="text"
id="aksrt_credits_reason"
name="aksrt_credits_reason"
id="aksrt_points_reason"
name="aksrt_points_reason"
class="regular-text"
maxlength="100"
placeholder="<?php echo esc_attr__('例如:手工补偿 / 运营赠送 / 退款修正', 'aksrt'); ?>"
placeholder="<?php echo esc_attr__('例如:运营赠送 / 活动奖励 / 人工核账', 'aksrt'); ?>"
>
<p class="description">
<?php esc_html_e('勾选后点击页面底部"更新用户"保存即可生效。', 'aksrt'); ?>
@@ -220,17 +203,8 @@ class CreditsAdmin {
<?php
// ========== 近期积分流水 ==========
$log = \AKSRT\Credits\Credits::get_log(['user_id' => (int) $user->ID, 'page' => 1, 'per_page' => 20]);
$log = \AKSRT\Ledger\LedgerQuery::get_instance()->history(['user_id' => (int) $user->ID, 'asset' => 'points', 'page' => 1, 'per_page' => 20]);
$items = $log['items'] ?? [];
$reason_labels = [
'register' => __('注册赠送', 'aksrt'),
'signin' => __('每日签到', 'aksrt'),
'comment' => __('评论奖励', 'aksrt'),
'referral' => __('推广注册奖励', 'aksrt'),
'referral_new_user' => __('推广注册新用户奖励', 'aksrt'),
'download' => __('下载消费', 'aksrt'),
'admin' => __('管理员调整', 'aksrt'),
];
?>
<h3 style="margin-top:24px;"><?php echo esc_html(sprintf(__('近期%s流水', 'aksrt'), $currency_name)); ?></h3>
<?php if (!empty($items)) : ?>
@@ -246,9 +220,9 @@ class CreditsAdmin {
</thead>
<tbody>
<?php foreach ($items as $row) :
$delta = (int) $row['delta'];
$delta = (int) $row['delta_minor'];
$reason_key = (string) ($row['reason'] ?? '');
$label = $reason_labels[$reason_key] ?? $reason_key;
$label = \AKSRT\Ledger\LedgerPresentation::reason_label($reason_key);
?>
<tr>
<td><?php echo esc_html(get_date_from_gmt((string) $row['created_at'], 'Y-m-d H:i')); ?></td>
@@ -257,7 +231,7 @@ class CreditsAdmin {
<td style="color:<?php echo $delta >= 0 ? '#16a34a' : '#ef4444'; ?>; font-weight:600;">
<?php echo esc_html(($delta > 0 ? '+' : '') . $delta); ?>
</td>
<td><?php echo esc_html((string) (int) $row['balance_after']); ?></td>
<td><?php echo esc_html((string) (int) $row['balance_after_minor']); ?></td>
</tr>
<?php endforeach; ?>
</tbody>
@@ -270,23 +244,36 @@ class CreditsAdmin {
// ========== 处理积分调整 ==========
public function handle_user_credits_update(int $user_id): void {
if (!$this->can_manage_credits() || !class_exists('\AKSRT\Credits\Credits')) {
if (!$this->can_manage_credits()) {
return;
}
if (!current_user_can('edit_user', $user_id)) {
return;
}
if (!isset($_POST['_aksrt_credits_nonce'])) {
if (!isset($_POST['_aksrt_points_nonce'])) {
return;
}
$nonce = sanitize_text_field((string) $_POST['_aksrt_credits_nonce']);
if (!wp_verify_nonce($nonce, 'aksrt_user_credits_adjust_' . $user_id)) {
$nonce = sanitize_text_field((string) $_POST['_aksrt_points_nonce']);
if (!wp_verify_nonce($nonce, 'aksrt_user_points_adjust_' . $user_id)) {
return;
}
$delta = isset($_POST['aksrt_credits_delta']) ? (int) $_POST['aksrt_credits_delta'] : 0;
$reason = isset($_POST['aksrt_credits_reason']) ? sanitize_text_field((string) wp_unslash($_POST['aksrt_credits_reason'])) : '';
$raw_delta = isset($_POST['aksrt_points_delta'])
? trim((string) wp_unslash($_POST['aksrt_points_delta']))
: '';
$unsigned_delta = str_starts_with($raw_delta, '-') ? substr($raw_delta, 1) : $raw_delta;
$max_integer = (string) PHP_INT_MAX;
if (
!preg_match('/^-?(?:0|[1-9]\d*)$/', $raw_delta)
|| strlen($unsigned_delta) > strlen($max_integer)
|| (strlen($unsigned_delta) === strlen($max_integer) && strcmp($unsigned_delta, $max_integer) > 0)
) {
return;
}
$delta = (int) $raw_delta;
$reason = isset($_POST['aksrt_points_reason']) ? sanitize_text_field((string) wp_unslash($_POST['aksrt_points_reason'])) : '';
$request_key = isset($_POST['aksrt_points_operation_key']) ? sanitize_text_field((string) wp_unslash($_POST['aksrt_points_operation_key'])) : '';
if ($delta === 0) {
return;
@@ -300,11 +287,12 @@ class CreditsAdmin {
return;
}
if ($delta > 0) {
$result = \AKSRT\Credits\Credits::add($user_id, $delta, 'admin', ['type' => 'user', 'id' => get_current_user_id()], $reason);
} else {
$result = \AKSRT\Credits\Credits::deduct($user_id, abs($delta), 'admin', ['type' => 'user', 'id' => get_current_user_id()], $reason);
}
if (!wp_is_uuid($request_key)) return;
$operation_key = \AKSRT\Ledger\OperationKey::deterministic('admin-points-adjustment', [get_current_user_id(), $request_key]);
$ledger = \AKSRT\Ledger\LedgerService::get_instance();
$result = $delta > 0
? $ledger->credit($user_id, \AKSRT\Ledger\AssetType::POINTS, $delta, $operation_key, 'admin_adjustment', ['type' => 'user', 'id' => $user_id], $reason, get_current_user_id())
: $ledger->debit($user_id, \AKSRT\Ledger\AssetType::POINTS, abs($delta), $operation_key, 'admin_adjustment', ['type' => 'user', 'id' => $user_id], $reason, get_current_user_id());
if (is_wp_error($result)) {
set_transient('aksrt_admin_notice_' . get_current_user_id(), [[
@@ -316,7 +304,7 @@ class CreditsAdmin {
set_transient('aksrt_admin_notice_' . get_current_user_id(), [[
'type' => 'success',
'msg' => sprintf(__('%s调整成功,当前余额:%d', 'aksrt'), $currency_name, (int) $result),
'msg' => sprintf(__('%s调整成功,当前余额:%d', 'aksrt'), $currency_name, $result->balance($user_id, \AKSRT\Ledger\AssetType::POINTS)),
]], 30);
}
}
+16 -33
View File
@@ -12,9 +12,6 @@ class Metrics {
public const META_POST_LIKE_SUM = 'aksrt_posts_like_sum';
public const META_COMMENT_LIKE_SUM = 'aksrt_comment_like_sum';
public const META_POSTS_VIEWS_SUM = 'aksrt_posts_views_sum';
public const META_PAY_INCOME = 'aksrt_pay_income_sum';
public const META_PAY_INCOME_POINTS = 'aksrt_pay_income_points_sum';
public const META_PAY_REBATE = 'aksrt_pay_rebate_sum';
public const META_CHECKIN_ALL_DAY = 'aksrt_checkin_all_day';
/** @var self|null */
@@ -34,8 +31,7 @@ class Metrics {
add_action('aksrt_post_viewed', [$this, 'on_post_viewed'], 20, 2);
add_action('aksrt_user_signed_in', [$this, 'on_user_signed_in'], 20, 1);
add_action('aksrt_creator_income_added', [$this, 'on_creator_income_added'], 20, 3);
add_action('aksrt_pay_rebate_added', [$this, 'on_pay_rebate_added'], 20, 3);
add_action('aksrt_asset_transaction_committed', [$this, 'on_asset_transaction_committed'], 20, 2);
}
public static function bump_user_meta(int $user_id, string $meta_key, float $delta = 1.0): float {
@@ -119,36 +115,23 @@ class Metrics {
self::reevaluate_medals($user_id);
}
/**
* @param int $user_id
* @param float $amount
* @param array $context
*/
public function on_creator_income_added($user_id, $amount, $context = []): void {
$currency = sanitize_key((string) ($context['currency'] ?? 'CNY'));
$user_id = (int) $user_id;
$amount = (float) $amount;
if ($user_id <= 0 || $amount <= 0) {
public function on_asset_transaction_committed($result, $command): void {
if (!$result instanceof \AKSRT\Ledger\LedgerResult || !$command instanceof \AKSRT\Ledger\LedgerCommand) {
return;
}
$meta_key = $currency === 'points' ? self::META_PAY_INCOME_POINTS : self::META_PAY_INCOME;
self::bump_user_meta($user_id, $meta_key, $amount);
self::reevaluate_medals($user_id);
if (!in_array($command->reason, ['creator_income', 'affiliate_commission'], true)) {
return;
}
$users = [];
foreach ($result->entries as $entry) {
$user_id = (int) ($entry['user_id'] ?? 0);
if ($user_id > 0 && (int) ($entry['delta_minor'] ?? 0) > 0) {
$users[$user_id] = true;
}
}
foreach (array_keys($users) as $user_id) {
self::reevaluate_medals((int) $user_id);
}
}
/**
* @param int $user_id
* @param float $amount
* @param array $context
*/
public function on_pay_rebate_added($user_id, $amount, $context = []): void {
unset($context);
$user_id = (int) $user_id;
$amount = (float) $amount;
if ($user_id <= 0 || $amount <= 0) {
return;
}
self::bump_user_meta($user_id, self::META_PAY_REBATE, $amount);
self::reevaluate_medals($user_id);
}
}