Функционал подарочных сертификатов можно реализовать с помощью купонов на скидку на сумму подарочного сертификата. То есть продавать эти купоны на разные суммы. Это стандартный функционал в битрикс.
Но на одном из проектов возникла задача убрать из заказа скидку по купону и добавить оплату с внутреннего счета на ту же сумму, потому что в 1с оплата подарочным сертификатом уже зачислена как аванс, и в заказе должна приходить вся сумма, а не сумма со скидкой.
Чтобы удалить скидку я использовала событие сохранения заказа OnSaleOrderSaved.
Получала из объекта заказа скидки, получала из заказа пользователя, находила id правила, чтобы проверить, что это подарочный сертификат, дальше находила сумму купона,
и убирала из заказа эту скидку.
Далее создавала или сразу зачисляла на счет пользователя сумму купона и оплачивала заказ с внутреннего счета.
1с программиста такая оплата устроила.
Main\EventManager::getInstance()->addEventHandler(
'sale',
'OnSaleOrderSaved',
'ConvertCoupon'
);
function ConvertCoupon($event){
AddMessage2Log("ConvertCoupon");
$order = $event->getParameter("ENTITY");
\Bitrix\Main\Loader::includeModule('sale');
$userId=$order->getUserId();
$discountData = $order->getDiscount()->getApplyResult();
foreach($discountData['FULL_DISCOUNT_LIST'] as $i=>$d){
if($i==43){
$sumCoupon=$d['ACTIONS']['CHILDREN'][0]['DATA']['Value'];
}
}
foreach($discountData["COUPON_LIST"] as $k=>$c){
if($c["DATA"]["DISCOUNT_ID"]==43){
\Bitrix\Sale\DiscountCouponsManager::clearApplyCoupon($k);
$discount=$order->getDiscount();
$discount->setOrderRefresh(true);
$discount->setApplyResult(array());
$basket = $order->getBasket();
$basket->refreshData(array('PRICE', 'COUPONS'));
$discount->setUseMode(1);
$discount->calculate();
$order->save();
if(!CSaleUserAccount::GetByUserID($userId, "RUB")){
$arFields = Array("USER_ID" => $userId, "CURRENCY" => "RUB", "CURRENT_BUDGET" => $sumCoupon);
$useraccId=CSaleUserAccount::Add($arFields);
}
else{
CSaleUserAccount::UpdateAccount( $userId, $sumCoupon, "RUB", "MANUAL", 0 );
}
Bitrix\Sale\Compatible\OrderCompatibility::payFromBudget($order,false,true);
$order->save();
}
}
}