feat(Core): add optimize and complete code
This commit is contained in:
@@ -11,7 +11,8 @@ class PricingService {
|
||||
private $trackingService;
|
||||
private $settings;
|
||||
private $cache;
|
||||
private $trackedApplications = [];
|
||||
private $appliedRules = [];
|
||||
private $trackedConversions = [];
|
||||
|
||||
public function __construct(RuleRepository $ruleRepository, TrackingService $trackingService) {
|
||||
$this->ruleRepository = $ruleRepository;
|
||||
@@ -29,7 +30,14 @@ class PricingService {
|
||||
return $price;
|
||||
}
|
||||
|
||||
if (!$product || !is_a($product, 'WC_Product')) {
|
||||
return $price;
|
||||
}
|
||||
|
||||
$price = $this->normalizePrice($price);
|
||||
if ($price <= 0) {
|
||||
return $price;
|
||||
}
|
||||
|
||||
if (!$this->settings->get('cart_pricing_enabled') && is_cart()) {
|
||||
return $price;
|
||||
@@ -50,8 +58,7 @@ class PricingService {
|
||||
foreach ($rules as $rule) {
|
||||
$oldPrice = $price;
|
||||
$price = $this->applyRuleActions($rule, $price);
|
||||
|
||||
$this->trackDiscountOnce($product, $oldPrice, $price, $rule->id);
|
||||
$this->rememberAppliedRule($product, $oldPrice, $price, $rule->id);
|
||||
}
|
||||
|
||||
$price = $this->enforceLimits($originalPrice, $price);
|
||||
@@ -59,6 +66,56 @@ class PricingService {
|
||||
return max(0, $price);
|
||||
}
|
||||
|
||||
public function getAppliedRulesForProduct($product) {
|
||||
if (!$product || !is_a($product, 'WC_Product')) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$keys = $this->getProductTrackingKeys($product);
|
||||
$rules = [];
|
||||
|
||||
foreach ($keys as $key) {
|
||||
if (!empty($this->appliedRules[$key])) {
|
||||
$rules = array_merge($rules, $this->appliedRules[$key]);
|
||||
}
|
||||
}
|
||||
|
||||
if (empty($rules)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$unique = [];
|
||||
foreach ($rules as $rule) {
|
||||
$unique[(int) $rule['rule_id']] = $rule;
|
||||
}
|
||||
|
||||
return array_values($unique);
|
||||
}
|
||||
|
||||
public function trackAppliedRulesForProduct($product) {
|
||||
foreach ($this->getAppliedRulesForProduct($product) as $rule) {
|
||||
$trackingKey = implode(':', [
|
||||
(int) $product->get_id(),
|
||||
(int) $rule['rule_id'],
|
||||
round((float) $rule['original_price'], 4),
|
||||
round((float) $rule['discounted_price'], 4),
|
||||
]);
|
||||
|
||||
if (isset($this->trackedConversions[$trackingKey])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$this->trackedConversions[$trackingKey] = true;
|
||||
$this->trackingService->recordDiscountApplied(
|
||||
$product,
|
||||
(float) $rule['original_price'],
|
||||
(float) $rule['discounted_price'],
|
||||
(int) $rule['rule_id']
|
||||
);
|
||||
$this->ruleRepository->incrementUsage((int) $rule['rule_id']);
|
||||
}
|
||||
}
|
||||
|
||||
private function getApplicableRules($product) {
|
||||
$rules = $this->ruleRepository->getEnabled();
|
||||
$applicable = [];
|
||||
@@ -160,6 +217,12 @@ class PricingService {
|
||||
return $this->getCustomerOrderCount() >= intval($value);
|
||||
case 'customer_order_count_max':
|
||||
return $this->getCustomerOrderCount() <= intval($value);
|
||||
case 'customer_days_since_last_order_min':
|
||||
return $this->getCustomerDaysSinceLastOrder() >= intval($value);
|
||||
case 'product_total_sales_max':
|
||||
return $this->getProductTotalSales($product) <= intval($value);
|
||||
case 'product_total_sales_min':
|
||||
return $this->getProductTotalSales($product) >= intval($value);
|
||||
case 'day_of_week':
|
||||
return in_array((string) current_time('N'), array_map('strval', $this->normalizeIdList($value)), true);
|
||||
default:
|
||||
@@ -195,6 +258,35 @@ class PricingService {
|
||||
return (int) wc_get_customer_order_count(get_current_user_id());
|
||||
}
|
||||
|
||||
private function getCustomerDaysSinceLastOrder() {
|
||||
if (!is_user_logged_in()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
$orders = wc_get_orders([
|
||||
'customer_id' => get_current_user_id(),
|
||||
'limit' => 1,
|
||||
'orderby' => 'date',
|
||||
'order' => 'DESC',
|
||||
'status' => ['wc-completed', 'wc-processing'],
|
||||
'return' => 'objects',
|
||||
]);
|
||||
|
||||
if (empty($orders)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
$date = $orders[0]->get_date_created();
|
||||
if (!$date) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
$lastOrderTimestamp = $date->getTimestamp();
|
||||
$now = current_time('timestamp', true);
|
||||
|
||||
return max(0, (int) floor(($now - $lastOrderTimestamp) / DAY_IN_SECONDS));
|
||||
}
|
||||
|
||||
private function userHasAllowedRole($roles) {
|
||||
if (!is_user_logged_in()) {
|
||||
return false;
|
||||
@@ -227,12 +319,36 @@ class PricingService {
|
||||
return $this->productHasTerm($product, $categories, 'product_cat');
|
||||
}
|
||||
|
||||
private function getProductTotalSales($product) {
|
||||
if (!$product || !is_a($product, 'WC_Product')) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
$productId = (int) $product->get_id();
|
||||
if ($product->is_type('variation') && method_exists($product, 'get_parent_id')) {
|
||||
$parentId = (int) $product->get_parent_id();
|
||||
if ($parentId > 0) {
|
||||
$productId = $parentId;
|
||||
}
|
||||
}
|
||||
|
||||
return (int) get_post_meta($productId, 'total_sales', true);
|
||||
}
|
||||
|
||||
private function productHasTerm($product, $terms, $taxonomy) {
|
||||
if (!$product || empty($terms)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$product_terms = wp_get_post_terms($product->get_id(), $taxonomy, ['fields' => 'ids']);
|
||||
$productId = (int) $product->get_id();
|
||||
if ($product->is_type('variation') && method_exists($product, 'get_parent_id')) {
|
||||
$parentId = (int) $product->get_parent_id();
|
||||
if ($parentId > 0) {
|
||||
$productId = $parentId;
|
||||
}
|
||||
}
|
||||
|
||||
$product_terms = wp_get_post_terms($productId, $taxonomy, ['fields' => 'ids']);
|
||||
if (is_wp_error($product_terms)) {
|
||||
return false;
|
||||
}
|
||||
@@ -428,16 +544,30 @@ class PricingService {
|
||||
return false;
|
||||
}
|
||||
|
||||
private function trackDiscountOnce($product, $oldPrice, $price, $ruleId) {
|
||||
$productId = $product ? $product->get_id() : 0;
|
||||
$key = implode(':', [$productId, (int) $ruleId, round($oldPrice, 4), round($price, 4)]);
|
||||
|
||||
if ($price >= $oldPrice || isset($this->trackedApplications[$key])) {
|
||||
private function rememberAppliedRule($product, $oldPrice, $price, $ruleId) {
|
||||
if ($price >= $oldPrice || !$product || !is_a($product, 'WC_Product')) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->trackedApplications[$key] = true;
|
||||
$this->trackingService->recordDiscountApplied($product, $oldPrice, $price, $ruleId);
|
||||
$this->ruleRepository->incrementUsage($ruleId);
|
||||
foreach ($this->getProductTrackingKeys($product) as $key) {
|
||||
$this->appliedRules[$key][(int) $ruleId] = [
|
||||
'rule_id' => (int) $ruleId,
|
||||
'original_price' => (float) $oldPrice,
|
||||
'discounted_price' => (float) $price,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
private function getProductTrackingKeys($product) {
|
||||
$keys = [(int) $product->get_id()];
|
||||
|
||||
if ($product->is_type('variation') && method_exists($product, 'get_parent_id')) {
|
||||
$parentId = (int) $product->get_parent_id();
|
||||
if ($parentId > 0) {
|
||||
$keys[] = $parentId;
|
||||
}
|
||||
}
|
||||
|
||||
return array_values(array_unique($keys));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user