refactor(classes): organize inc/classes into domain folders
Move ~94 root class shells and root *-traits into domain directories (core, auth, user, credits, content, payment/gateways, forum, shop, sms, ai, messages, extensions, widgets, settings, admin). Update bootstrap require paths, co-locate traits with owners, fix forum/user relative requires, drop duplicate shop controller requires, and wire home-modules load. Path-only; class names and init order unchanged.
This commit is contained in:
1 parent
2a8fe68048
commit
ce1c13b947
115 files changed
+171
-224
No files matched your search
@@ -0,0 +1,171 @@
|
||||
<?php
|
||||
/**
|
||||
* AKSRT Discount Engine
|
||||
*
|
||||
* 优惠活动计算引擎 — reduction 立减 / discount 打折 / gift 买赠。
|
||||
* scope: item / product / author / order。
|
||||
* 绑定在 shop_discount taxonomy 上,商品可挂多个活动。
|
||||
*
|
||||
* @package AKSRT
|
||||
*/
|
||||
|
||||
defined('ABSPATH') || exit;
|
||||
|
||||
class AKSRT_Discount {
|
||||
|
||||
private static $instance = null;
|
||||
|
||||
public static function get_instance(): self {
|
||||
if (null === self::$instance) {
|
||||
self::$instance = new self();
|
||||
}
|
||||
return self::$instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all active discount campaigns for a product.
|
||||
*
|
||||
* @param int $product_id
|
||||
* @return array<int, array> Sorted by priority desc.
|
||||
*/
|
||||
public function get_active_discounts(int $product_id): array {
|
||||
$terms = wp_get_object_terms($product_id, 'shop_discount', ['fields' => 'all']);
|
||||
if (is_wp_error($terms) || empty($terms)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$now = current_time('timestamp');
|
||||
$active = [];
|
||||
|
||||
foreach ($terms as $term) {
|
||||
$meta = AKSRT_Shop_Term_Meta::get_discount_meta($term->term_id);
|
||||
|
||||
// Time limit check
|
||||
if (!empty($meta['start']) && strtotime($meta['start']) > $now) {
|
||||
continue;
|
||||
}
|
||||
if (!empty($meta['end']) && strtotime($meta['end']) < $now) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$meta['term_id'] = $term->term_id;
|
||||
$meta['name'] = $term->name;
|
||||
$active[] = $meta;
|
||||
}
|
||||
|
||||
// Sort by priority desc
|
||||
usort($active, function ($a, $b) {
|
||||
return ((int) $b['priority']) - ((int) $a['priority']);
|
||||
});
|
||||
|
||||
return $active;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate discount for a single line item.
|
||||
*
|
||||
* @param float $unit_price Unit price
|
||||
* @param int $quantity Quantity
|
||||
* @param int $product_id Product ID
|
||||
* @param int $user_id User ID (for user_limit checks)
|
||||
* @return array{
|
||||
* original: float,
|
||||
* discount_amount: float,
|
||||
* final_price: float,
|
||||
* gifts: array,
|
||||
* applied: array<int, array>
|
||||
* }
|
||||
*/
|
||||
public function calculate(float $unit_price, int $quantity, int $product_id, int $user_id = 0): array {
|
||||
$original = $unit_price * $quantity;
|
||||
$discount_amount = 0.0;
|
||||
$gifts = [];
|
||||
$applied = [];
|
||||
|
||||
$discounts = $this->get_active_discounts($product_id);
|
||||
|
||||
foreach ($discounts as $d) {
|
||||
// User limit check
|
||||
if (!empty($d['user_limit']) && $user_id > 0) {
|
||||
if (!$this->check_user_limit($d['user_limit'], $user_id)) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// Price limit check
|
||||
if ((float) $d['price_limit'] > 0 && $original < (float) $d['price_limit']) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$type = $d['type'] ?? 'reduction';
|
||||
$value = (float) ($d['value'] ?? 0);
|
||||
|
||||
switch ($type) {
|
||||
case 'reduction':
|
||||
// 立减
|
||||
$discount_amount += min($value * $quantity, $original - $discount_amount);
|
||||
break;
|
||||
|
||||
case 'discount':
|
||||
// 打折 (value = 折扣系数 e.g. 8.5 = 85折)
|
||||
if ($value > 0 && $value < 10) {
|
||||
$rate = $value / 10.0;
|
||||
$save = ($original - $discount_amount) * (1 - $rate);
|
||||
$discount_amount += $save;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'gift':
|
||||
// 买赠 — collect gift config, no price reduction
|
||||
if (!empty($d['gift_config'])) {
|
||||
$gift_data = json_decode($d['gift_config'], true);
|
||||
if (is_array($gift_data)) {
|
||||
$gifts[] = $gift_data;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
$applied[] = [
|
||||
'term_id' => $d['term_id'],
|
||||
'name' => $d['name'] ?? '',
|
||||
'type' => $type,
|
||||
'value' => $value,
|
||||
];
|
||||
}
|
||||
|
||||
$discount_amount = min($discount_amount, $original);
|
||||
|
||||
return [
|
||||
'original' => $original,
|
||||
'discount_amount' => round($discount_amount, 2),
|
||||
'final_price' => round($original - $discount_amount, 2),
|
||||
'gifts' => $gifts,
|
||||
'applied' => $applied,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a user meets the user_limit requirement.
|
||||
*
|
||||
* @param string $limit 'vip' / 'vip_2' / 'auth'
|
||||
* @param int $user_id
|
||||
* @return bool
|
||||
*/
|
||||
private function check_user_limit(string $limit, int $user_id): bool {
|
||||
if (empty($limit)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
switch ($limit) {
|
||||
case 'vip':
|
||||
return function_exists('aksrt_is_vip') ? aksrt_is_vip($user_id) : false;
|
||||
case 'vip_2':
|
||||
return function_exists('aksrt_is_vip2') ? aksrt_is_vip2($user_id) : false;
|
||||
case 'auth':
|
||||
return function_exists('aksrt_is_verified') ? aksrt_is_verified($user_id) : false;
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user