Scheduling¶
What is contract scheduling?¶
Contract scheduling is when a contract is started or ended at some future point relative to when it was created or updated. This could look like creating a contract to start at the beginning of next month, or conversely complete at the end of the next month. Scheduling is controlled by the started_at
and ended_at
of a contract or it’s pricing. From a glance it might seem like all contracts are scheduled, but this is not the case since the most frequent started_at
is equal to the created_at
and the ended_at
is often indefinite. Eventually, when the customer signals the contract is coming to an end the ended_at
is scheduled.
Why is contract scheduling important?¶
Provisioning at some future date is primarily accomplished through scheduling. An automated script or a post-it note could also enable a contract to be created at some upcoming date but it can be less effort and provide higher visibility if it’s built into the data modeling. The most straightforward use cases are swapping out pricing, packaging or administrative changes. More complex use cases like creating multiple contracts scheduled one after the other far in advance can also be accomplished. Once the contracts are set the associated revenue documents can be created as well, in draft, to enable visibility into the invoice schedule. This can be useful for multiple purposes: debugging end of month invoicing, establishing a future looking revenue waterfall or reconciling invoices with sales accounts.
How to model contract scheduling¶
The most basic way to model contract scheduling is to set the started_at
and ended_at
on the contract
. An alternative is to set this solely on the contract_price
which allows for a separate schedule to be established. With these primatives we can handle almost any type of scheduling use case.
Basic contract scheduling¶
To demonstrate the standard case of contract scheduling, let’s demonstrate starting a contract at the beginning of the next month and then having it end prematurely.
As of 6/1/2024, “4throck” requires customer support for 2 weeks in July. They are going to be onboarding a new teammate and would like to have someone from Wikipedia pitch in to guide them.
This can be modeled by creating a new contract for “4throck” that started on 7/1/2024 and ends on 7/15/2024. Given this is an add-on, a new pricebook won’t required and the pricing will be tied directly to the contract itself.
products.id |
products.name |
prices.contract_price_uid |
prices.price |
prices.prorate |
contracts.customer_id |
contracts.durable_id |
contracts.started_at |
contracts.ended_at |
---|---|---|---|---|---|---|---|---|
7 |
Customer support fee |
6 |
1000.00 |
true |
4throck |
bschedule_contract |
2024-07-01 |
2024-07-15 |
This results in a single invoice being generated for the two week period that occurs in the July. As of 6/1/2024 this invoice is still considered DRAFT
since the billing period hasn’t begun yet. Another note is that the line item that is generated is prorated. This occurs since the customer support product is intended to be offered for a month while the time period of the contract is limited to two weeks.
products.id |
products.name |
line_items.price |
line_items.quantity |
line_items.amount |
invoices.total |
invoices.invoice_delivery |
invoices.status |
invoices.contract_id |
invoices.started_at |
invoices.ended_at |
---|---|---|---|---|---|---|---|---|---|---|
7 |
Customer support fee |
1000.00 |
1.0 |
451.61 |
451.61 |
ADVANCED |
DRAFT |
bschedule_contract |
2024-07-01 00:00:00 |
2024-07-15 00:00:00 |
Contract price scheduling¶
A different way to model the same example could be accomplished using contract_prices
if the customer already has an active contract. An add-on could be directly added as a contract_price
with a specific started_at
and ended_at
. This could be a more efficient, but less auditable way of modeling the customer support fee.
products.id |
products.name |
prices.contract_price_uid |
prices.price |
prices.prorate |
prices.started_at |
prices.ended_at |
contracts.customer_id |
contracts.durable_id |
contracts.started_at |
contracts.ended_at |
---|---|---|---|---|---|---|---|---|---|---|
1 |
Updates |
0.10 |
2023-11-01 |
2024-11-01 |
4throck |
4throck_contract |
2023-11-01 |
2024-11-01 |
||
2 |
Creates |
0.05 |
2023-11-01 |
2024-11-01 |
4throck |
4throck_contract |
2023-11-01 |
2024-11-01 |
||
3 |
Platform fee |
1000.00 |
2023-11-01 |
2024-11-01 |
4throck |
4throck_contract |
2023-11-01 |
2024-11-01 |
||
7 |
Customer support fee |
7 |
1000.00 |
true |
2024-07-01 |
2024-07-15 |
4throck |
4throck_contract |
2023-11-01 |
2024-11-01 |
Similar to the basic scheduling in the earlier demonstration only a single additional invoice is created amongst the existing invoices for the adjusted contract.
products.id |
products.name |
line_items.price |
line_items.quantity |
line_items.amount |
invoices.total |
invoices.invoice_delivery |
invoices.status |
invoices.contract_id |
invoices.started_at |
invoices.ended_at |
---|---|---|---|---|---|---|---|---|---|---|
7 |
Customer support fee |
1000.00 |
1.0 |
451.61 |
451.61 |
ADVANCED |
DRAFT |
4throck_contract |
2024-07-01 00:00:00 |
2024-07-15 00:00:00 |
Multi-contract scheduling¶
Scheduling multiple contracts at once does not change how the data models are formed. What is more interesting is seeing the resulting contracts, prices and revenue documents. In order to demonstrate what this could look like a hypothetical deal has been put into motion:
As of 6/1/2024, a new customer, “aBigDeal” decides to onboard onto Wikipedia’s content upload product. This new customer intends to spend quite a bit of money so the sales team rolls out the red carpet. This results in a contract where the first year is discounted by 20% and the year after that is full price. “aBigDeal” is also interested in customer support for the first 6 months of their first year. After the contract is signed it turns out that “aBigDeal” can only go through procurement in the next quarter, 10/1/2024, and the sales team allows for them to use the product in a trial mode, free usage with rate limiting, until then.
There are several ways to model this, but in the context of contract scheduling this will be our primary lever. Using 3 different contracts and an add-on can represent the needs of “aBigDeal” over the next 2-3 years.
products.id |
products.name |
prices.contract_price_uid |
prices.price |
prices.prorate |
prices.started_at |
prices.ended_at |
contracts.customer_id |
contracts.durable_id |
contracts.started_at |
contracts.ended_at |
---|---|---|---|---|---|---|---|---|---|---|
1 |
Updates |
8 |
0.00 |
2024-06-01 |
2024-10-01 |
aBigDeal |
multi_sched_trial |
2024-06-01 |
2024-10-01 |
|
2 |
Creates |
9 |
0.00 |
2024-06-01 |
2024-10-01 |
aBigDeal |
multi_sched_trial |
2024-06-01 |
2024-10-01 |
|
3 |
Platform fee |
10 |
0.00 |
2024-06-01 |
2024-10-01 |
aBigDeal |
multi_sched_trial |
2024-06-01 |
2024-10-01 |
products.id |
products.name |
prices.contract_price_uid |
prices.price |
prices.prorate |
prices.started_at |
prices.ended_at |
contracts.customer_id |
contracts.durable_id |
contracts.started_at |
contracts.ended_at |
---|---|---|---|---|---|---|---|---|---|---|
1 |
Updates |
11 |
0.04 |
2024-10-01 |
2025-10-01 |
aBigDeal |
multi_sched_disc |
2024-10-01 |
2025-10-01 |
|
2 |
Creates |
12 |
0.032 |
2024-10-01 |
2025-10-01 |
aBigDeal |
multi_sched_disc |
2024-10-01 |
2025-10-01 |
|
4 |
Enterprise platform fee |
13 |
4000.00 |
2024-10-01 |
2025-10-01 |
aBigDeal |
multi_sched_disc |
2024-10-01 |
2025-10-01 |
|
7 |
Customer support fee |
14 |
1000.00 |
2024-10-01 |
2025-04-01 |
aBigDeal |
multi_sched_disc |
2024-10-01 |
2025-10-01 |
products.id |
products.name |
prices.contract_price_uid |
prices.price |
prices.prorate |
prices.started_at |
prices.ended_at |
contracts.customer_id |
contracts.durable_id |
contracts.started_at |
contracts.ended_at |
---|---|---|---|---|---|---|---|---|---|---|
1 |
Updates |
0.05 |
2025-10-01 |
2026-10-01 |
aBigDeal |
multi_sched_full |
2025-10-01 |
2026-10-01 |
||
2 |
Creates |
0.04 |
2025-10-01 |
2026-10-01 |
aBigDeal |
multi_sched_full |
2025-10-01 |
2026-10-01 |
||
4 |
Enterprise platform fee |
5000.00 |
2025-10-01 |
2026-10-01 |
aBigDeal |
multi_sched_full |
2025-10-01 |
2026-10-01 |
Since this deal will take place over multiple years there are numerous future invoices that will be created. Each month will have an invoice for the usage based charges. There are also a handful of fixed charges that represent platform and customer support fees. While the plethora of quantity=0
usage based charges may not be helpful, the fixed charges do have values associated with them. For the purposes of visibility or recon understanding which customers have upcoming revenue events can be useful.
products.id |
products.name |
line_items.price |
line_items.quantity |
line_items.amount |
invoices.total |
invoices.invoice_delivery |
invoices.status |
invoices.contract_id |
invoices.started_at |
invoices.ended_at |
---|---|---|---|---|---|---|---|---|---|---|
4 |
Enterprise platform fee |
4000.00 |
1.0 |
4000.0 |
4000.0 |
ADVANCED |
DRAFT |
multi_sched_disc |
2024-10-01 00:00:00 |
2025-10-01 00:00:00 |
7 |
Customer support fee |
1000.00 |
1.0 |
1000.0 |
1000.0 |
ADVANCED |
DRAFT |
multi_sched_disc |
2024-10-01 00:00:00 |
2024-11-01 00:00:00 |
7 |
Customer support fee |
1000.00 |
1.0 |
1000.0 |
1000.0 |
ADVANCED |
DRAFT |
multi_sched_disc |
2024-11-01 00:00:00 |
2024-12-01 00:00:00 |
7 |
Customer support fee |
1000.00 |
1.0 |
1000.0 |
1000.0 |
ADVANCED |
DRAFT |
multi_sched_disc |
2024-12-01 00:00:00 |
2025-01-01 00:00:00 |
7 |
Customer support fee |
1000.00 |
1.0 |
1000.0 |
1000.0 |
ADVANCED |
DRAFT |
multi_sched_disc |
2025-01-01 00:00:00 |
2025-02-01 00:00:00 |
7 |
Customer support fee |
1000.00 |
1.0 |
1000.0 |
1000.0 |
ADVANCED |
DRAFT |
multi_sched_disc |
2025-02-01 00:00:00 |
2025-03-01 00:00:00 |
7 |
Customer support fee |
1000.00 |
1.0 |
1000.0 |
1000.0 |
ADVANCED |
DRAFT |
multi_sched_disc |
2025-03-01 00:00:00 |
2025-04-01 00:00:00 |
4 |
Enterprise platform fee |
5000.00 |
1.0 |
5000.0 |
5000.0 |
ADVANCED |
DRAFT |
multi_sched_full |
2025-10-01 00:00:00 |
2026-10-01 00:00:00 |
products.id |
products.name |
line_items.price |
line_items.quantity |
line_items.amount |
invoices.total |
invoices.invoice_delivery |
invoices.status |
invoices.contract_id |
invoices.started_at |
invoices.ended_at |
---|---|---|---|---|---|---|---|---|---|---|
1 |
Updates |
0.04 |
0.0 |
0.0 |
0.0 |
ARREARS |
DRAFT |
multi_sched_disc |
2024-10-01 00:00:00 |
2024-11-01 00:00:00 |
1 |
Updates |
0.04 |
0.0 |
0.0 |
0.0 |
ARREARS |
DRAFT |
multi_sched_disc |
2024-11-01 00:00:00 |
2024-12-01 00:00:00 |
1 |
Updates |
0.04 |
0.0 |
0.0 |
0.0 |
ARREARS |
DRAFT |
multi_sched_disc |
2024-12-01 00:00:00 |
2025-01-01 00:00:00 |
1 |
Updates |
0.04 |
0.0 |
0.0 |
0.0 |
ARREARS |
DRAFT |
multi_sched_disc |
2025-01-01 00:00:00 |
2025-02-01 00:00:00 |
1 |
Updates |
0.04 |
0.0 |
0.0 |
0.0 |
ARREARS |
DRAFT |
multi_sched_disc |
2025-02-01 00:00:00 |
2025-03-01 00:00:00 |
1 |
Updates |
0.04 |
0.0 |
0.0 |
0.0 |
ARREARS |
DRAFT |
multi_sched_disc |
2025-03-01 00:00:00 |
2025-04-01 00:00:00 |
1 |
Updates |
0.04 |
0.0 |
0.0 |
0.0 |
ARREARS |
DRAFT |
multi_sched_disc |
2025-04-01 00:00:00 |
2025-05-01 00:00:00 |
1 |
Updates |
0.04 |
0.0 |
0.0 |
0.0 |
ARREARS |
DRAFT |
multi_sched_disc |
2025-05-01 00:00:00 |
2025-06-01 00:00:00 |
1 |
Updates |
0.04 |
0.0 |
0.0 |
0.0 |
ARREARS |
DRAFT |
multi_sched_disc |
2025-06-01 00:00:00 |
2025-07-01 00:00:00 |
1 |
Updates |
0.04 |
0.0 |
0.0 |
0.0 |
ARREARS |
DRAFT |
multi_sched_disc |
2025-07-01 00:00:00 |
2025-08-01 00:00:00 |
1 |
Updates |
0.04 |
0.0 |
0.0 |
0.0 |
ARREARS |
DRAFT |
multi_sched_disc |
2025-08-01 00:00:00 |
2025-09-01 00:00:00 |
1 |
Updates |
0.04 |
0.0 |
0.0 |
0.0 |
ARREARS |
DRAFT |
multi_sched_disc |
2025-09-01 00:00:00 |
2025-10-01 00:00:00 |
2 |
Creates |
0.032 |
0.0 |
0.0 |
0.0 |
ARREARS |
DRAFT |
multi_sched_disc |
2024-10-01 00:00:00 |
2024-11-01 00:00:00 |
2 |
Creates |
0.032 |
0.0 |
0.0 |
0.0 |
ARREARS |
DRAFT |
multi_sched_disc |
2024-11-01 00:00:00 |
2024-12-01 00:00:00 |
2 |
Creates |
0.032 |
0.0 |
0.0 |
0.0 |
ARREARS |
DRAFT |
multi_sched_disc |
2024-12-01 00:00:00 |
2025-01-01 00:00:00 |
2 |
Creates |
0.032 |
0.0 |
0.0 |
0.0 |
ARREARS |
DRAFT |
multi_sched_disc |
2025-01-01 00:00:00 |
2025-02-01 00:00:00 |
2 |
Creates |
0.032 |
0.0 |
0.0 |
0.0 |
ARREARS |
DRAFT |
multi_sched_disc |
2025-02-01 00:00:00 |
2025-03-01 00:00:00 |
2 |
Creates |
0.032 |
0.0 |
0.0 |
0.0 |
ARREARS |
DRAFT |
multi_sched_disc |
2025-03-01 00:00:00 |
2025-04-01 00:00:00 |
2 |
Creates |
0.032 |
0.0 |
0.0 |
0.0 |
ARREARS |
DRAFT |
multi_sched_disc |
2025-04-01 00:00:00 |
2025-05-01 00:00:00 |
2 |
Creates |
0.032 |
0.0 |
0.0 |
0.0 |
ARREARS |
DRAFT |
multi_sched_disc |
2025-05-01 00:00:00 |
2025-06-01 00:00:00 |
2 |
Creates |
0.032 |
0.0 |
0.0 |
0.0 |
ARREARS |
DRAFT |
multi_sched_disc |
2025-06-01 00:00:00 |
2025-07-01 00:00:00 |
2 |
Creates |
0.032 |
0.0 |
0.0 |
0.0 |
ARREARS |
DRAFT |
multi_sched_disc |
2025-07-01 00:00:00 |
2025-08-01 00:00:00 |
2 |
Creates |
0.032 |
0.0 |
0.0 |
0.0 |
ARREARS |
DRAFT |
multi_sched_disc |
2025-08-01 00:00:00 |
2025-09-01 00:00:00 |
2 |
Creates |
0.032 |
0.0 |
0.0 |
0.0 |
ARREARS |
DRAFT |
multi_sched_disc |
2025-09-01 00:00:00 |
2025-10-01 00:00:00 |
1 |
Updates |
0.05 |
0.0 |
0.0 |
0.0 |
ARREARS |
DRAFT |
multi_sched_full |
2025-10-01 00:00:00 |
2025-11-01 00:00:00 |
1 |
Updates |
0.05 |
0.0 |
0.0 |
0.0 |
ARREARS |
DRAFT |
multi_sched_full |
2025-11-01 00:00:00 |
2025-12-01 00:00:00 |
1 |
Updates |
0.05 |
0.0 |
0.0 |
0.0 |
ARREARS |
DRAFT |
multi_sched_full |
2025-12-01 00:00:00 |
2026-01-01 00:00:00 |
1 |
Updates |
0.05 |
0.0 |
0.0 |
0.0 |
ARREARS |
DRAFT |
multi_sched_full |
2026-01-01 00:00:00 |
2026-02-01 00:00:00 |
1 |
Updates |
0.05 |
0.0 |
0.0 |
0.0 |
ARREARS |
DRAFT |
multi_sched_full |
2026-02-01 00:00:00 |
2026-03-01 00:00:00 |
1 |
Updates |
0.05 |
0.0 |
0.0 |
0.0 |
ARREARS |
DRAFT |
multi_sched_full |
2026-03-01 00:00:00 |
2026-04-01 00:00:00 |
1 |
Updates |
0.05 |
0.0 |
0.0 |
0.0 |
ARREARS |
DRAFT |
multi_sched_full |
2026-04-01 00:00:00 |
2026-05-01 00:00:00 |
1 |
Updates |
0.05 |
0.0 |
0.0 |
0.0 |
ARREARS |
DRAFT |
multi_sched_full |
2026-05-01 00:00:00 |
2026-06-01 00:00:00 |
1 |
Updates |
0.05 |
0.0 |
0.0 |
0.0 |
ARREARS |
DRAFT |
multi_sched_full |
2026-06-01 00:00:00 |
2026-07-01 00:00:00 |
1 |
Updates |
0.05 |
0.0 |
0.0 |
0.0 |
ARREARS |
DRAFT |
multi_sched_full |
2026-07-01 00:00:00 |
2026-08-01 00:00:00 |
1 |
Updates |
0.05 |
0.0 |
0.0 |
0.0 |
ARREARS |
DRAFT |
multi_sched_full |
2026-08-01 00:00:00 |
2026-09-01 00:00:00 |
1 |
Updates |
0.05 |
0.0 |
0.0 |
0.0 |
ARREARS |
DRAFT |
multi_sched_full |
2026-09-01 00:00:00 |
2026-10-01 00:00:00 |
2 |
Creates |
0.04 |
0.0 |
0.0 |
0.0 |
ARREARS |
DRAFT |
multi_sched_full |
2025-10-01 00:00:00 |
2025-11-01 00:00:00 |
2 |
Creates |
0.04 |
0.0 |
0.0 |
0.0 |
ARREARS |
DRAFT |
multi_sched_full |
2025-11-01 00:00:00 |
2025-12-01 00:00:00 |
2 |
Creates |
0.04 |
0.0 |
0.0 |
0.0 |
ARREARS |
DRAFT |
multi_sched_full |
2025-12-01 00:00:00 |
2026-01-01 00:00:00 |
2 |
Creates |
0.04 |
0.0 |
0.0 |
0.0 |
ARREARS |
DRAFT |
multi_sched_full |
2026-01-01 00:00:00 |
2026-02-01 00:00:00 |
2 |
Creates |
0.04 |
0.0 |
0.0 |
0.0 |
ARREARS |
DRAFT |
multi_sched_full |
2026-02-01 00:00:00 |
2026-03-01 00:00:00 |
2 |
Creates |
0.04 |
0.0 |
0.0 |
0.0 |
ARREARS |
DRAFT |
multi_sched_full |
2026-03-01 00:00:00 |
2026-04-01 00:00:00 |
2 |
Creates |
0.04 |
0.0 |
0.0 |
0.0 |
ARREARS |
DRAFT |
multi_sched_full |
2026-04-01 00:00:00 |
2026-05-01 00:00:00 |
2 |
Creates |
0.04 |
0.0 |
0.0 |
0.0 |
ARREARS |
DRAFT |
multi_sched_full |
2026-05-01 00:00:00 |
2026-06-01 00:00:00 |
2 |
Creates |
0.04 |
0.0 |
0.0 |
0.0 |
ARREARS |
DRAFT |
multi_sched_full |
2026-06-01 00:00:00 |
2026-07-01 00:00:00 |
2 |
Creates |
0.04 |
0.0 |
0.0 |
0.0 |
ARREARS |
DRAFT |
multi_sched_full |
2026-07-01 00:00:00 |
2026-08-01 00:00:00 |
2 |
Creates |
0.04 |
0.0 |
0.0 |
0.0 |
ARREARS |
DRAFT |
multi_sched_full |
2026-08-01 00:00:00 |
2026-09-01 00:00:00 |
2 |
Creates |
0.04 |
0.0 |
0.0 |
0.0 |
ARREARS |
DRAFT |
multi_sched_full |
2026-09-01 00:00:00 |
2026-10-01 00:00:00 |
1 |
Updates |
0.00 |
0.0 |
0.0 |
0.0 |
ARREARS |
DRAFT |
multi_sched_trial |
2024-06-01 00:00:00 |
2024-07-01 00:00:00 |
1 |
Updates |
0.00 |
0.0 |
0.0 |
0.0 |
ARREARS |
DRAFT |
multi_sched_trial |
2024-07-01 00:00:00 |
2024-08-01 00:00:00 |
1 |
Updates |
0.00 |
0.0 |
0.0 |
0.0 |
ARREARS |
DRAFT |
multi_sched_trial |
2024-08-01 00:00:00 |
2024-09-01 00:00:00 |
1 |
Updates |
0.00 |
0.0 |
0.0 |
0.0 |
ARREARS |
DRAFT |
multi_sched_trial |
2024-09-01 00:00:00 |
2024-10-01 00:00:00 |
2 |
Creates |
0.00 |
0.0 |
0.0 |
0.0 |
ARREARS |
DRAFT |
multi_sched_trial |
2024-06-01 00:00:00 |
2024-07-01 00:00:00 |
2 |
Creates |
0.00 |
0.0 |
0.0 |
0.0 |
ARREARS |
DRAFT |
multi_sched_trial |
2024-07-01 00:00:00 |
2024-08-01 00:00:00 |
2 |
Creates |
0.00 |
0.0 |
0.0 |
0.0 |
ARREARS |
DRAFT |
multi_sched_trial |
2024-08-01 00:00:00 |
2024-09-01 00:00:00 |
2 |
Creates |
0.00 |
0.0 |
0.0 |
0.0 |
ARREARS |
DRAFT |
multi_sched_trial |
2024-09-01 00:00:00 |
2024-10-01 00:00:00 |