Применить в корзине купон в обход его же правила через sale.order.ajax
Вот такую задачу не могу решить: Есть купон-скидка на первый заказ пользователя. У тестового пользователя есть один отмененный заказ, но скидка должна все равно учитываться.
В скопированном sale.order.ajax компоненте я пытался заново пересчитать скидки в методе класс SaleOrderAjax->getJsDataResult() : (проверял варианты и по корзине, и по "заказу", что в классе есть) Код
DiscountCouponsManager::init();
DiscountCouponsManager::clear(true);
DiscountCouponsManager::add($oneCoupon['COUPON']);
// $discounts = \Bitrix\Sale\Discount::buildFromBasket($basket, new Sale\Discount\Context\Fuser(Fuser::getId()));
$discounts = \Bitrix\Sale\Discount::buildFromOrder($this->order);
$discounts->calculate();
$discounts->save();
$discountResult = $discounts->getApplyResult();
$this->obtainBasket(); #
// $basket->refresh();
// $basket->save();
$arErrors = DiscountCouponsManager::getErrors();
Пример с https://dev.1c-bitrix.ru/api_d7/bitrix/sale/classes/discountcouponsmanager/add.php , в комментарии который, хоть и устаревший, но все равно не смог под себя заставить работать применение купона.
Подскажите, пожалуйста, куда можно еще посмотреть.
Заранее благодарен
Ответы (1 шт):
К сожалению больше нет идей. Могу поделиться своим методом, который создает скидку и добавляет к заказу купон с этой скидкой на указанную сумму. Понимаю, что не то, что вам нужно, но в свое время тоже столкнулся с проблемой реализации добавления купонов и просто методом тыка нашел работающее решение.
Есть еще проблема - Битрикс может добавить купон к заказу, но не применит скидку из него. В этом случае в админке на странице заказа купон будет серого цвета. Сработавший купон должен быть зеленым.
public static function applyDiscountCoupon(SaleOrder $order, float $discount): void
{
DiscountCouponsManager::init(DiscountCouponsManagerBase::MODE_ORDER, [
"userId" => $order->getUserId(),
"orderId" => $order->getId(),
]);
$coupon = self::generateCoupon($order->getId(), $discount);
DiscountCouponsManager::clearApply();
DiscountCouponsManager::add($coupon);
$discounts = $order->getDiscount();
$discounts->setOrderRefresh(true);
$basket = $order->getBasket();
if (!$basket) {
throw new \Exception(GetMessage("TICKET_ORDER_ERROR_NO_BASKET"));
}
$basket->refreshData(["PRICE", "COUPONS"]);
$result = $discounts->calculate();
if (!$result->isSuccess()) {
throw new \Exception(implode(', ', $result->getErrors()));
}
$discountData = $result->getData();
if (!empty($discountData) && is_array($discountData)) {
$result = $order->applyDiscount($discountData);
if (!$result->isSuccess()) {
throw new \Exception(implode(', ', $result->getErrors()));
}
}
}
private static function generateCoupon(int $orderId, float $amount): string
{
$discount = self::getDiscount($amount);
if (!$discount) {
throw new \Exception("Can't get discount");
}
$fields = [
'DISCOUNT_ID' => $discount['ID'],
'COUPON' => \CatalogGenerateCoupon(),
'ACTIVE' => 'Y',
'TYPE' => 2,
'MAX_USE' => 0,
];
$result = DiscountCouponTable::add($fields);
if (!$result->isSuccess()) {
throw new \Exception(implode(', ', $result->getErrors()));
}
return $fields['COUPON'];
}
private static function getDiscount(float $amount): array|bool
{
Loader::includeModule('catalog');
Loader::includeModule('sale');
$xmlId = "api_discount_$amount";
$discount = \CSaleDiscount::GetList([], ['XML_ID' => $xmlId])->Fetch();
if ($discount) {
return $discount;
}
Loc::loadMessages(__FILE__);
$discountId = \CSaleDiscount::Add([
'NAME' => Loc::getMessage('TICKET_ORDER_DISCOUNT_TITLE', [
'#VALUE#' => Price::format($amount, 'RUB', false),
]),
'LID' => 's1',
'ACTIVE' => 'Y',
'XML_ID' => $xmlId,
'USER_GROUPS' => [TICKETS_DISCOUNT_USER_GROUP_ID],
'CURRENCY' => 'RUB',
'CONDITIONS' => [
'CLASS_ID' => 'CondGroup',
'DATA' => [
'All' => 'AND',
'True' => 'True',
],
'CHILDREN' => [],
],
'USE_COUPONS' => 'Y',
'ACTIONS' => [
'CLASS_ID' => 'CondGroup',
'DATA' => [
'All' => 'AND',
],
'CHILDREN' => [
[
'CLASS_ID' => 'ActSaleBsktGrp',
'DATA' => [
'Type' => 'Discount',
'Value' => $amount,
'Unit' => 'CurAll',
'Max' => 0,
'All' => 'AND',
'True' => 'True',
],
'CHILDREN' => [],
],
],
],
]);
if ($discountId) {
return \CSaleDiscount::GetByID($discountId);
}
global $APPLICATION;
$exception = $APPLICATION->GetException();
return false;
}