Quote to Cash
Overview
The Quote-to-Cash (O2C) process encompasses Customer Account Management, Order Fulfillment, Billing, and Accounts Receivable functions. The coordination of this process is owned by the Enterprise Applications team.
This is a cross-functional page which is meant to be the source of truth for our Quote to Cash (Q2C) systems and underlying data systems and processes.
An efficient Quote-to-Cash system makes purchasing, activating, and managing Denomas subscriptions as easy as possible.
- Improves
customer satisfaction, and alsostreamlines our go-to-market (GTM) processesand acceleratesrevenue growthfor the company. - Ensures
consistencybetween the data for some of the most critical business objects/entities across all the Source Systems. Master Data Objectsfor all core business critical objects will have same definitions and data across all the systems.- Proper
alignment/syncexists between all the data source systems - Zuora, CustomerDot, SFDC and Denomas.com along with 1:1 mapping between Zuora Billing Object Model and CustomersDot. - Improves
data qualityand ensures asingle lineagefor understanding the paid namespace conversion journey, the first paid subscription for a given namespace, free/trial to paid conversion analysis etc..
Q2C System Teams
Quote-to-Cash system projects and initiatives often require close collaboration across functions and teams. The teams most often involved include: Enterprise Applications, Billing Ops, Fulfillment, Field Operations, Support, and Data.
Q2C System Architecture
The Fulfillment Team is re-architecting our Quote 2 Cash Systems, in particular CustomersDot, in a way that promotes more reliability, sustainability, and flexibility. This handbook page serves as the SSOT for the Q2C systems with links back to functional department pages and artifacts.
Cross-Functional SSOT Architecture Plans:
- Fulfillment SSOT Plan: data_architecture
- Central Data Team SSOT Plan: data_architecture
- Sales Systems SSOT Plan: To be added
- Enterprise Apps SSOT Plan: To be added
Zuora serves as the source of truth for Zuora Account and Zuora Contact data once a Subscription is purchased. Prior to a purchase, a user can register for CDot which creates a CustomersDot User record that isn’t associated with an CustomersDot BillingAccount (because it doesn’t exist yet). Once purchased, the CustomersDot BillingAccount record is created along with the related CustomersDot BillingAccountMembership.
Given that CustomersDot User/Zuora Contact and CustomersDot BillingAccount/Zuora Account information can be edited by users directly in CDot or directly in Zuora (or indirectly via SFDC), we need to be mindful of syncing this data between CDot and Zuora. In particular, if we can’t use Zuora callouts to keep the CustomersDot BillingAccount and CustomersDot User records in sync, we will explore Zuora Custom Events.
A CustomersDot User record in CDot is tied to one email address. This email address can be associated with multiple Zuora Accounts, and therefore have multiple Zuora Contacts. Each of these Zuora Contacts could be modified independently. For instance, a billing admin may choose to change the address for Contact A for the billing entity in the US, but not choose to change the address for Contact B (associated with the same email address) for the billing entity in Europe. For this reason, contact metadata could eventually be stored on the CustomersDot BillingAccountMembership model, but we are choosing to keep this lightweight to begin with to reduce scope. We will start by fetching this data from Zuora.
Equivalent Data Objects Across Q2C Systems
This table shows the equivalent data objects across systems:
| Denomas | CustomersDot | Zuora | SFDC |
|---|---|---|---|
| Organization | BillingAccount | Account | BillingAccount |
| User | User | Contact | Contact |
| - | Order | Order | Opportunity & primary quote |
| - | Subscription | Subscription | TBD Quote Amendment |
| License | License | - | - |
| - | Cloud Activation | - | - |
Note: In SFDC, a SFDC BillingAccount is not the same as a SFDC Account. A SFDC Account can have many BillingAccounts.
Note: The Order object in CustomersDot is not the same as the Order object in Zuora, they have different definitions. Orders in CustomerDot are more like subscriptions in Zuora than they are Orders in Zuora. More architecture and definition work needs to be done on the Order object in CustomersDot.
More information about the User and Contact objects shown in the table above, and how they interact together, can be found in this workflow documentation.
CustomerDot Object Model
The following is a focused view of the database ERD for the newly proposed data architecture.
erDiagram
CustomersDotUser ||--o{ CustomersDotBillingAccountMembership : "has many"
CustomersDotUser ||--o{ ZuoraContact : "has many"
CustomersDotBillingAccount ||--o{ CustomersDotBillingAccountMembership : "has many"
CustomersDotBillingAccount ||--o{ CustomersDotCloudActivation : "has many"
CustomersDotBillingAccount ||--o{ CustomersDotLicense : "has many"
CustomersDotBillingAccount ||--o{ CustomersDotOrder : "has many"
CustomersDotBillingAccount ||--|| DenomasOrganization : "has one"
CustomersDotCloudActivation ||--o{ DenomasCloudActivation : "has many"
CustomersDotLicense ||--o{ DenomasLicense : "has many"
CustomersDotUser ||--|| DenomasUser : "has one"
CustomersDotOrder ||--o{ CustomersDotSubscription : "has many"
CustomersDotSubscription ||--|| ZuoraSubscription : "has one"
DenomasUser ||--o{ DenomasMember : "has many"
DenomasOrganization ||--o{ DenomasMember : "has many"
DenomasOrganization ||--o{ DenomasLicense : "has many"
DenomasOrganization ||--o{ DenomasCloudActivation : "has many"
ZuoraAccount ||--o{ ZuoraContact : "has many"
ZuoraAccount ||--o{ ZuoraPaymentMethod : "has many"
ZuoraAccount ||--o{ ZuoraOrder : "has many"
ZuoraAccount ||--o{ ZuoraSubscription : "has many"
ZuoraOrder ||--o{ ZuoraSubscription : "has many"
ZuoraAccount ||--|| CustomersDotBillingAccount : "has one"
SFDCAccount ||--o{ ZuoraAccount : "has many"
SFDCAccount ||--o{ CustomersDotBillingAccount : "has many"
CustomersDotBillingAccount {
bigint id
string zuora_account_id
string zuora_account_name
string zuora_account_number
string zuora_account_entity
string zuora_account_vat_id
string salesforce_account_id
timestamp created_at
timestamp updated_at
}
CustomersDotBillingAccountMembership {
bigint id
bigint user_id
bigint billing_account_id
timestamp created_at
timestamp updated_at
}
CustomersDotUser {
int id
string first_name
string last_name
datetime created_at
datetime updated_at
string email
string encrypted_password
string reset_password_token
datetime reset_password_sent_at
datetime remember_created_at
integer sign_in_count
datetime current_sign_in_at
datetime last_sign_in_at
inet current_sign_in_ip
inet last_sign_in_ip
string provider
string uid
string country
string state
string city
string zip_code
string vat_code
string company
boolean billable
string access_token
string confirmation_token
datetime confirmed_at
datetime confirmation_sent_at
string unconfirmed_email
string address_1
string address_2
string company_size
string authentication_token
string phone_number
boolean login_activated
string refresh_token
datetime_with_timezone access_token_expires_at
datetime_with_timezone token_refresh_last_attempted_at
}
CustomersDotCloudActivation {
bigint id
bigint billing_account_id
string activation_code
string subscription_name
boolean super_sonics_aware
datetime seat_utilization_reminder_sent_at
timestamp created_at
timestamp updated_at
}
CustomersDotLicense {
bigint id
bigint billing_account_id
uuid license_file_md5
bigint creator_id
datetime_with_timezone created_at
datetime_with_timezone updated_at
datetime_with_timezone last_synced_at
datetime_with_timezone next_sync_at
integer users_count
integer previous_users_count
integer trueup_quantity
date expires_at
date starts_at
date trueup_from
date trueup_to
boolean trial
boolean cloud_licensing_enabled
string plan_code
string plan_name
string zuora_subscription_id
string email
string name
string company
string zuora_subscription_name
text notes
text license_file
datetime_with_timezone activated_at
boolean auto_renew_enabled
boolean seat_reconciliation_enabled
boolean operational_metrics_enabled
boolean reconciliation_completed
boolean offline_cloud_licensing_enabled
}
CustomersDotOrder {
int id
bigint billing_account_id
string zuora_product_rate_plan_id
string zuora_subscription_id
string zuora_subscription_name
date start_date
date end_date
integer quantity
datetime created_at
datetime updated_at
string denomas_namespace_id
string denomas_namespace_name
string amendment_type
boolean trial
datetime last_extra_ci_minutes_sync_at
string zuora_account_id
datetime increased_billing_rate_notified_at
boolean reconciliation_accepted
integer trial_extension_type
string source
datetime_with_timezone seat_overage_notified_at
datetime_with_timezone auto_renew_error_notified_at
}
CustomersDotSubscription {
}
ZuoraAccount {
string crm_id
}
ZuoraContact {
}
ZuoraSubscription {
}
ZuoraPaymentMethod {
}
SFDCAccount {
}
DenomasLicense {
}
DenomasCloudActivation {
}
DenomasOrganization {
}
DenomasMember {
}
DenomasUser {
}
Zuora Billing Object Model
Zuora provides a diagram of the relationships of Zuora’s Billing Object Model

To reduce the amount of data issues across our systems, our goal is to try to ensure we have a 1:1 mapping between Zuora Billing Object Model and CustomersDot.
Zuora and Salesforce Integrated Object Model
Zuora CPQ is used to connect Zuora with Salesforce.

Billing Account Master Data Object
Billing Account is a core business entity that holds a paying customer’s most critical account information such as their contact details, payment terms, and payment methods. And this information is used to track subscriptions, amendments, and transactions, such as invoices and payments. The data from this Master Data Object is actively being used in several GTM, Product Usage and Data science Propensity models to understand the billing information of paid customers better etc..
First, we focussed on improving the data architecture alignment between Zuora Billing Accounts and CDot Billing Accounts in order to proceed with developing a Conformed Dimension for Billing Account Entity.
The Customer model in CDot has known design flaws as it represents a combination of both a Contact (individual user) and an Account (organization). Research for this epic can be found in this Spike issue.
Fulfillment data architecture plan
CustomersDot BillingAccount management
CustomersDot BillingAccount management
- BillingAccount: Introduce a BillingAccount and BillingMembership object
- BillingAccount: Update CDot navigation to display new data structure to customers - Link to be updated
- BillingAccount: Multiple CDot customers can manage one BillingAccount
- BillingAccount: CDot customers can manage BillTo and SoldTo contacts
- BillingAccount: One CDot customer can manage multiple BillingAccounts
- BillingAccount: Clean up legacy data objects
Background
In this epic, the focus is on improving the data architecture of CustomersDot to better align with Zuora Billing Accounts. The Customer model in CDot has known design flaws as it represents a combination of both a Zuora Contact (individual user) and a Zuora Account (organization).
Problem
Currently CustomersDot (CDot) has a data object for Customer (e.g. customers DB table) which serves a few different functions:
- A user (with a unique email address) that can login CustomersDot
- Contact information related to a physical person within a Company with metadata like first and last name, email, mailing address, etc.
- Company information that is associated with a Zuora Account with company name.
It is important to note that a Zuora Account maps to a company/customer account which can have many users or contacts. It should not map to one user in particular. In the current architecture, a zuora_account_id can be shared with more than one Customer but this isn’t ideal. We need to have an architecture that accurately reflects the data structure from Zuora and our business model. In CustomersDot, we need to have a data architecture that accurately reflects Zuora’s Billing Objects Model).
Examples of issues this could benefit
Plan
We recommend adding a few new models to the CustomersDot data architecture to better reflect the Zuora data structure.
Most importantly, CDot lacks a model for the CustomersDot BillingAccount (aka. “Company” / “Billing Entity”). Adding this model will allow us to separate the data currently in the CustomersDot Customer model that belongs at a BillingAccount level (see below for an example). We will also be renaming CustomersDot Customer model to CustomersDot User as the current naming is a bit confusing due to Salesforce having a different definition for what a Salesforce Customer is.
zuora_account_idcompany_namevat_codesalesforce_account_id
Additionally, we can add a join table (e.g. billing_account_memberships table) between the CustomersDot BillingAccount and CustomersDot User models which will allow a CustomersDot BillingAccount to have multiple CustomersDot Users. Likewise, a CustomersDot User could be associated to many CustomersDot BillingAccounts.
With this data structure, CDot should consider the data structure of CustomersDot BillingAccount and CustomersDot User as a way of determining which users of CDot should have access to view / manage subscriptions for a Zuora Account. CDot could rely on Zuora for providing the source of truth for who the contacts are for the Zuora Account and likely their metadata (e.g. name, address).
Currently, CDot creates a CustomersDot User record for the SoldTo contact associated with the Subscription Account. In this epic, we could also create a CustomersDot User record for the BillTo contact as well for the same Subscription Account, but this isn’t a requirement. This will effectively allow both types of contacts to login to CDot and manage the Account’s subscriptions.
Why do we need the ability to associate a CustomersDot User with many CustomersDot BillingAccounts?
We considered only allowing a CustomersDot User to be associated with a single CustomersDot BillingAccount, however, we determined that we should build a many-to-many mapping capability because:
- Zuora currently allows for a single user to map to multiple billing accounts.
- We see examples in production where this is already happening (over 1800 user accounts in Zuora currently map to multiple Billing Accounts).
Enabling this will bring parity between CustomersDot and Zuora.
Update: CDot has added BillingAccount, BillingAccountMembership and BillingAccountContact models to align with Zuora Billing models.
Source of Truth
Zuora serves as the source of truth for Zuora Account and Zuora Contact data once a Subscription is purchased. Prior to a purchase, a user can register for CDot which creates a CustomersDot User record that isn’t associated with an CustomersDot BillingAccount (because it doesn’t exist yet). Once purchased, the CustomersDot BillingAccount record is created along with the related CustomersDot BillingAccountMembership.
Given that CustomersDot User/Zuora Contact and CustomersDot BillingAccount/Zuora Account information can be edited by users directly in CDot or directly in Zuora (or indirectly via SFDC), we need to be mindful of syncing this data between CDot and Zuora. In particular, if we can’t use Zuora callouts to keep the CustomersDot BillingAccount and CustomersDot User records in sync, we will explore Zuora Custom Events.
A CustomersDot User record in CDot is tied to one email address. This email address can be associated with multiple Zuora Accounts, and therefore have multiple Zuora Contacts. Each of these Zuora Contacts could be modified independently. For instance, a billing admin may choose to change the address for Contact A for the billing entity in the US, but not choose to change the address for Contact B (associated with the same email address) for the billing entity in Europe. For this reason, contact metadata could eventually be stored on the CustomersDot BillingAccountMembership model, but we are choosing to keep this lightweight to begin with to reduce scope. We will start by fetching this data from Zuora.
Denomas.com SSO as the only sign in option for CustomersDot
With Denomas.com SSO as the only sign in option for Customers Portal, we can eliminate the legacy sign up (email and password) and prepare CDot for future integration with a third party e-commerce provider. Our goal is to streamline the experience between SaaS/self-managed and web direct/sales-assisted customers in how they access their subscription information.
Overall, this will lead to a more secure environment for our customers in CDot and allows us to establish a 1:1 relationship between a CDot customer and a Denomas.com account.
Denomas.com SSO as the only sign up option for CustomersDot
- CDot SSO: Remove email and password sign up
- CDot SSO: Enhance experience for first time login to CDot
- CDot SSO: Migrate more CDot customers to use the Denomas SSO for login
Align CustomersDot Orders to Zuora subscriptions and trials
Align CustomersDot Orders to Zuora subscriptions and trials
- Update Zuora Subscription API integration to more accurately determine subsription state
- Further iterations - TBD
This iteration focuses on breaking apart the CustomersDot Order table to more accurately reflect its representation of Zuora Subscriptions + Trials. In the future, we could explore moving the reference for Denomas Namespace from being stored on the Subscription (and Order) to a Zuora Account. See this LucidChart for more details.
Snowflake Data Warehouse and dbt (data build tool)
We extract data from the Quote to Cash systems towards Snowflake and use dbt to transform the data into data models for reporting and analysis.
Data Architecture Plan
The Fulfillment Team is re-architecting our Quote 2 Cash Systems, in particular CustomersDot, in a way that promotes more reliability, sustainability, and flexibility. A significant result of the new architecture will be to have the same customer definition in CustomerDot, Zuora, and Salesforce. This definition is based on the Billing Account in Zuora and the key for the customer is the billing_account_id. It is necessary to re-architect the data model in Snowflake and dbt in order to align the customer definition to CustomersDot data tables. The data models built that model the Zuora and Salesforce systems have the correct customer definition and no rearchitecting needs to happen for those models at this time.
Important Callouts for the Customer Definition in the Unified Q2C data model:
- The unified customer key is the Billing_Account_Id which joins the systems together. The Billing_Account_Id appears on Q2C systems as follows:
Zuora.Account.Account_IdCustomersDot.Billing_Accounts.Billing_Account_IdSalesforce.Billing_Account.Billing_Account_IdDRAFT: Denomas_Dotcom.Organization.Billing_Account_IdThe Organization Entity Object has not been created yet in Denomas_Dotcom and is still in the validation process. The Billing Account Id Foreign key needs to be determined.
- The source id data (where the data is originated and is considered the SSOT) for billing_account_id lives in Zuora.
- The customer definition is only unified for billing accounts that are in Zuora and Salesforce which are generally limited to paying and formerly paying customers and edu/oss customers.
- The target state for trials is to put them into Zuora. At that time, we would be able to have a unified definition for customers across CustomersDot, Salesforce, and Zuora for their trial to paid activity.
- The target state for how to unify the customer definition for free customers across the Q2C systems needs to be determined. The quantity of free users presents challenges for putting them into Salesforce and Zuora. This area needs further exploration.
- The Account object in Salesforce can have customers that will have a billing account or it can have prospect accounts that do not have a billing account.
The Q2C Re-Architecture will be implemented in various phases with a clear communication to the audience and other cross-functional teams on the Expected Outcomes and Deliverables from each phase.
Phase 1
Design & develop Master Data Objects for Billing Accounts, Orders & Ramps to support Quote to Cash Re-Architecture - Epic
- Design & Implementation of Master Data Object for Billing Accounts
- Design & Implmentation of Master Data Object for Orders(inclduing Ramps)
Phase 2
Design & develop Master Data Objects for Customers, Contacts/Users & Leads to support Quote to Cash Re-Architecture - Epic
- Design & implementation of Master Data Object for Customers/Users/Contacts
- Design & Implementation of Master Data Object for Leads
Conformed Dimensions
Conformed dimensions allow facts and measures to be categorized and described in the same way across multiple facts and/or data marts, ensuring consistent reporting across the enterprise.
Conformed Dimensions correspond to Master data and are critical building blocks of any Data Warehousing Environment.
The below Master Data objects for core business entities will be created that can be used in the different applications across the organization, along with their associated metadata, attributes, definitions, roles, connections, and taxonomies.
- Billing Account
- Customer/User
- Organization
- Order
- Lead
- License
Below is the Entity Relationship Diagram for the Re-architected data model in Snowflake. The Target State tab shows how the business entities we extract from the CustomersDot, Zuora, Salesforce, and Denomas.com source systems connect with each other.
ERDs (Entity Relationship Diagrams) for Business Process Modeling
These ERDs illustrate how we model data from the Quote to Cash Systems in the Snowflake Enterprise Dimensional Model.
Sales Funnel Dimensional Model ERD (Built using Salesforce data)
Service Ping Dimensional Model ERD (Built with CustomerDot, Version App, Zuora, and Salesforce Data)
Common Subscription Dimensional Model ERD (Built using Salesforce and Zuora Data)
ARR (Annual Recurring Revenue) Dimensional Model ERD (Built using Salesforce and Zuora Data)
Conformed Dimension Design for Core Business Objects
Billing Account Master Data Object/Entity (Conformed Dimension Design)
Order Master Data Object/Entity (Conformed Dimension Design)
Customer/User Master Data Object/Entity (Conformed Dimension Design)
dbt Data Lineage Diagrams and Data Dictionaries
Quote to Cash Data Lineage Diagrams illustrate how the data from critical Quote to Cash source tables flow through the Snowflake data models.
Quote to Cash Data Dictionaries provide definitions for the Quote to Cash fields used in the Snowflake Enterprise Dimensional Data Model.
Business Insights and Analysis
Our Data Catalog provides access to Analytics Hubs, Data Guides, ERDs, and Analytics projects relating to the Quote to Cash business processes.
3d741be9)
