Files
ubicloud/migrate/20230725_add_billing_rate.rb
Burak Yucesoy 3943af0e73 Introduce billing rates
Rest of the usage record logic depends on product naming and requires some
modification on the DB side, which will be integrated with separate commit.

This commit introduces billing rates, which will be used as catalog for all
pricing calculations and invoices. Each place that needs to calculate a price
will be able to fetch unit price of particular resource from this table, and
then calculate the total price as unit_price * usage_amount * usage_duration.

For example, for VMs, if the a customer uses 4 cores from c5a family for 1000
minutes in hetzner-fsn1 region, total price would be 0.000171296 * 4 * 1000.
Unit of unit_price for VMs is minute, but each product can determine its own
unit. For disks, it could be GB or for a serverless product it could be number
of requests. It is possible to add human readable unit column so eliminate
potential confusion, but I'm leaving that out for now. We can add if we see
a need for that.

Initially, I started to build more general solution that would satisfy the
needs of many future products, but that proved itself quite challenging as
there are lots of unknown unknowns. Instead, I decided to build much more
simple and flexible model that can be extended as we learn more about the
product we are building.

Current model is quite flexible and allows numerous potential expansion paths.
For example, reserved instance pricing can be implemented easily by adding a
column.

Similarly price updates can be done quite easily by adding two new columns;
effective_since and effective_until. Then it is matter of ensuring invoice
generation and price calculator honours those dates. Alternative would be
generating new billing rates and depreciating the old ones, but updating
billing rate references everywhere requires manual database surgery and is
open to operator mistakes.
2023-07-31 07:13:00 +03:00

25 lines
1.1 KiB
Ruby

# frozen_string_literal: true
Sequel.migration do
up do
create_table(:billing_rate) do
column :id, :uuid, primary_key: true, default: nil
column :resource_type, :text, collate: '"C"', null: false
column :resource_family, :text, collate: '"C"', null: false
column :location, :text, collate: '"C"', null: false
column :unit_price, :numeric, null: false
index [:resource_type, :resource_family, :location], unique: true
end
# These are valid UBIDs for TYPE_BILLING_RATE
run "INSERT INTO billing_rate VALUES('0b87e0b8-85de-8978-9a60-ba72cb21eedc', 'VmCores', 'c5a', 'hetzner-fsn1', 0.000171296)"
run "INSERT INTO billing_rate VALUES('d44d4d44-3c8c-8578-9bf6-4d668a1cba8f', 'VmCores', 'c5a', 'hetzner-hel1', 0.000154167)"
run "INSERT INTO billing_rate VALUES('139d9a67-8182-8578-a303-235cabd5161c', 'VmCores', 'm5a', 'hetzner-fsn1', 0.000171296)"
run "INSERT INTO billing_rate VALUES('08c502f7-df5d-8978-9896-feafa0ec5c40', 'VmCores', 'm5a', 'hetzner-hel1', 0.000154167)"
end
down do
drop_table :billing_rate
end
end