Integrate SFDC CPQ with Zuora CPQ
Use the information in this article to install and configure the Salesforce CPQ connector for Zuora Billing. The article includes prerequisites, setup steps, mapped field descriptions, and reference use cases.
Prerequisites
Make sure the customer's Zuora Billing tenant is set up before starting the configuration.
Procedure
Complete the following steps to set up the Salesforce CPQ connector for Zuora Billing:
- Log in to the Zuora environment with your credentials.
- Navigate to Marketplace and choose My Connector Hub. You'll find a list of all the Salesforce connectors for configuration.
- To configure, select Salesforce(Dev).
- Verify your access to the Salesforce CPQ customer instance.
- Customize the fields to be synchronized from Salesforce to Zuora, if necessary.
Once the connector is successfully set up, you have the ability to view and configure them. To view and update the list of all the enabled connectors,
- Navigate to the My Connector tab.
- Add custom fields to the respective connector details.
Objects and Field Mappings
The Zuora-Salesforce CPQ connector has two types of field mappings:
Standard field mappings
The connector setup's standard fields enable the mapping of contact, account, person account, and opportunity fields to lead records during conversion.
The following field names are identical in SFDC CPQ connector and Zuora.
SFDC CPQ Field |
Zuora Field |
---|---|
Contact |
Contact |
Account |
Customer Account |
Order |
Order |
Subscription |
Subscription |
Assets |
Order Line items |
Contract |
Subscription->Contract custom field |
Product2 |
Product |
Pricebook |
Zuora RatePlan/RatePlanCharge/RatePlanChargeTier |
Technical details on standard field mapping
This section provides detailed information about object and field mapping for the SFDC CPQ and Zuora Connector.
Account
SFDC CPQ Field Name |
Zuora Field Name |
Description |
---|---|---|
createAccountRequest.accountNumber(accountId)`: |
Account Number |
Sets the account number for the new Zuora account to the value of `accountId`. Presumably, `accountId` is a variable representing the account identifier in Salesforce. |
.crmId(account.getId())` |
CRM Account ID |
Sets the CRM (Customer Relationship Management) ID for the new account to the ID of the associated `account` in Salesforce. |
.currency("USD")`: |
Currency |
Sets the currency for the new account to "USD". The default currency is set as "USD". |
billCycleDay(1L) |
Bill Cycle day |
Sets the bill cycle day for the new account to the 1st day of the billing cycle. |
.billToContact(new POSTAccountTypeBillToContact() ... )` billToContact
|
BillTo |
Creates a `POSTAccountTypeBillToContact` object and sets various contact-related information for billing, such as address, city, zip code, state, country, first name, last name, work email, home phone, mobile phone, and other phone. These details are retrieved from the associated `AccountSObject` (`account`) and `ContactSObject` (`contact`) in Salesforce. |
.invoiceCollect(null)` |
Sets the field as null, indicating that the invoice collection information is not specified in the request. |
|
.autoPay(false) |
Auto-pay |
Sets the auto-pay option for the account to `false`, indicating that the account will not be automatically charged. |
.invoice(null) |
Sets the field as null, indicating that the invoice details are not specified in the request. |
|
.notes(account.getDescription()) |
Account description |
Sets the notes/description for the new account using the description field of the associated `account` in Salesforce. |
.name(account.getName())` |
Account Name |
Sets the name of the new account using the name field of the associated `account` in Salesforce. |
.salesRep(account.getOwnerId())` |
Sales Rep |
Sets the sales representative ID for the new account using the `OwnerId` field of the associated `account` in Salesforce. |
Order
SFDC CPQ Field Name |
Zuora Field Name |
Description |
---|---|---|
orderAction.contains("New")`: |
Checks if the `contractAction` contains the string "New." Note: if the contract action contains "New," it indicates a new order, and the code proceeds to create an instance of `POSTOrderRequestType`. |
|
`orderRequest.orderNumber(orderSObject.getOrderNumber())`:. |
Order Number |
Sets the order number for the new order using the value from the `getOrderNumber()` method of the `orderSObject` object. By default, the order status is set to pending. |
`orderRequest.existingAccountNumber(orderSObject.getAccountId())`: |
Account |
Sets the account number associated with the order using the value from the `getAccountId()` method of the `orderSObject` object. |
orderRequest.description(orderSObject.getDescription())`: |
Description |
Sets the description of the order using the value from the `getDescription()` method of the `orderSObject` object. |
orderRequest.orderDate(orderSObject.getEffectiveDate())`: |
Order Date |
Sets the order date using the value from the `getEffectiveDate()` method of the `orderSObject` object. |
quote(new QuoteObjectFields())`: |
Sets the quote information associated with the order. Here, an empty `QuoteObjectFields` object is used with default values. |
|
: addOrderActionsItem(new CreateOrderOrderAction() ... )` |
Order Actions |
Adds an order action to the order request. A `CreateOrderOrderAction` object is created and populated with subscription-related details. |
Subscription
SFDC CPQ Field Name |
Zuora Field Name |
Exception |
---|---|---|
addSubscriptionsItem(new POSTOrderAsyncRequestTypeSubscriptionsInner() ... )`: |
Adds subscription information to the order request. A `POSTOrderAsyncRequestTypeSubscriptionsInner` object gets populated with subscription-related details. |
|
`subscriptionNumber(String.valueOf(sfdcDataObject.getOrderSObjectSBQQSubscriptionCSObjectBiMap().get(orderSObject).getName()))`: . |
Subscription ID |
Sets the subscription number using the `getName()` method of the subscription associated with the order from the `sfdcDataObject`. |
subscriptionOwnerAccountNumber(orderSObject.getAccountId())`: |
Subscription Account |
Sets the account number for the subscription owner using the value from the `getAccountId()` method of the `orderSObject` object. |
terms(new CreateOrderCreateSubscriptionTerms() ... )`: |
Sets the term(s) for the subscription using the `CreateOrderCreateSubscriptionTerms` object, including the initial term, period, and period type. |
|
renewalSetting(CreateOrderCreateSubscriptionTerms.RenewalSettingEnum.TO_EVERGREEN)`: |
Sets the renewal setting for the subscription to "TO_EVERGREEN," indicating that the subscription must be renewed automatically. |
|
addSubscribeToRatePlansItem(new CreateOrderRatePlanOverride() ... )`: |
Adds a rate plan override for the subscription. A `CreateOrderRatePlanOverride` object gets created and populated with information about the product rate plan associated with the subscription. |
|
externalCatalogPlanId(sfdcDataObject.getProduct2SObjectMap().get(orderItemSObject.getProduct2Id()).getProductCode())`: for the rate plan override using the product code from the associated product (`orderItemSObject.getProduct2Id()`). |
Sets the external catalog plan ID. |
|
`productRatePlanChargeId(flowContext.getZuoraPRPtoPRPC().get(sfdcDataObject.getProduct2SObjectMap().get(orderItemSObject.getProduct2Id()).getProductCode()))`: |
Sets the product rate plan charge ID for the rate plan override. A mapping of (`flowContext.getZuoraPRPtoPRPC()`) is used for retrieval based on the product code. |
|
`chargeNumber(orderItemSObject.getId())`: |
Sets the charge number for the rate plan override using the ID of the associated order item (`orderItemSObject`). |
|
pricing(new CreateOrderChargeOverridePricing() ... )`: |
Sets the pricing details for the rate plan override, including recurring per-unit pricing (quantity and list price). |
|
Subscription trigger dates
|
Subscription status is based on the boolean data type. For NO, the subscription gets created in State - Activated. For YES, the subscription gets created in State - Pending. |
|
From SDC Order SBQQ__PaymentTerm__c |
Payment term |
View the Customize payment term line item from Billing Settings. |
Order Line Items
SFDC CPQ Field Name |
Zuora Field Name |
Description |
---|---|---|
BillToContactId
|
BillTo |
|
ShipToContactId |
soldTo |
|
Billing address |
A new Contact created in Zuora and added to BillTo |
For example, Order-000195ContactBillTo |
Shipping address |
A new Contact created in Zuora and added to SoldTo |
For example, Order-000195ContactSoldTo |
orderItemSObject1.getUnitPrice() |
listPricePerUnit |
|
No related field in salesforce |
CreateOrderOrderLineItem.ItemCategoryEnum.SALES |
itemCategory : “Sales” is hardcoded |
No related field in salesforce |
productRatePlanChargeId |
getZuoraPRPtoPRPC() |
getProduct2Id()) |
get(orderItemSObject1.getProduct2Id())) |
|
orderItemSObject1.getQuantity() |
quantity |
|
orderItemSObject1.getOrderId() |
purchaseOrderNumber |
|
sfdcDataObject.getProduct2SObjectMap() .get(orderItemSObject1.getProduct2Id()) .getName()) |
itemName |
|
rderItemSObject1.getOrderItemNumber() |
ItemNumber |
|
orderItemSObject1.getDescription()) |
Description |
|
No related field in salesforce |
iTemType |
itemType : “Product” |
**Custom field OrderStatus required in Salesforce. Executing, SentToBilling, Complete , Canceled |
iTemState |
itemState : You can configure the source custom field for this value in SFDC, if not provided the default is “Sent To Billing”. |
billTargetDate |
billTargetDate |
|
orderItemSObject1.getProduct2Id())); |
productCode |
|
orderItemSObject1.getCustomFields()) |
customFields |
Product
SFDC CPQ Field Name |
Zuora Field Name |
Description |
---|---|---|
product2SObject.getName() |
Product Name |
Sets the name of the product using the `getName()` method of the `product2SObject` object. |
product2SObject.getDescription |
Product description |
Sets the description of the product using the `getDescription()` method of the `product2SObject` object. |
product2SObject.getProductCode() |
Product SKU |
Sets the SKU (Stock Keeping Unit) of the product using the `getProductCode()` method of the `product2SObject` object. |
LocalDate.of(2000, 1, 1) |
Effective Period |
Sets the effective start date of the product to January 1, 2000, using the `of()` method of `LocalDate` class. |
LocalDate.of(3000, 1, 1) |
Effective Period |
Sets the effective end date of the product to January 1, 3000, using the `of()` method of `LocalDate` class. |
Product Rate Plan
SFDC CPQ Field Name |
Zuora Field Name |
Description |
---|---|---|
product2SObject.getProductCode() |
PRP Externally Managed Plan Ids |
Sets the externalPlanIds of the product rate plan using the `getProductCode()` method of the `product2SObject` object. It appears that the `externalPlanIds` is used as an identifier for the product rate plan, and it's set to the value of the product's SKU or unique code. |
product2SObject.getName()`: |
PRP Name |
Sets the name of the product rate plan using the `getName()` method of the `product2SObject` object. |
zuoraProductId |
Sets the productId of the product rate plan using the value provided in the `zuoraProductId` parameter. This identifier is linked to the Zuora product for this rate plan. |
|
product2SObject.getDescription()`: |
Sets the description of the product rate plan using the `getDescription()` method of the `product2SObject` object. |
|
LocalDate.of(2000, 1, 1 |
Effective Start Date |
Sets the effective start date of the product rate plan to January 1, 2000, using the `of()` method of `LocalDate` class. |
`LocalDate.of(3000, 1, 1) |
Effective End Date |
Sets the effective end date of the product rate plan to January 1, 3000, using the `of()` method of `LocalDate` class. |
Product Rate Plan Charge
This function appears to be a Java method that synchronizes product rate plan charge data to Zuora, a billing platform. Let's go through each field of the input object and see how it is mapped to the request that is sent out to Zuora
SFDC CPQ Field Name |
Zuora Field Name |
Description |
---|---|---|
product2SObject |
zuoraProductRatePlanId |
Iidentifier of the Zuora product rate plan to which the charge will be associated. |
createProductRatePlanCharge.productRatePlanId(zuoraProductRatePlanId)` |
Sets the Zuora product rate plan ID for the new charge using the value provided in `zuoraProductRatePlanId`. |
|
product2SObject.getName |
createProductRatePlanCharge.name(product2SObject.getName()) |
Sets the name of the charge using the name of the product from the `product2SObject`. |
Quantity |
createProductRatePlanCharge.defaultQuantity(1.0)`: |
Sets the default quantity for the charge to 1.0. |
createProductRatePlanCharge.chargeModel("Per Unit Pricing")`: |
Sets the charge model for the new charge to "Per Unit Pricing". |
|
product2SObject.getSbQQChargeTypeC()` |
switch (product2SObject.getSbQQChargeTypeC())`: |
A switch statement based on the value of `product2SObject.getSbQQChargeTypeC()`, which appears to be a custom field in the `product2SObject` representing the charge type. Note: If no `chargeType` is provided in the `product2SObject`, the default `Recurring` charge type is set in the `createProductRatePlanCharge` object. Inside the switch statement:
|
product2SObject.getSbQQTaxCodeC() |
createProductRatePlanCharge.taxCode(product2SObject.getSbQQTaxCodeC()) |
Sets the tax code for the charge using the value from the `SbQQTaxCodeC` field in the `product2SObject`. |
product2SObject.getSbQQTaxableC() |
createProductRatePlanCharge.taxable(product2SObject.getSbQQTaxableC())` |
Sets whether the charge is taxable or not using the value from the `SbQQTaxableC` field in the `product2SObject`. |
`createProductRatePlanCharge.billCycleType("DefaultFromCustomer")`: |
Sets the bill cycle type to "DefaultFromCustomer" for the charge. |
|
createProductRatePlanCharge.billingPeriod("Month")`: |
Sets the billing period for the charge to "Month". |
|
`createProductRatePlanCharge.UOM("Each")`: |
Sets the unit of measure for the charge to "Each." |
|
`createProductRatePlanCharge.useDiscount |
SpecificAccountingCode(false)`: Sets whether to use discount-specific accounting codes to false. |
|
createProductRatePlanCharge.triggerEvent("ContractEffective")`: |
Sets the trigger event for the charge to "ContractEffective." |
|
createProductRatePlanCharge.productRatePlanChargeTierData(new ProxyCreateOrModifyProductRatePlanChargeTierData() ... )`: |
Sets the tier data for the charge. It includes the currency and price information. |
Custom Field mappings
During the connector setup, customers can configure additional custom fields to synchronize from Salesforce to Zuora.