Вы находитесь здесь:
Использование инфраструктуры плана процедур
Чтобы обеспечить выполнение процедур в правильном порядке и последовательное применение ценообразования к смете, создайте новый план процедур.
Требуемые версии
| Доступно в версиях: Lightning Experience |
| Доступно в версиях: Enterprise, Performance, Unlimited и Developer Edition Revenue Cloud с включенным ценообразованием Salesforce |
| Необходимые полномочия пользователя | |
|---|---|
| Для создания и обновления определений плана процедур: | Доступ к плану процедур AND Пользователь времени проектирования ценообразования Salesforce |
| Для создания, обновления и удаления процедур ценообразования: | Доступ к плану процедур ИЛИ Пользователь времени проектирования ценообразования Salesforce |
| Для использования процедур ценообразования: | Пользователь времени выполнения ценообразования Salesforce |
| Для определения, редактирования, удаления, настройки параметров безопасности и настройки версий для классов Apex: | Автор Apex |
Представьте, что вы работаете в авиакомпании и помогаете деловым путешественникам. А теперь забронируем билет! Мы хотим, чтобы наше ценообразование отражало условия рынка в реальном времени и отображало цены в местной валюте клиента.
Прежде чем рассчитать цену, мы автоматически извлекаем динамический базовый тариф из внешней системы для обеспечения конкурентоспособного ценообразования. Мы также применим скидки платформы бронирования и добавим плату за удобство.
После создания плана процедуры мы создадим смету. Потом, в зависимости от расположения пользователя (например, Индия), мы преобразуем общую цену из USD в INR.
Перед началом работы убедитесь, что вы:
- Включите ценообразование Salesforce.
- Имейте полномочия на создание процедур, планов процедур, продуктов и смет.
- Ознакомьтесь со способом создания процедур ценообразования. Дополнительные сведения о процедурах ценообразования см. в разделе «Создание процедур ценообразования с использованием Salesforce Pricing».
- Понимание и умение использовать определения контекста. Чтобы узнать больше об определениях контекста, см. Определения контекста.
- Используйте одинаковое определение контекста в процедурах ценообразования и планах процедур.
Определения плана процедур могут быть сложными, особенно если они связаны с классами Apex и разными процедурами ценообразования. Выполните данные действия, чтобы создать смету и узнать, как сделать ценообразование динамичным и точным, не усложняя саму процедуру.
Включение оркестрации плана процедур для ценообразования
- Введите строку «Параметры дохода» в поле «Быстрый поиск» меню «Настройка» и выберите пункт «Параметры дохода».
- Найдите и включите оркестрацию плана процедур для ценообразования.
- Найдите и включите параметр «Исключить стандартные процедуры и процедуры ценообразования транзакций продажи».
Создание коммерческого продукта
- В средстве запуска приложений найдите и откройте «Продукты».
-
Создайте коммерческий продукт под названием Дели - Нью-Йорк.
Чтобы узнать, как создать продукт, см. «Создание простых продуктов» и убедитесь, что тип записи продукта установлен на «Коммерческий».
- Добавьте продукт в каталог и создайте для него запись прайс-листа.
- В разделе «Настройка» в поле «Быстрый поиск» найдите и выберите «Настройка ценообразования Salesforce».
- В разделе «Синхронизация данных ценообразования» нажмите «Синхронизация».
Создание процедуры ценообразования
-
Создайте процедуру ценообразования и назовите ее Процедура ценообразования авиабилетов.
Чтобы создать процедуру ценообразования, выполните первые 5 действий в разделе «Настройка процедуры ценообразования».
-
Создание постоянных. Эти постоянные будут служить структурными нулями для фиксированных значений в процедуре ценообразования.
Постоянное имя Тип данных Стандартное значение AdjType ТЕКСТ Процент AdjValue ЧИСЛО 5 Переопределение ТЕКСТ Переопределение ConvFeeAdjType ТЕКСТ Стоимость ConvFeeAdjValue ЧИСЛО -250 -
Добавьте следующие элементы.
- Настройка цен
- Цена по прайс-листу. Используйте таблицу решений V2 прайс-листа.
- Скидки вручную. Вам нужно добавить три элемента скидки вручную.
-
Первый элемент скидки вручную добавляется для расчета динамического базового тарифа рейса. Соотнесите эти переменные.
- Переменные ввода
- Тип поправки: Переопределение
- Значение поправки: PartnerUnitPrice
- Количество: LineItemQuantity
- Цена входной единицы: ListPrice
- Переменная вывода
- Цена нетто за единицу: NetUnitPrice
- Переменные ввода
-
Второй элемент скидки вручную добавляется для расчета скидки платформы за бронирование авиабилетов. Соотнесите эти переменные.
- Переменные ввода
- Тип поправки: AdjType
- Значение поправки: AdjValue
- Количество: LineItemQuantity
- Цена входной единицы: PartnerUnitPrice
- Переменная вывода
- Цена нетто за единицу: NetUnitPrice
- Переменные ввода
-
И последний элемент скидки вручную добавляется для расчета платежа за удобство для выставления счета клиенту за бронирование авиабилетов.
- Переменные ввода
- Тип поправки: ConvFeeAdjType
- Значение поправки: ConvFeeAdjValue
- Количество: LineItemQuantity
- Цена входной единицы: NetUnitPrice
- Переменная вывода
- Цена нетто за единицу: NetUnitPrice
- Переменные ввода
- Настройте параметры для просмотра сведений о ценообразовании, доступа к профилю и рейтинга.
- Сохраните процедуру.
- Активируйте процедуру.
Ваша процедура должна выглядеть следующим образом. Для большей ясности мы переименовали каждый элемент скидки вручную, чтобы отобразить расчет цен, который он будет выполнять. Чтобы переименовать элемент, нажмите
и введите нужное имя.

Определение классов для Apex Hooks
- Введите строку Apex в поле «Быстрый поиск» меню «Настройка» и выберите пункт «Классы Apex».
- Нажмите «Создать».
-
Первый класс Apex - это предварительный крюк, который извлекает все элементы транзакций продаж из контекста ценообразования и переопределяет их тег PartnerUnitPrice с динамическим случайным базовым тарифом в диапазоне от 990 до 1200 перед ценообразованием выполнения из внешней базы данных.
public class DynamicFlightBasePriceApex implements RevSignaling.SignalingApexProcessor { public RevSignaling.TransactionResponse execute(RevSignaling.TransactionRequest request) { System.debug('Executing PREHOOK'); String contextId = request.ctxInstanceId; Context.IndustriesContext industriesContext = new Context.IndustriesContext(); //Query SalesTransactionItem nodes Map<String, Object> inputQueryItem = new Map<String, Object>{ 'contextId' => contextId, 'tags' => new List<String>{ 'SalesTransactionItem' } }; Map<String, Object> itemQueryOutput = industriesContext.queryTags(inputQueryItem); Map<String, Object> itemQueryResult = (Map<String, Object>)itemQueryOutput.get('queryResult'); List<Object> itemData = (List<Object>) itemQueryResult.get('SalesTransactionItem'); System.debug('QLI itemData=' + itemData); // Generate random price between 990 and 1200 Decimal minPrice = 990; Decimal maxPrice = 1200; Decimal range = maxPrice - minPrice; // Use Crypto.getRandomInteger() to generate a secure random number Integer randomInt = Math.abs(Crypto.getRandomInteger()); Decimal randomPrice = minPrice + Math.mod(randomInt, range.intValue() + 1); System.debug('Generated Random Price: ' + randomPrice); // STEP 3 - Build update list List<Map<String, Object>> itemNodeUpdates = new List<Map<String, Object>>(); for (Object itemObj : itemData) { Map<String, Object> itemNode = (Map<String, Object>) itemObj; List<Object> dataPath = (List<Object>) itemNode.get('dataPath'); System.debug('Full item dataPath: ' + JSON.serialize(dataPath)); dataPath.remove(0); // Remove contextId itemNodeUpdates.add(new Map<String, Object>{ 'nodePath' => new Map<String, Object>{ 'dataPath' => dataPath }, 'attributes' => new List<Object>{ new Map<String, Object>{ 'attributeName' => 'PartnerUnitPrice', 'attributeValue' => randomPrice } } }); } // STEP 4 - Submit context update if (!itemNodeUpdates.isEmpty()) { Map<String, Object> updateInput = new Map<String, Object>{ 'contextId' => contextId, 'nodePathAndAttributes' => itemNodeUpdates }; System.debug('--- PREHOOK: SUBMITTING CONTEXT UPDATE ---'); System.debug(JSON.serializePretty(updateInput)); industriesContext.updateContextAttributes(updateInput); } // Return the response RevSignaling.TransactionResponse response = new RevSignaling.TransactionResponse(); response.status = RevSignaling.TransactionStatus.SUCCESS; response.message = 'Apex executed successfully with Random Price: ' + randomPrice; return response; } } -
Создайте другой класс Apex.
Этот класс Apex является posthook, который извлекает тег NetUnitPrice после ценообразования и преобразует его в местную валюту INR (индийские рупии) посредством имитации динамического курса обмена между 85 и 86. Потом он обновляет описание элемента транзакции продажи новым тарифом INR, предоставляя локализованное ценообразование для клиентов Индии.
public class ConvertFareToINRApex implements RevSignaling.SignalingApexProcessor { public RevSignaling.TransactionResponse execute(RevSignaling.TransactionRequest request) { System.debug('Executing POSTHOOK'); String contextId = request.ctxInstanceId; Context.IndustriesContext industriesContext = new Context.IndustriesContext(); //Query SalesTransactionItem nodes Map<String, Object> inputQueryItem = new Map<String, Object>{ 'contextId' => contextId, 'tags' => new List<String>{ 'SalesTransactionItem' } }; Map<String, Object> itemQueryOutput = industriesContext.queryTags(inputQueryItem); Map<String, Object> itemQueryResult = (Map<String, Object>)itemQueryOutput.get('queryResult'); List<Object> itemData = (List<Object>) itemQueryResult.get('SalesTransactionItem'); System.debug('QLI itemData=' + itemData); //Query NetUnitPrice nodes Map<String, Object> inputQueryItem2 = new Map<String, Object>{ 'contextId' => contextId, 'tags' => new List<String>{ 'NetUnitPrice' } }; Map<String, Object> itemQueryOutput2 = industriesContext.queryTags(inputQueryItem2); Map<String, Object> itemQueryResult2 = (Map<String, Object>)itemQueryOutput2.get('queryResult'); List<Object> itemData2 = (List<Object>) itemQueryResult2.get('NetUnitPrice'); System.debug('NetUnitPrice itemData=' + itemData2); Map<String, Object> netUnitTagData = (Map<String, Object>) itemData2.get(0); Decimal netUnitPrice = (Decimal) netUnitTagData.get('tagValue'); netUnitPrice = netUnitPrice.setScale(2); System.debug('NetUnitPrice Tag Value=' + netUnitPrice); // Generate random price between 85.00 and 86.00 with decimals Decimal minPrice = 85.00; Decimal maxPrice = 86.00; Decimal range = maxPrice - minPrice; Integer randomInt = Math.abs(Crypto.getRandomInteger()); Integer randomDecimalInt = Math.mod(randomInt, 100); Decimal randomFraction = Decimal.valueOf(randomDecimalInt) / 100; Decimal usdToInrRate = minPrice + randomFraction; if (usdToInrRate > maxPrice) { usdToInrRate = maxPrice; } // Calculate NetUnitPrice in INR Decimal fareInInr = (netUnitPrice * usdToInrRate).setScale(2); String fareMessage = 'The Flight fare in INR is: ' + fareInInr + ' (USD ' + netUnitPrice + ' at rate ' + usdToInrRate + ')'; System.debug(fareMessage); // STEP 3 - Build update list List<Map<String, Object>> itemNodeUpdates = new List<Map<String, Object>>(); for (Object itemObj : itemData) { Map<String, Object> itemNode = (Map<String, Object>) itemObj; List<Object> dataPath = (List<Object>) itemNode.get('dataPath'); System.debug('Full item dataPath: ' + JSON.serialize(dataPath)); dataPath.remove(0); // Remove contextId itemNodeUpdates.add(new Map<String, Object>{ 'nodePath' => new Map<String, Object>{ 'dataPath' => dataPath }, 'attributes' => new List<Object>{ new Map<String, Object>{ 'attributeName' => 'SalesTrxnItemDescription', 'attributeValue' => fareMessage } } }); } // STEP 4 - Submit context update if (!itemNodeUpdates.isEmpty()) { Map<String, Object> updateInput = new Map<String, Object>{ 'contextId' => contextId, 'nodePathAndAttributes' => itemNodeUpdates }; System.debug('--- PREHOOK: SUBMITTING CONTEXT UPDATE ---'); System.debug(JSON.serializePretty(updateInput)); industriesContext.updateContextAttributes(updateInput); } // Return the response RevSignaling.TransactionResponse response = new RevSignaling.TransactionResponse(); response.status = RevSignaling.TransactionStatus.SUCCESS; response.message = 'Apex executed successfully with Price in INR: ' + fareInInr; return response; } }
Настройка определения настраиваемого плана процедуры
- В разделе «Настройка» в поле «Быстрый поиск» найдите и выберите «Определения плана процедур».
- Нажмите «Создать»
-
Укажите данные сведения.
-
Заголовок: План процедуры бронирования авиабилетов.
Нажмите «Вкладка», чтобы автоматически заполнить имя разработчика.
- Тип процесса: Revenue Cloud.
- Основной объект: Смета.
-
Определение контекста: <Имя определения контекста>.
Вам нужно выбрать определение контекста, созданное для вашего сценария использования. Однако, убедитесь, что это определение контекста, используемое при создании процедуры ценообразования.
- Сохраните изменения.
-
Заголовок: План процедуры бронирования авиабилетов.
- Откройте созданную запись определения плана процедуры.
- Чтобы добавить нужные процедуры в разделы плана процедур, выберите «Добавить».
-
Добавьте первый раздел для получения динамической базовой цены нашего рейса. Укажите данные сведения.
- Тип: Стандартно.
- Имя: DynamicBasePriceApex.
- Тип раздела: Apex.
-
После добавления раздела нажмите
и укажите данные сведения.
- Этапы: Ценообразование
- Тип разрешения: По умолчанию
- Apex: DynamicFlightBasePriceApex
Должно выглядеть примерно так:
-
Таким же образом, добавьте еще один раздел для выполнения расчета ценообразования и переопределите базовую цену с ценой, созданной с помощью предварительного крюка Apex. Укажите данные значения.
- Тип: Стандартно.
- Имя: FlightPriceCalculation.
- Тип раздела: Процедура ценообразования .
-
Нажмите
и укажите данные сведения.
- Этапы: Ценообразование
- Тип разрешения: По умолчанию
- Процедура: Flight_Booking_Pricing_Procedure
-
Наконец, добавьте раздел для преобразования цены из USD в INR (Доллар США в индийскую рупию), добавив этот постхук Apex для пользователей, чья Страна для счета установлена на Индию
- Тип: Стандартно.
- Имя: ConvertFareToINR.
- Тип раздела: Apex.
-
Нажмите
и укажите данные сведения.
- Этапы: Ценообразование
- Тип разрешения: На основе правил
- Требования к условиям: Соответствие всем условиям (AND)
- Ресурс: Счет в страну
- Оператор: Равно
- Значение вывода: Индия
- Apex: ConvertFareToINRApex
- Сохраните, а потом активируйте определение плана процедуры.
Проверка выполнения плана процедур
Чтобы проверить, выполняется ли план процедуры в заданном нами порядке и корректность ценообразования, необходимо создать смету.
-
Создание сметы.
В поле «Выставить счет стране» введите Индия.
- Сохраните изменения.
- Нажмите «Об зор каталогов» и добавьте продукт Дели - Нью-Йорк к с мете.
-
Наведите указатель мыши на значение «Цена нетто за единицу» для просмотра сведений о каскадной цене.
Вы увидите применение плана процедуры и скидки и дополнения, настроенные в процедуре ценообразования.
-
Чтобы просмотреть преобразованный курс для элемента строки сметы, нажмите
в строке элемента строки сметы и выберите «Просмотр».
-
Описание позиции строки отображает локализованную цену для вашего рейса.

