Edits¶
What are edits?¶
An edit within bframe refers to an overwrite on a source model (e.g. customers, products, etc). This is most commonly used to update fields. Since bframe is append-only edits are not made directly on the row, but are accomplished through versioning. When a new version is created bframe automatically references the latest copy.
bframe does not respect references to prior versions since edits are considered a global change. To preserve historical references please see the amendments feature.
Why are edits important?¶
Dealing with change is one of the more challenging pieces of business modeling. Edits are a key feature to enable an efficient and safe resolution path when change is necessary. It’s simple to delete or directly update a row, but this can leave a system open to compounding mistakes or with a dead end audit trail. The edit feature is a method to make changes with an exit strategy. This is possible since prior versions are persisted in the source. For example, rolling back versions or recovering the history of a model is straightforward with the edit feature.
How do edits work in bframe?¶
Edits are simple to make and can be performed on any source model with a version
field. To make an edit, a larger version with the same id
field is inserted into the table. The bframe library manages the process to ensure that the latest version is always returned. If prior versions are desired they can be accessed through querying the source directly. Let’s cover a simple example to demonstrate how all of this works.
Making an edit¶
Using the Wikipedia case study as base, we can make an edit and see the impact. In this case let’s update the quantity of the platform fee product from 1
to 2
.
Below is the current state of the list price.
products.id |
products.name |
list_prices.id |
list_prices.version |
list_prices.price |
list_prices.fixed_quantity |
---|---|---|---|---|---|
3 |
Platform fee |
3 |
0 |
1000.00 |
SELECT
p.id AS 'products.id',
p.name AS 'products.name',
lp.id AS 'list_prices.id',
lp.version AS 'list_prices.version',
lp.price AS 'list_prices.price',
lp.fixed_quantity AS 'list_prices.fixed_quantity'
FROM bframe.list_prices AS lp
JOIN bframe.products AS p
ON p.id = lp.product_uid
WHERE lp.id = 3;
Two changes need to be made to the existing model. The fixed_quantity
needs to be set to 2
and the version needs to be set to 1
.
INSERT INTO src.list_prices (org_id, env_id, branch_id, id, product_uid, pricebook_uid, price, invoice_delivery, invoice_schedule, fixed_quantity, version) values (2, 2, 1, 3, 3, 1, '1000.00', 'ADVANCED', 12, 2, 1);
Count |
---|
1 |
Once inserted the edit is live. This can be confirmed by querying the list price directly.
products.id |
products.name |
list_prices.id |
list_prices.version |
list_prices.price |
list_prices.fixed_quantity |
---|---|---|---|---|---|
3 |
Platform fee |
3 |
1 |
1000.00 |
2.0 |
SELECT
p.id AS 'products.id',
p.name AS 'products.name',
lp.id AS 'list_prices.id',
lp.version AS 'list_prices.version',
lp.price AS 'list_prices.price',
lp.fixed_quantity AS 'list_prices.fixed_quantity'
FROM bframe.list_prices AS lp
JOIN bframe.products AS p
ON p.id = lp.product_uid
WHERE lp.id = 3;
Exploring the change¶
All contracts associated with this list price now will generate line items with this change in place. Looking at a line item we can see that each platform fee product indeed has a quantity of 2
.
products.id |
products.name |
line_items.quantity |
line_items.amount |
line_items.invoice_delivery |
line_items.status |
line_items.contract_id |
line_items.started_at |
line_items.ended_at |
---|---|---|---|---|---|---|---|---|
3 |
Platform fee |
2.0 |
2000.0 |
ADVANCED |
FINALIZED |
Papergirl_contract |
2023-11-06 07:23:49 |
2024-11-01 |
SELECT
prod.id as 'products.id',
prod.name as 'products.name',
li.quantity as 'line_items.quantity',
li.amount as 'line_items.amount',
li.invoice_delivery as 'line_items.invoice_delivery',
li.status as 'line_items.status',
li.contract_id as 'line_items.contract_id',
li.started_at as 'line_items.started_at',
li.ended_at as 'line_items.ended_at'
FROM bframe.line_items AS li
JOIN bframe.products as prod
ON li.product_uid = prod.id
WHERE
li.product_uid = 3
AND li.contract_id = 'Papergirl_contract'
ORDER BY li.started_at;
Since this is an edit all past, present and future transformations will be affected by this change. For example, the line item that was shown has a finalized status. In this scenario the goal is not stated, so we can’t be sure if such a change is good or bad.
Most business systems persist finalized invoices and line items on a regular cadence. This could cause a divergence between invoices and line items generated by bframe and what’s already stored in the destination. To keep both systems aligned it would be best to update the destination to match bframe’s output. Alternatively, it may be intentional that bframe is only correct on a go-forward basis and the destination is considered the definitive source of truth.