19 $GLOBALS[
"APPLICATION"]->ThrowException(
GetMessage(
"SKGR_EMPTY_USER_ID"),
"NO_USER_ID");
24 $GLOBALS[
"APPLICATION"]->ThrowException(
GetMessage(
"SKGR_EMPTY_NEXT_DATE"),
"NO_NEXT_DATE");
29 $GLOBALS[
"APPLICATION"]->ThrowException(
GetMessage(
"SKGR_EMPTY_ORDER_ID"),
"NO_ORDER_ID");
35 $dbUser = CUser::GetByID(
$arFields[
"USER_ID"]);
36 if (!$dbUser->Fetch())
45 if (!($arOrder = CSaleOrder::GetByID(
$arFields[
"ORDER_ID"])))
72 $arFields[
'~TIMESTAMP_X'] = $helper->getCurrentDateTimeFunction();
88 $strUpdate =
$DB->PrepareUpdate(
"b_sale_recurring",
$arFields);
89 $strSql =
"UPDATE b_sale_recurring SET ".$strUpdate.
" WHERE ID = ".
$ID.
" ";
92 unset(
$GLOBALS[
"SALE_RECURRING"][
"SALE_RECURRING_CACHE_".
$ID]);
105 unset(
$GLOBALS[
"SALE_RECURRING"][
"SALE_RECURRING_CACHE_".
$ID]);
107 return $DB->Query(
"DELETE FROM b_sale_recurring WHERE ID = ".
$ID.
" ",
true);
112 $callbackFunc = trim($callbackFunc);
113 $module = trim($module);
114 $productID = intval($productID);
117 if ($callbackFunc <>
'')
119 if ($module <>
'' && $module !=
"main")
120 CModule::IncludeModule($module);
122 $arArgs =
array($productID);
123 $numArgs = func_num_args();
125 for (
$i = 3;
$i < $numArgs;
$i++)
126 $arArgs[] = func_get_arg(
$i);
128 $result = call_user_func_array($callbackFunc, $arArgs);
136 if (defined(
"SALE_PROC_REC_NUM"))
144 "<=NEXT_DATE" =>
Date(
$GLOBALS[
"DB"]->DateFormatToPHP(CLang::GetDateFormat(
"FULL",
SITE_ID))),
146 "!REMAINING_ATTEMPTS" => 0
149 array(
"nTopCount" => $processRecords),
157 if ($cnt >= $processRecords)
162 public static function NextPayment(
$ID)
177 $GLOBALS[
"APPLICATION"]->ThrowException(str_replace(
"#ID#",
$ID,
GetMessage(
"SKGR_NO_RECID1")),
"NO_RECORD");
181 $arOrder = CSaleOrder::GetByID($arRecur[
"ORDER_ID"]);
184 $GLOBALS[
"APPLICATION"]->ThrowException(str_replace(
"#ID#", $arRecur[
"ORDER_ID"],
GetMessage(
"SKGR_NO_ORDER1")),
"NO_ORDER");
190 $newOrderID = intval($arRecur[
"ORDER_ID"]);
195 $arProduct = $productProvider::RecurringOrderProduct(
array(
196 "PRODUCT_ID" => $arRecur[
"PRODUCT_ID"],
197 "USER_ID" => $arOrder[
"USER_ID"]
203 $arRecur[
"CALLBACK_FUNC"],
205 $arRecur[
"PRODUCT_ID"],
210 if (!$arProduct || !is_array($arProduct) || empty($arProduct))
217 if ($arProduct[
"WITHOUT_ORDER"] ==
"Y" || $arRecur[
"SUCCESS_PAYMENT"] ==
"Y")
220 $productPrice = \Bitrix\Sale\PriceMaths::roundPrecision(
CCurrencyRates::ConvertCurrency($arProduct[
"PRICE"], $arProduct[
"CURRENCY"], $baseSiteCurrency));
225 $arOrder[
"DELIVERY_ID"] = intval($arOrder[
"DELIVERY_ID"]);
226 if ($arOrder[
"DELIVERY_ID"] > 0)
228 $deliveryLocation = 0;
232 "ORDER_ID" => $arRecur[
"ORDER_ID"],
233 "PROP_IS_LOCATION" =>
"Y"
239 if ($arOrderPropValues = $dbOrderPropValues->Fetch())
240 $deliveryLocation = intval($arOrderPropValues[
"VALUE"]);
243 array(
"SORT" =>
"ASC",
"NAME" =>
"ASC"),
245 "LID" => $arOrder[
"LID"],
246 "WEIGHT" => DoubleVal($arProduct[
"WEIGHT"]) * DoubleVal($arProduct[
"QUANTITY"]),
247 "ORDER_PRICE" => $productPrice * DoubleVal($arProduct[
"QUANTITY"]),
249 "LOCATION" => $deliveryLocation
252 while ($arDelivery = $dbDelivery->Fetch())
254 $deliveryPriceTmp = \Bitrix\Sale\PriceMaths::roundPrecision(
CCurrencyRates::ConvertCurrency($arDelivery[
"PRICE"], $arDelivery[
"CURRENCY"], $baseSiteCurrency));
255 if (intval($arDelivery[
"ID"]) == $arOrder[
"DELIVERY_ID"])
257 $deliveryID = intval($arDelivery[
"ID"]);
258 $deliveryPrice = $deliveryPriceTmp;
261 if ($deliveryPriceTmp < $deliveryPrice || $deliveryID <= 0)
263 $deliveryID = intval($arDelivery[
"ID"]);
264 $deliveryPrice = $deliveryPriceTmp;
268 if ($deliveryID <= 0)
270 $deliveryID = \Bitrix\Sale\Delivery\Services\EmptyDeliveryService::getEmptyDeliveryServiceId();
274 $deliveryID = \CSaleDelivery::getCodeById($deliveryID);
278 if ($deliveryID <= 0)
280 $GLOBALS[
"APPLICATION"]->ThrowException(
GetMessage(
"SKGR_NO_DELIVERY"),
"NO_DELIVERY");
287 $discountPrice = $productPrice;
288 $discountProduct = 0;
290 array(
"SORT" =>
"ASC"),
292 "LID" => $arOrder[
"LID"],
294 "!>ACTIVE_FROM" => Date(
$DB->DateFormatToPHP(CSite::GetDateFormat(
"FULL"))),
295 "!<ACTIVE_TO" => Date(
$DB->DateFormatToPHP(CSite::GetDateFormat(
"FULL"))),
296 "<=PRICE_FROM" => $productPrice,
297 ">=PRICE_TO" => $productPrice,
298 "USER_GROUPS" =>
$USER->GetUserGroup($arOrder[
'USER_ID']),
301 if ($arDiscount = $dbDiscount->Fetch())
303 if ($arDiscount[
"DISCOUNT_TYPE"] ==
"P")
305 $discountProduct = \Bitrix\Sale\PriceMaths::roundPrecision($productPrice * $arDiscount[
"DISCOUNT_VALUE"] / 100);
306 $discount = \Bitrix\Sale\PriceMaths::roundPrecision($discountProduct * DoubleVal($arProduct[
"QUANTITY"]));
307 $discountPrice = $productPrice - $discountProduct;
312 $discountValue = \Bitrix\Sale\PriceMaths::roundPrecision($discountValue);
314 $discountProduct = \Bitrix\Sale\PriceMaths::roundPrecision(1.0 * $discountValue / DoubleVal($arProduct[
"QUANTITY"]));
315 $discount = \Bitrix\Sale\PriceMaths::roundPrecision($curDiscount * DoubleVal($arProduct[
"QUANTITY"]));
316 $discountPrice = $productPrice - $discountProduct;
322 if(DoubleVal($arProduct[
"VAT_RATE"]) > 0)
325 $vatRate = $arProduct[
"VAT_RATE"];
329 $arTaxExempt =
array();
331 while ($arUserGroups = $dbUserGroups->Fetch())
334 while ($arTaxExemptTmp = $dbTaxExemptTmp->Fetch())
336 $arTaxExemptTmp[
"TAX_ID"] = intval($arTaxExemptTmp[
"TAX_ID"]);
337 if (!in_array($arTaxExemptTmp[
"TAX_ID"], $arTaxExempt))
338 $arTaxExempt[] = $arTaxExemptTmp[
"TAX_ID"];
350 "ORDER_ID" => $arRecur[
"ORDER_ID"],
351 "PROP_IS_LOCATION4TAX" =>
"Y"
357 if ($arOrderPropValues = $dbOrderPropValues->Fetch())
358 $taxLocation = intval($arOrderPropValues[
"VALUE"]);
362 array(
"APPLY_ORDER" =>
"ASC"),
364 "LID" => $arOrder[
"LID"],
365 "PERSON_TYPE_ID" => $arOrder[
"PERSON_TYPE_ID"],
367 "LOCATION" => $taxLocation
370 while ($arTaxRateTmp = $dbTaxRateTmp->Fetch())
372 if (!in_array(intval($arTaxRateTmp[
"TAX_ID"]), $arTaxExempt))
384 "VALUE" => $vatRate*100,
386 "APPLY_ORDER" => 100,
387 "IS_IN_PRICE" =>
"Y",
393 $arTaxSums =
array();
400 $discountPrice * DoubleVal($arProduct[
"QUANTITY"]),
422 $arTaxList[0][
"VALUE_MONEY"] = \Bitrix\Sale\PriceMaths::roundPrecision((($discountPrice / ($vatRate +1)) * $vatRate) * DoubleVal($arProduct[
"QUANTITY"]));
429 $totalOrderPrice = $discountPrice * DoubleVal($arProduct[
"QUANTITY"]) + $deliveryPrice + $taxPrice;
431 $arProduct[
"WITHOUT_ORDER"] = (($arProduct[
"WITHOUT_ORDER"]==
"Y") ?
"Y" :
"N");
432 if ($arProduct[
"WITHOUT_ORDER"] ==
"N")
434 $DB->StartTransaction();
437 $currentFUser = Sale\Fuser::getIdByUserId((
int)$arOrder[
'USER_ID']);
440 "FUSER_ID" => $currentFUser,
441 "PRODUCT_ID" => $arProduct[
"PRODUCT_ID"],
442 "PRODUCT_NAME" => $arProduct[
"PRODUCT_NAME"],
443 "PRODUCT_URL" => $arProduct[
"PRODUCT_URL"],
444 "PRODUCT_PRICE_ID" => $arProduct[
"PRODUCT_PRICE_ID"],
445 "PRICE" => $arProduct[
"PRICE"],
446 "CURRENCY" => $arProduct[
"CURRENCY"],
447 "WEIGHT" => $arProduct[
"WEIGHT"],
448 "QUANTITY" => $arProduct[
"QUANTITY"],
449 "LID" => $arOrder[
"LID"],
452 "NAME" => $arProduct[
"NAME"],
453 "CALLBACK_FUNC" => $arProduct[
"CALLBACK_FUNC"],
454 "ORDER_CALLBACK_FUNC" => $arProduct[
"ORDER_CALLBACK_FUNC"],
455 "CANCEL_CALLBACK_FUNC" => $arProduct[
"CANCEL_CALLBACK_FUNC"],
456 "PAY_CALLBACK_FUNC" => $arProduct[
"PAY_CALLBACK_FUNC"],
457 "PRODUCT_PROVIDER_CLASS" => $arProduct[
"PRODUCT_PROVIDER_CLASS"],
458 "MODULE" => $arRecur[
"MODULE"],
459 "NOTES" => $arProduct[
"CATALOG_GROUP_NAME"],
460 "DETAIL_PAGE_URL" => $arProduct[
"DETAIL_PAGE_URL"],
461 "VATE_RATE" => $arProduct[
"VATE_RATE"],
462 "PRODUCT_XML_ID" => $arProduct[
"PRODUCT_XML_ID"],
463 "TYPE" => $arProduct[
"TYPE"],
469 $basketID = intval($basketID);
475 if (CModule::IncludeModule(
"statistic"))
476 CStatistic::Set_Event(
"eStore",
"add2basket",
$arFields[
"PRODUCT_ID"]);
479 "LID" => $arOrder[
"LID"],
480 "PERSON_TYPE_ID" => $arOrder[
"PERSON_TYPE_ID"],
484 "PRICE_DELIVERY" => $deliveryPrice,
485 "ALLOW_DELIVERY" =>
"N",
486 "PRICE" => $totalOrderPrice,
487 "CURRENCY" => $baseSiteCurrency,
489 "USER_ID" => $arOrder[
"USER_ID"],
490 "PAY_SYSTEM_ID" => $arOrder[
"PAY_SYSTEM_ID"],
491 "DELIVERY_ID" => $deliveryID,
492 "USER_DESCRIPTION" => $arOrder[
"USER_DESCRIPTION"],
493 "TAX_VALUE" => ((
$bUseVat)? $taxVatPrice : $taxPrice),
494 "STAT_GID" => $arOrder[
"STAT_GID"],
495 "RECURRING_ID" => $arRecur[
"ID"]
500 $newOrderID = intval($newOrderID);
501 if ($newOrderID <= 0)
507 $arDiscounts =
array();
508 $arDiscounts[$basketID] = $discountProduct;
509 CSaleBasket::OrderBasket($newOrderID, $currentFUser, $arOrder[
"LID"], $arDiscounts);
517 "ORDER_ID" => $newOrderID,
519 "IS_PERCENT" =>
$arTaxList[$it][
"IS_PERCENT"],
521 "VALUE_MONEY" =>
$arTaxList[$it][
"VALUE_MONEY"],
522 "APPLY_ORDER" =>
$arTaxList[$it][
"APPLY_ORDER"],
523 "IS_IN_PRICE" =>
$arTaxList[$it][
"IS_IN_PRICE"],
531 array(
"ORDER_ID" => $arRecur[
"ORDER_ID"]),
534 array(
"ORDER_PROPS_ID",
"NAME",
"CODE",
"VALUE",
"PROP_IS_PAYER",
"PROP_IS_EMAIL")
536 while ($arOrderPropValues = $dbOrderPropValues->Fetch())
539 "ORDER_ID" => $newOrderID,
540 "ORDER_PROPS_ID" => $arOrderPropValues[
"ORDER_PROPS_ID"],
541 "NAME" => $arOrderPropValues[
"NAME"],
542 "CODE" => $arOrderPropValues[
"CODE"],
543 "VALUE" => $arOrderPropValues[
"VALUE"]
547 if ($arOrderPropValues[
"PROP_IS_PAYER"] ==
"Y")
548 $payerName = $arOrderPropValues[
"VALUE"];
549 if ($arOrderPropValues[
"PROP_IS_EMAIL"] ==
"Y")
550 $payerEMail = $arOrderPropValues[
"VALUE"];
556 if (CModule::IncludeModule(
"statistic"))
557 CStatistic::Set_Event(
"eStore",
"order_create", $newOrderID);
564 array(
"NAME" =>
"ASC"),
565 array(
"ORDER_ID" => $newOrderID)
567 while ($arBasketTmp = $dbBasketTmp->Fetch())
569 $strOrderList .= $arBasketTmp[
"NAME"].
" - ".$arBasketTmp[
"QUANTITY"].
" ".
GetMessage(
"SALE_QUANTITY_UNIT");
570 $strOrderList .=
"\n";
573 if ($payerName ==
'' || $payerEMail ==
'')
576 if ($arUser = $dbUser->Fetch())
578 if ($payerName ==
'')
579 $payerName = $arUser[
"NAME"].(($arUser[
"NAME"] ==
'' || $arUser[
"LAST_NAME"] ==
'') ?
"" :
" ").$arUser[
"LAST_NAME"];
580 if ($payerEMail ==
'')
581 $payerEMail = $arUser[
"EMAIL"];
586 "ORDER_ID" => $newOrderID,
587 "ORDER_DATE" => Date(
$DB->DateFormatToPHP(CLang::GetDateFormat(
"SHORT", $arOrder[
"LID"]))),
588 "ORDER_USER" => $payerName,
590 "BCC" => COption::GetOptionString(
"sale",
"order_email",
"order@".$SERVER_NAME),
591 "EMAIL" => $payerEMail,
592 "ORDER_LIST" => $strOrderList,
593 "SALE_EMAIL" => COption::GetOptionString(
"sale",
"order_email",
"order@".$SERVER_NAME)
595 $eventName =
"SALE_NEW_ORDER_RECURRING";
598 foreach(
GetModuleEvents(
"sale",
"OnOrderRecurringSendEmail",
true) as $arEvent)
619 $totalOrderPrice = $arOrder[
"PRICE"];
620 $baseSiteCurrency = $arOrder[
"CURRENCY"];
629 if ($arProduct[
"WITHOUT_ORDER"] ==
"N")
631 CSaleOrder::PayOrder($newOrderID,
"Y", False, False, $arRecur[
"ID"]);
632 CSaleOrder::DeliverOrder($newOrderID,
"Y", $arRecur[
"ID"]);
640 $r = $productProvider::DeliverProduct(
array(
641 "PRODUCT_ID" => $arProduct[
"PRODUCT_ID"],
642 "USER_ID" => $arOrder[
"USER_ID"],
644 'BASKET_ID' => $basketID
650 $arProduct[
"PAY_CALLBACK_FUNC"],
652 $arProduct[
"PRODUCT_ID"],
660 "ORDER_ID" => $newOrderID,
661 "PRODUCT_NAME" => $arProduct[
"PRODUCT_NAME"],
662 "PRODUCT_URL" => $arProduct[
"PRODUCT_URL"],
663 "PRICE_TYPE" => $arProduct[
"PRICE_TYPE"],
664 "RECUR_SCHEME_TYPE" => $arProduct[
"RECUR_SCHEME_TYPE"],
665 "RECUR_SCHEME_LENGTH" => $arProduct[
"RECUR_SCHEME_LENGTH"],
666 "WITHOUT_ORDER" => $arProduct[
"WITHOUT_ORDER"],
667 "PRIOR_DATE" => Date(
$GLOBALS[
"DB"]->DateFormatToPHP(CLang::GetDateFormat(
"FULL",
SITE_ID))),
668 "NEXT_DATE" => $arProduct[
"NEXT_DATE"],
670 "SUCCESS_PAYMENT" =>
"Y"
678 "ORDER_ID" => $newOrderID,
679 "PRODUCT_NAME" => $arProduct[
"PRODUCT_NAME"],
680 "PRODUCT_URL" => $arProduct[
"PRODUCT_URL"],
681 "PRICE_TYPE" => $arProduct[
"PRICE_TYPE"],
682 "RECUR_SCHEME_LENGTH" => $arProduct[
"RECUR_SCHEME_LENGTH"],
683 "RECUR_SCHEME_TYPE" => $arProduct[
"RECUR_SCHEME_TYPE"],
684 "WITHOUT_ORDER" => $arProduct[
"WITHOUT_ORDER"],
686 "REMAINING_ATTEMPTS" => (intval($arRecur[
"REMAINING_ATTEMPTS"]) - 1),
687 "SUCCESS_PAYMENT" =>
"N"
691 if ((intval($arRecur[
"REMAINING_ATTEMPTS"]) - 1) <= 0)
716 $GLOBALS[
"APPLICATION"]->ThrowException(
GetMessage(
"SKGR_EMPTY_SUBSCR"),
"NO_RECURRING_ID");
723 $GLOBALS[
"APPLICATION"]->ThrowException(str_replace(
"#ID#",
$ID,
GetMessage(
"SKGR_NO_SUBSCR")),
"NO_RECURRING");
729 $GLOBALS[
"APPLICATION"]->ThrowException(str_replace(
"#ID#",
$ID,
GetMessage(
"SKGR_DUB_CANCEL")),
"ALREADY_FLAG");
735 "DATE_CANCELED" => ((
$val ==
"Y") ?
Date(CDatabase::DateFormatToPHP(CLang::GetDateFormat(
"FULL", LANG))) : False),
740 unset(
$GLOBALS[
"SALE_RECURRING"][
"SALE_RECURRING_CACHE_".
$ID]);
744 $arUser = $dbUser->Fetch();
746 $arOrder = CSaleOrder::GetByID(
$arRecurring[
"ORDER_ID"]);
749 "RECURRING_ID" =>
$ID,
751 "EMAIL" => $arUser[
"EMAIL"],
753 "SALE_EMAIL" => COption::GetOptionString(
"sale",
"order_email",
"order@".$SERVER_NAME)
755 $eventName =
"SALE_RECURRING_CANCEL";
758 foreach(
GetModuleEvents(
"sale",
"OnOrderRecurringCancelSendEmail",
true) as $arEvent)
795 return "CSaleRecurring::AgentCheckRecurring();";
801 if ($Currency ==
'')
return false;
803 return $DB->Query(
"DELETE FROM b_sale_recurring WHERE CURRENCY = '".
$DB->ForSql(
$ID).
"' ",
true);
809 $UserID = intval($UserID);
811 return $DB->Query(
"DELETE FROM b_sale_recurring WHERE USER_ID = ".$UserID.
" ",
true);