diff --git a/src/include/class-wc-retailcrm-base.php b/src/include/class-wc-retailcrm-base.php index 4a28a22..7ab9377 100644 --- a/src/include/class-wc-retailcrm-base.php +++ b/src/include/class-wc-retailcrm-base.php @@ -114,11 +114,12 @@ if (!class_exists('WC_Retailcrm_Base')) { // Add coupon hooks for loyalty program add_action('woocommerce_cart_coupon', [$this, 'coupon_info'], 11, 1); //Remove coupons when cart changes - add_action('woocommerce_add_to_cart', [$this, 'delete_loyalty_coupon'], 11, 1); - add_action('woocommerce_after_cart_item_quantity_update', [$this, 'delete_loyalty_coupon'], 11, 1); - add_action('woocommerce_cart_item_removed', [$this, 'delete_loyalty_coupon'], 11, 1); + add_action('woocommerce_add_to_cart', [$this, 'refresh_loyalty_coupon'], 11, 1); + add_action('woocommerce_after_cart_item_quantity_update', [$this, 'refresh_loyalty_coupon'], 11, 1); + add_action('woocommerce_cart_item_removed', [$this, 'refresh_loyalty_coupon'], 11, 1); add_action('woocommerce_before_cart_empted', [$this, 'delete_loyalty_coupon'], 11, 1); - add_action('woocommerce_removed_coupon', [$this, 'removed_loyalty_coupon'], 11, 1); + add_action('woocommerce_removed_coupon', [$this, 'removed_coupon'], 11, 1); + add_action('woocommerce_applied_coupon', [$this, 'applied_coupon'], 11, 1); } // Subscribed hooks @@ -691,86 +692,21 @@ if (!class_exists('WC_Retailcrm_Base')) { public function coupon_info() { - global $woocommerce; - try { - $site = $this->apiClient->getSingleSiteForKey(); - $cartItems = $woocommerce->cart->get_cart(); - $customerId = $woocommerce->customer->get_id(); + $result = $this->loyalty->createLoyaltyCoupon(); - $resultString = ''; - - if (!$customerId || !$cartItems) { - return; + if ($result) { + echo $result; } + } catch (Throwable $exception) { + writeBaseLogs($exception->getMessage()); + } + } - $validator = new WC_Retailcrm_Loyalty_Validator($this->apiClient, $this->settings['corporate_enabled'] ?? static::NO); - - if (!$validator->checkAccount($customerId)) { - return; - } - - $lpDiscountSum = $this->loyalty->getDiscountLp($cartItems, $site, $customerId); - - if ($lpDiscountSum === 0) { - return; - } - - $couponsLp = []; - // Check exists used loyalty coupons - foreach ($woocommerce->cart->get_coupons() as $code => $coupon) { - if (preg_match('/^pl\d+$/m', $code) === 1) { - $couponsLp[] = $code; - } - } - - //If one loyalty coupon is used, not generate a new one - // if more than 1 loyalty coupon is used, delete all coupons - if (count($couponsLp) === 1) { - return; - } - - if (count($couponsLp) > 1) { - foreach ($couponsLp as $code) { - $woocommerce->cart->remove_coupon($code); - - $coupon = new WC_Coupon($code); - - $coupon->delete(true); - } - } - - //Check the existence of loyalty coupons and delete them - $coupons = $this->loyalty->getCouponLoyalty($woocommerce->customer->get_email()); - $loyaltyInfo = $this->loyalty->getLoyaltyAccounts($customerId); - - if (!isset($loyaltyInfo['loyaltyAccounts'][0])) { - return; - } - - if ($loyaltyInfo['loyaltyAccounts'][0]['level']['type'] === 'discount') { - $resultString .= '
' . 'Предоставляется скидка в ' . $lpDiscountSum . $loyaltyInfo['loyaltyAccounts'][0]['loyalty']['currency'] . '
'; - } else { - $resultString .= '
' . 'Возможно списать ' . $lpDiscountSum . ' бонусов' . '
'; - } - - foreach ($coupons as $item) { - $coupon = new WC_Coupon($item['code']); - - $coupon->delete(true); - } - - //Generate new coupon - $coupon = new WC_Coupon(); - - //$coupon->set_individual_use(true); // запрещает использование других купонов одноврeменно с этим - $coupon->set_usage_limit(0); - $coupon->set_amount($lpDiscountSum); - $coupon->set_email_restrictions($woocommerce->customer->get_email()); - $coupon->set_code('pl' . mt_rand()); - $coupon->save(); - - echo $resultString . '
' . 'Your coupon: ' . $coupon->get_code() . '
'; + public function refresh_loyalty_coupon() + { + try { + $this->loyalty->createLoyaltyCoupon(true); } catch (Throwable $exception) { writeBaseLogs($exception->getMessage()); } @@ -778,30 +714,33 @@ if (!class_exists('WC_Retailcrm_Base')) { public function delete_loyalty_coupon() { - global $woocommerce; - try { - foreach ($woocommerce->cart->get_coupons() as $code => $coupon) { - if (preg_match('/^pl\d+$/m', $code) === 1) { - $woocommerce->cart->remove_coupon($code); - - $coupon = new WC_Coupon($code); - - $coupon->delete(true); - } - } + $this->loyalty->deleteAppliedLoyaltyCoupon(); } catch (Throwable $exception) { writeBaseLogs($exception->getMessage()); } } - public function removed_loyalty_coupon($couponCode) + public function removed_coupon($couponCode) { try { if (preg_match('/^pl\d+$/m', $couponCode) === 1) { $coupon = new WC_Coupon($couponCode); $coupon->delete(true); + } else { + $this->loyalty->createLoyaltyCoupon(true); + } + } catch (Throwable $exception) { + writeBaseLogs($exception->getMessage()); + } + } + + public function applied_coupon($couponCode) + { + try { + if (preg_match('/^pl\d+$/m', $couponCode) !== 1) { + $this->loyalty->createLoyaltyCoupon(true); } } catch (Throwable $exception) { writeBaseLogs($exception->getMessage()); diff --git a/src/include/class-wc-retailcrm-loyalty.php b/src/include/class-wc-retailcrm-loyalty.php index 2fa93e4..0132728 100644 --- a/src/include/class-wc-retailcrm-loyalty.php +++ b/src/include/class-wc-retailcrm-loyalty.php @@ -105,7 +105,7 @@ if (!class_exists('WC_Retailcrm_Loyalty')) : } } - public function getDiscountLp($cartItems, $site, $customerId) + private function getDiscountLp($cartItems, $site, $customerId) { $order = [ 'site' => $site, @@ -121,7 +121,8 @@ if (!class_exists('WC_Retailcrm_Loyalty')) : $order['items'][] = [ 'offer' => $useXmlId ? ['xmlId' => $product->get_sku()] : ['externalId' => $product->get_id()], 'quantity' => $item['quantity'], - 'initialPrice' => wc_get_price_including_tax($product) + 'initialPrice' => wc_get_price_including_tax($product), + 'discountManualAmount' => ($item['line_subtotal'] - $item['line_total']) / $item['quantity'] ]; } @@ -138,13 +139,13 @@ if (!class_exists('WC_Retailcrm_Loyalty')) : continue; } - $discount = $calculate['discount'] !== 0 ? $calculate['discount'] : $calculate['maxChargeBonuses']; + $discount = /*$calculate['discount'] !== 0 ? $calculate['discount'] :*/ $calculate['maxChargeBonuses']; } return $discount; } - public function getLoyaltyAccounts(int $userId) + private function getLoyaltyAccounts(int $userId) { $response = $this->apiClient->customersGet($userId); @@ -163,6 +164,116 @@ if (!class_exists('WC_Retailcrm_Loyalty')) : return $response; } + public function createLoyaltyCoupon($refreshCoupon = false) + { + global $woocommerce; + + $site = $this->apiClient->getSingleSiteForKey(); + $cartItems = $woocommerce->cart->get_cart(); + $customerId = $woocommerce->customer ? $woocommerce->customer->get_id() : null; + + $resultString = ''; + + if (!$customerId || !$cartItems) { + return null; + } + + $couponsLp = []; + // Check exists used loyalty coupons + foreach ($woocommerce->cart->get_coupons() as $code => $coupon) { + if (preg_match('/^pl\d+$/m', $code) === 1) { + $couponsLp[] = $code; + } + } + + // if you need to refresh coupon that does not exist + if (count($couponsLp) === 0 && $refreshCoupon) { + return null; + } + + //If one loyalty coupon is used, not generate a new one + if (count($couponsLp) === 1 && !$refreshCoupon) { + return null; + } + + // if more than 1 loyalty coupon is used, delete all coupons + if (count($couponsLp) > 1 || $refreshCoupon) { + foreach ($couponsLp as $code) { + $woocommerce->cart->remove_coupon($code); + + $coupon = new WC_Coupon($code); + + $coupon->delete(true); + } + } + + $validator = new WC_Retailcrm_Loyalty_Validator($this->apiClient, $this->settings['corporate_enabled'] ?? WC_Retailcrm_Base::NO); + + if (!$validator->checkAccount($customerId)) { + return null; + } + + $lpDiscountSum = $this->getDiscountLp($woocommerce->cart->get_cart(), $site, $customerId); + + if ($lpDiscountSum === 0) { + return null; + } + + //Check the existence of loyalty coupons and delete them + $coupons = $this->getCouponLoyalty($woocommerce->customer->get_email()); + + foreach ($coupons as $item) { + $coupon = new WC_Coupon($item['code']); + + $coupon->delete(true); + } + + //Generate new coupon + $coupon = new WC_Coupon(); + + //$coupon->set_individual_use(true); // запрещает использование других купонов одноврeменно с этим + $coupon->set_usage_limit(0); + $coupon->set_amount($lpDiscountSum); + $coupon->set_email_restrictions($woocommerce->customer->get_email()); + $coupon->set_code('pl' . mt_rand()); + $coupon->save(); + + if ($refreshCoupon) { + $woocommerce->cart->apply_coupon($coupon->get_code()); + + return $resultString; + } + + $loyaltyInfo = $this->getLoyaltyAccounts($customerId); + + if (!isset($loyaltyInfo['loyaltyAccounts'][0])) { + return null; + } + + if ($loyaltyInfo['loyaltyAccounts'][0]['level']['type'] === 'discount') { + $resultString .= '
' . 'Предоставляется скидка в ' . $lpDiscountSum . $loyaltyInfo['loyaltyAccounts'][0]['loyalty']['currency'] . '
'; + } else { + $resultString .= '
' . 'Возможно списать ' . $lpDiscountSum . ' бонусов' . '
'; + } + + return $resultString . '
' . 'Your coupon: ' . $coupon->get_code() . '
'; + } + + public function deleteAppliedLoyaltyCoupon() + { + global $woocommerce; + + foreach ($woocommerce->cart->get_coupons() as $code => $coupon) { + if (preg_match('/^pl\d+$/m', $code) === 1) { + $woocommerce->cart->remove_coupon($code); + + $coupon = new WC_Coupon($code); + + $coupon->delete(true); + } + } + } + public function getCouponLoyalty($email) { global $wpdb; diff --git a/src/include/class-wc-retailcrm-orders.php b/src/include/class-wc-retailcrm-orders.php index 6d657aa..516ad4c 100644 --- a/src/include/class-wc-retailcrm-orders.php +++ b/src/include/class-wc-retailcrm-orders.php @@ -87,28 +87,32 @@ if (!class_exists('WC_Retailcrm_Orders')) : $this->order_payment->resetData(); $wcOrder = wc_get_order($orderId); - $coupons = $wcOrder->get_coupons(); - $discountLp = 0; + $privilegeType = 'none'; - foreach ($coupons as $coupon) { - $code = $coupon->get_code(); + if (isset($this->retailcrm_settings['loyalty']) + && $this->retailcrm_settings['loyalty'] === WC_Retailcrm_Base::YES + ) { + $discountLp = $this->deleteLoyaltyCoupon($wcOrder); + $wcUser = $wcOrder->get_user(); - if (preg_match('/^pl\d+$/m', $code) !== 1) { - continue; + if ( + ( + !$wcUser + || ( + isset($this->retailcrm_settings['corporate_enabled']) + && $this->retailcrm_settings['corporate_enabled'] === WC_Retailcrm_Base::YES + && !empty($wcUser->get_shipping_company()) + ) + ) && $discountLp > 0 + ) { + wp_die(); } - $discountLp = $coupon->get_discount(); - $wcOrder->remove_coupon($code); - $objectCoupon = new WC_Coupon($code); - $objectCoupon->delete(true); - - break; + $privilegeType = 'loyalty_level'; } - $wcOrder->recalculate_coupons(); - $this->processOrder($wcOrder); - $this->order['privilegeType'] = 'loyalty_level'; + $this->order['privilegeType'] = $privilegeType; $response = $this->retailcrm->ordersCreate($this->order); @@ -119,36 +123,9 @@ if (!class_exists('WC_Retailcrm_Orders')) : return $response->getErrorString(); } - $response = $this->retailcrm->applyBonusToOrder('woo', ['externalId' => $this->order['externalId']], (float) $discountLp); - - if (!$response instanceof WC_Retailcrm_Response || !$response->isSuccessful()) { - return $response->getErrorString(); + if (isset($discountLp) && $discountLp > 0) { + $this->applyLoyaltyDiscount($wcOrder, $discountLp); } - - $wcItems = $wcOrder->get_items(); - - foreach ($response['order']['items'] as $item) { - $externalId = $item['externalIds'][0]['value']; - $externalId = preg_replace('/^\d+\_/m', '', $externalId); - - if (isset($wcItems[(int) $externalId])) { - - $discountLoyaltyTotal = 0; - - foreach ($item['discounts'] as $discount) { - if ($discount['type'] === 'bonus_charge') { - $discountLoyaltyTotal += $discount['amount']; - } - } - - $wcItem = $wcItems[(int) $externalId]; - $wcItem->set_total($wcItem->get_total() - $discountLoyaltyTotal); - $wcItem->calculate_taxes(); - $wcItem->save(); - } - } - - $wcOrder->calculate_totals(); } catch (Throwable $exception) { writeBaseLogs( sprintf( @@ -689,5 +666,63 @@ if (!class_exists('WC_Retailcrm_Orders')) : return $customerWasChanged; } + + private function deleteLoyaltyCoupon(&$wcOrder) + { + $discountLp = 0; + $coupons = $wcOrder->get_coupons(); + + foreach ($coupons as $coupon) { + $code = $coupon->get_code(); + + if (preg_match('/^pl\d+$/m', $code) !== 1) { + continue; + } + + $discountLp = $coupon->get_discount(); + $wcOrder->remove_coupon($code); + $objectCoupon = new WC_Coupon($code); + $objectCoupon->delete(true); + + $wcOrder->recalculate_coupons(); + break; + } + + return $discountLp; + } + + private function applyLoyaltyDiscount(&$wcOrder, $discountLp) + { + $response = $this->retailcrm->applyBonusToOrder('woo', ['externalId' => $this->order['externalId']], (float) $discountLp); + + if (!$response instanceof WC_Retailcrm_Response || !$response->isSuccessful()) { + return $response->getErrorString(); + } + + $wcItems = $wcOrder->get_items(); + + foreach ($response['order']['items'] as $item) { + $externalId = $item['externalIds'][0]['value']; + $externalId = preg_replace('/^\d+\_/m', '', $externalId); + + if (isset($wcItems[(int) $externalId])) { + + $discountLoyaltyTotal = 0; + + foreach ($item['discounts'] as $discount) { + if ($discount['type'] === 'bonus_charge') { + $discountLoyaltyTotal += $discount['amount']; + } + } + + $wcItem = $wcItems[(int) $externalId]; + $wcItem->set_total($wcItem->get_total() - $discountLoyaltyTotal); + $wcItem->calculate_taxes(); + $wcItem->save(); + } + } + + $wcOrder->calculate_totals(); + } } endif; diff --git a/src/include/validators/loyalty-validator/class-wc-retailcrm-loyalty-validator.php b/src/include/validators/loyalty-validator/class-wc-retailcrm-loyalty-validator.php index 6c512b0..a65d608 100644 --- a/src/include/validators/loyalty-validator/class-wc-retailcrm-loyalty-validator.php +++ b/src/include/validators/loyalty-validator/class-wc-retailcrm-loyalty-validator.php @@ -56,7 +56,7 @@ if (!class_exists('WC_Retailcrm_Loyalty_Validator')) : $customer = new WC_Customer($userId); - if ($this->isActiveCorp === 'yes' && !empty($customer->get_shipping_company())) { + if ($this->isActiveCorp === WC_Retailcrm_Base::YES && !empty($customer->get_shipping_company())) { throw new ValidatorException($this->isCorporateUser, 400); }