feat: Implement upsell functionality with repository and service layers
This commit is contained in:
137
app/Services/TrackingService.php
Normal file
137
app/Services/TrackingService.php
Normal file
@@ -0,0 +1,137 @@
|
||||
<?php
|
||||
namespace Sodino\Services;
|
||||
|
||||
use Sodino\Repositories\EventRepository;
|
||||
|
||||
class TrackingService {
|
||||
private $eventRepository;
|
||||
private $loggedEvents = [];
|
||||
|
||||
public function __construct(EventRepository $eventRepository) {
|
||||
$this->eventRepository = $eventRepository;
|
||||
}
|
||||
|
||||
public function trackProductView($product_id) {
|
||||
if (!$product_id) {
|
||||
return;
|
||||
}
|
||||
|
||||
$session_key = 'sodino_viewed_' . intval($product_id);
|
||||
if ($this->hasLogged($session_key)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->logEvent('product_view', [
|
||||
'product_id' => $product_id,
|
||||
]);
|
||||
$this->markLogged($session_key);
|
||||
}
|
||||
|
||||
public function trackAddToCart($product_id, $variation_id = null, $quantity = 1) {
|
||||
if (!$product_id) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->logEvent('add_to_cart', [
|
||||
'product_id' => $product_id,
|
||||
'variation_id' => $variation_id,
|
||||
'value' => floatval($quantity),
|
||||
]);
|
||||
}
|
||||
|
||||
public function trackCheckoutStart() {
|
||||
$this->logEvent('checkout_start', []);
|
||||
}
|
||||
|
||||
public function trackPurchase($order_id) {
|
||||
if (!$order_id) {
|
||||
return;
|
||||
}
|
||||
|
||||
$order = wc_get_order($order_id);
|
||||
if (!$order) {
|
||||
return;
|
||||
}
|
||||
|
||||
$total = floatval($order->get_total());
|
||||
$discount = 0;
|
||||
if (method_exists($order, 'get_total_discount')) {
|
||||
$discount = floatval($order->get_total_discount());
|
||||
} else {
|
||||
foreach ($order->get_items() as $item) {
|
||||
$discount += floatval($item->get_subtotal()) - floatval($item->get_total());
|
||||
}
|
||||
}
|
||||
|
||||
$this->logEvent('purchase', [
|
||||
'value' => $total,
|
||||
'discount_value' => max(0, $discount),
|
||||
]);
|
||||
}
|
||||
|
||||
public function recordDiscountApplied($product, $original_price, $discounted_price, $rule_id = null) {
|
||||
if (!$product || $original_price <= 0 || $discounted_price >= $original_price) {
|
||||
return;
|
||||
}
|
||||
|
||||
$product_id = $product->get_id();
|
||||
$variation_id = $product->is_type('variation') ? $product_id : 0;
|
||||
$discount_value = round($original_price - $discounted_price, 2);
|
||||
|
||||
$key = 'discount_applied_' . $product_id . '_' . $rule_id . '_' . $discount_value;
|
||||
if ($this->hasLogged($key)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->logEvent('discount_applied', [
|
||||
'product_id' => $product_id,
|
||||
'variation_id' => $variation_id,
|
||||
'rule_id' => $rule_id,
|
||||
'value' => $discounted_price,
|
||||
'discount_value' => $discount_value,
|
||||
]);
|
||||
$this->markLogged($key);
|
||||
}
|
||||
|
||||
public function getRuleUsageCount($rule_id) {
|
||||
return $this->eventRepository->getRuleUsageCount($rule_id);
|
||||
}
|
||||
|
||||
private function logEvent($type, array $data = []) {
|
||||
$event = [
|
||||
'event_type' => $type,
|
||||
'product_id' => isset($data['product_id']) ? intval($data['product_id']) : null,
|
||||
'variation_id' => isset($data['variation_id']) ? intval($data['variation_id']) : null,
|
||||
'user_id' => get_current_user_id() ?: null,
|
||||
'session_id' => $this->getSessionId(),
|
||||
'rule_id' => isset($data['rule_id']) ? intval($data['rule_id']) : null,
|
||||
'value' => isset($data['value']) ? floatval($data['value']) : 0,
|
||||
'discount_value' => isset($data['discount_value']) ? floatval($data['discount_value']) : 0,
|
||||
'metadata' => isset($data['metadata']) ? wp_json_encode($data['metadata']) : null,
|
||||
'created_at' => current_time('mysql'),
|
||||
];
|
||||
|
||||
$this->eventRepository->insert($event);
|
||||
}
|
||||
|
||||
private function getSessionId() {
|
||||
if (function_exists('WC') && WC()->session) {
|
||||
$session_id = WC()->session->get('sodino_session_id');
|
||||
if (!$session_id) {
|
||||
$session_id = uniqid('sodino_', true);
|
||||
WC()->session->set('sodino_session_id', $session_id);
|
||||
}
|
||||
return $session_id;
|
||||
}
|
||||
|
||||
return 'guest_' . md5($_SERVER['REMOTE_ADDR'] . '|' . $_SERVER['HTTP_USER_AGENT']);
|
||||
}
|
||||
|
||||
private function hasLogged($key) {
|
||||
return isset($this->loggedEvents[$key]);
|
||||
}
|
||||
|
||||
private function markLogged($key) {
|
||||
$this->loggedEvents[$key] = true;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user