Skip to content

Commit 86f2c73

Browse files
committed
feat(products): link fees to rate_card_rate and add product_item fee type
Fees produced by the new billing path need to reference the catalog rate that generated them and a fee type identifying them as coming from a product item. Add an optional rate_card_rate_id reference to fees (concurrent index, unvalidated foreign key for a safe rollout) and append product_item to Fee::FEE_TYPES. The existing fee types and billing path are untouched.
1 parent ff555e9 commit 86f2c73

7 files changed

Lines changed: 88 additions & 34 deletions

File tree

app/models/fee.rb

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ class Fee < ApplicationRecord
2121
belongs_to :organization
2222
belongs_to :billing_entity
2323
belongs_to :fixed_charge, -> { with_discarded }, optional: true
24+
belongs_to :rate_card_rate, optional: true
2425

2526
has_one :adjusted_fee, dependent: :nullify
2627
has_one :billable_metric, -> { with_discarded }, through: :charge
@@ -45,7 +46,7 @@ class Fee < ApplicationRecord
4546
monetize :unit_amount_cents, disable_validation: true, allow_nil: true, with_model_currency: :currency
4647

4748
# TODO: Deprecate add_on type in the near future
48-
FEE_TYPES = %i[charge add_on subscription credit commitment fixed_charge].freeze
49+
FEE_TYPES = %i[charge add_on subscription credit commitment fixed_charge product_item].freeze
4950
PAYMENT_STATUS = %i[pending succeeded failed refunded].freeze
5051

5152
enum :fee_type, FEE_TYPES
@@ -414,6 +415,7 @@ def to_date
414415
# original_fee_id :uuid
415416
# pay_in_advance_event_id :uuid
416417
# pay_in_advance_event_transaction_id :string
418+
# rate_card_rate_id :uuid
417419
# subscription_id :uuid
418420
# true_up_parent_fee_id :uuid
419421
#
@@ -435,6 +437,7 @@ def to_date
435437
# index_fees_on_organization_id (organization_id)
436438
# index_fees_on_original_fee_id (original_fee_id)
437439
# index_fees_on_pay_in_advance_event_transaction_id (pay_in_advance_event_transaction_id) WHERE (deleted_at IS NULL)
440+
# index_fees_on_rate_card_rate_id (rate_card_rate_id)
438441
# index_fees_on_subscription_id (subscription_id)
439442
# index_fees_on_true_up_parent_fee_id (true_up_parent_fee_id)
440443
#
@@ -449,6 +452,7 @@ def to_date
449452
# fk_rails_... (invoice_id => invoices.id)
450453
# fk_rails_... (organization_id => organizations.id)
451454
# fk_rails_... (original_fee_id => fees.id)
455+
# fk_rails_... (rate_card_rate_id => rate_card_rates.id)
452456
# fk_rails_... (subscription_id => subscriptions.id)
453457
# fk_rails_... (true_up_parent_fee_id => fees.id)
454458
#

app/models/rate_card_rate.rb

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@ class RateCardRate < ApplicationRecord
3333
belongs_to :organization
3434
belongs_to :rate_card
3535

36+
has_many :fees
37+
3638
enum :rate_model, RATE_MODELS, validate: true
3739
enum :billing_interval_unit, BILLING_INTERVAL_UNITS, validate: true
3840

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
# frozen_string_literal: true
2+
3+
class AddRateCardRateToFees < ActiveRecord::Migration[8.0]
4+
disable_ddl_transaction!
5+
6+
def change
7+
add_reference :fees, :rate_card_rate, type: :uuid, null: true, index: {algorithm: :concurrently}
8+
add_foreign_key :fees, :rate_card_rates, column: :rate_card_rate_id, validate: false
9+
end
10+
end

db/structure.sql

Lines changed: 63 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@ ALTER TABLE IF EXISTS ONLY public.quantified_events DROP CONSTRAINT IF EXISTS fk
2626
ALTER TABLE IF EXISTS ONLY public.invoice_subscriptions DROP CONSTRAINT IF EXISTS fk_rails_f435d13904;
2727
ALTER TABLE IF EXISTS ONLY public.fees DROP CONSTRAINT IF EXISTS fk_rails_f375d320ad;
2828
ALTER TABLE IF EXISTS ONLY public.wallet_transactions DROP CONSTRAINT IF EXISTS fk_rails_f32b205d44;
29-
ALTER TABLE IF EXISTS ONLY public.rate_phases DROP CONSTRAINT IF EXISTS fk_rails_f2ab981080;
3029
ALTER TABLE IF EXISTS ONLY public.enriched_store_subscription_migrations DROP CONSTRAINT IF EXISTS fk_rails_f232478e56;
3130
ALTER TABLE IF EXISTS ONLY public.payment_requests DROP CONSTRAINT IF EXISTS fk_rails_f228550fda;
3231
ALTER TABLE IF EXISTS ONLY public.usage_monitoring_alert_thresholds DROP CONSTRAINT IF EXISTS fk_rails_f18cd04d51;
@@ -60,7 +59,6 @@ ALTER TABLE IF EXISTS ONLY public.usage_monitoring_alerts DROP CONSTRAINT IF EXI
6059
ALTER TABLE IF EXISTS ONLY public.product_items DROP CONSTRAINT IF EXISTS fk_rails_d9e7580aa8;
6160
ALTER TABLE IF EXISTS ONLY public.integration_resources DROP CONSTRAINT IF EXISTS fk_rails_d9448a540b;
6261
ALTER TABLE IF EXISTS ONLY public.wallets DROP CONSTRAINT IF EXISTS fk_rails_d9342a8ca7;
63-
ALTER TABLE IF EXISTS ONLY public.rate_phases DROP CONSTRAINT IF EXISTS fk_rails_d844d6b2b1;
6462
ALTER TABLE IF EXISTS ONLY public.subscription_fixed_charge_units_overrides DROP CONSTRAINT IF EXISTS fk_rails_d72a9877be;
6563
ALTER TABLE IF EXISTS ONLY public.entitlement_privileges DROP CONSTRAINT IF EXISTS fk_rails_d648e28d9f;
6664
ALTER TABLE IF EXISTS ONLY public.rate_card_rates DROP CONSTRAINT IF EXISTS fk_rails_d53feb5721;
@@ -117,7 +115,6 @@ ALTER TABLE IF EXISTS ONLY public.integration_items DROP CONSTRAINT IF EXISTS fk
117115
ALTER TABLE IF EXISTS ONLY public.subscription_product_items DROP CONSTRAINT IF EXISTS fk_rails_a8771420b2;
118116
ALTER TABLE IF EXISTS ONLY public.recurring_transaction_rules_invoice_custom_sections DROP CONSTRAINT IF EXISTS fk_rails_a7f20c73bb;
119117
ALTER TABLE IF EXISTS ONLY public.charges DROP CONSTRAINT IF EXISTS fk_rails_a710519346;
120-
ALTER TABLE IF EXISTS ONLY public.rate_phases DROP CONSTRAINT IF EXISTS fk_rails_a61520ac30;
121118
ALTER TABLE IF EXISTS ONLY public.product_item_filter_values DROP CONSTRAINT IF EXISTS fk_rails_a32a8f7fc6;
122119
ALTER TABLE IF EXISTS ONLY public.group_properties DROP CONSTRAINT IF EXISTS fk_rails_a2d2cb3819;
123120
ALTER TABLE IF EXISTS ONLY public.quotes DROP CONSTRAINT IF EXISTS fk_rails_a1ab65f1f7;
@@ -144,6 +141,7 @@ ALTER TABLE IF EXISTS ONLY public.fixed_charge_events DROP CONSTRAINT IF EXISTS
144141
ALTER TABLE IF EXISTS ONLY public.commitments_taxes DROP CONSTRAINT IF EXISTS fk_rails_8fa6f0d920;
145142
ALTER TABLE IF EXISTS ONLY public.applied_pricing_units DROP CONSTRAINT IF EXISTS fk_rails_8e0c3d0c5b;
146143
ALTER TABLE IF EXISTS ONLY public.usage_thresholds DROP CONSTRAINT IF EXISTS fk_rails_8df9bf2b6c;
144+
ALTER TABLE IF EXISTS ONLY public.rate_phases DROP CONSTRAINT IF EXISTS fk_rails_8d4c29e03f;
147145
ALTER TABLE IF EXISTS ONLY public.product_items DROP CONSTRAINT IF EXISTS fk_rails_8c9cbcf514;
148146
ALTER TABLE IF EXISTS ONLY public.usage_monitoring_alerts DROP CONSTRAINT IF EXISTS fk_rails_8c18828b53;
149147
ALTER TABLE IF EXISTS ONLY public.fixed_charges_taxes DROP CONSTRAINT IF EXISTS fk_rails_8c09ee2428;
@@ -234,6 +232,7 @@ ALTER TABLE IF EXISTS ONLY public.payment_provider_customers DROP CONSTRAINT IF
234232
ALTER TABLE IF EXISTS ONLY public.wallets DROP CONSTRAINT IF EXISTS fk_rails_4ff087c52e;
235233
ALTER TABLE IF EXISTS ONLY public.rate_cards DROP CONSTRAINT IF EXISTS fk_rails_4f7ffc3e03;
236234
ALTER TABLE IF EXISTS ONLY public.order_forms DROP CONSTRAINT IF EXISTS fk_rails_4ed54bfec0;
235+
ALTER TABLE IF EXISTS ONLY public.fees DROP CONSTRAINT IF EXISTS fk_rails_4cadfc14f3;
237236
ALTER TABLE IF EXISTS ONLY public.product_item_filter_values DROP CONSTRAINT IF EXISTS fk_rails_4b395cde98;
238237
ALTER TABLE IF EXISTS ONLY public.billing_entities DROP CONSTRAINT IF EXISTS fk_rails_4aa58496c3;
239238
ALTER TABLE IF EXISTS ONLY public.recurring_transaction_rules_invoice_custom_sections DROP CONSTRAINT IF EXISTS fk_rails_49fcc221b0;
@@ -268,6 +267,7 @@ ALTER TABLE IF EXISTS ONLY public.fees DROP CONSTRAINT IF EXISTS fk_rails_34ab15
268267
ALTER TABLE IF EXISTS ONLY public.lifetime_usages DROP CONSTRAINT IF EXISTS fk_rails_348acbd245;
269268
ALTER TABLE IF EXISTS ONLY public.customers_taxes DROP CONSTRAINT IF EXISTS fk_rails_33d169382f;
270269
ALTER TABLE IF EXISTS ONLY public.payment_requests DROP CONSTRAINT IF EXISTS fk_rails_32600e5a72;
270+
ALTER TABLE IF EXISTS ONLY public.rate_phases DROP CONSTRAINT IF EXISTS fk_rails_32197619c6;
271271
ALTER TABLE IF EXISTS ONLY public.credits DROP CONSTRAINT IF EXISTS fk_rails_310fcb3585;
272272
ALTER TABLE IF EXISTS ONLY public.invoices DROP CONSTRAINT IF EXISTS fk_rails_309d3a4412;
273273
ALTER TABLE IF EXISTS ONLY public.wallets_invoice_custom_sections DROP CONSTRAINT IF EXISTS fk_rails_3092f5f2e0;
@@ -303,6 +303,7 @@ ALTER TABLE IF EXISTS ONLY public.webhooks DROP CONSTRAINT IF EXISTS fk_rails_20
303303
ALTER TABLE IF EXISTS ONLY public.plan_products DROP CONSTRAINT IF EXISTS fk_rails_1df4cf80e4;
304304
ALTER TABLE IF EXISTS ONLY public.credits DROP CONSTRAINT IF EXISTS fk_rails_1db0057d9b;
305305
ALTER TABLE IF EXISTS ONLY public.applied_usage_thresholds DROP CONSTRAINT IF EXISTS fk_rails_1d112bf8a0;
306+
ALTER TABLE IF EXISTS ONLY public.rate_phases DROP CONSTRAINT IF EXISTS fk_rails_1c069c1c44;
306307
ALTER TABLE IF EXISTS ONLY public.plan_products DROP CONSTRAINT IF EXISTS fk_rails_19f4567acb;
307308
ALTER TABLE IF EXISTS ONLY public.billing_entities_invoice_custom_sections DROP CONSTRAINT IF EXISTS fk_rails_19c47827ba;
308309
ALTER TABLE IF EXISTS ONLY public.customer_metadata DROP CONSTRAINT IF EXISTS fk_rails_195153290d;
@@ -703,6 +704,7 @@ DROP INDEX IF EXISTS public.index_fees_taxes_on_fee_id_and_tax_id;
703704
DROP INDEX IF EXISTS public.index_fees_taxes_on_fee_id;
704705
DROP INDEX IF EXISTS public.index_fees_on_true_up_parent_fee_id;
705706
DROP INDEX IF EXISTS public.index_fees_on_subscription_id;
707+
DROP INDEX IF EXISTS public.index_fees_on_rate_card_rate_id;
706708
DROP INDEX IF EXISTS public.index_fees_on_pay_in_advance_event_transaction_id;
707709
DROP INDEX IF EXISTS public.index_fees_on_original_fee_id;
708710
DROP INDEX IF EXISTS public.index_fees_on_organization_id;
@@ -3490,7 +3492,8 @@ CREATE TABLE public.fees (
34903492
precise_credit_notes_amount_cents numeric(30,5) DEFAULT 0.0 NOT NULL,
34913493
fixed_charge_id uuid,
34923494
duplicated_in_advance boolean DEFAULT false,
3493-
original_fee_id uuid
3495+
original_fee_id uuid,
3496+
rate_card_rate_id uuid
34943497
);
34953498

34963499

@@ -8738,6 +8741,13 @@ CREATE INDEX index_fees_on_original_fee_id ON public.fees USING btree (original_
87388741
CREATE INDEX index_fees_on_pay_in_advance_event_transaction_id ON public.fees USING btree (pay_in_advance_event_transaction_id) WHERE (deleted_at IS NULL);
87398742

87408743

8744+
--
8745+
-- Name: index_fees_on_rate_card_rate_id; Type: INDEX; Schema: public; Owner: -
8746+
--
8747+
8748+
CREATE INDEX index_fees_on_rate_card_rate_id ON public.fees USING btree (rate_card_rate_id);
8749+
8750+
87418751
--
87428752
-- Name: index_fees_on_subscription_id; Type: INDEX; Schema: public; Owner: -
87438753
--
@@ -11484,6 +11494,14 @@ ALTER TABLE ONLY public.plan_products
1148411494
ADD CONSTRAINT fk_rails_19f4567acb FOREIGN KEY (plan_id) REFERENCES public.plans(id);
1148511495

1148611496

11497+
--
11498+
-- Name: rate_phases fk_rails_1c069c1c44; Type: FK CONSTRAINT; Schema: public; Owner: -
11499+
--
11500+
11501+
ALTER TABLE ONLY public.rate_phases
11502+
ADD CONSTRAINT fk_rails_1c069c1c44 FOREIGN KEY (organization_id) REFERENCES public.organizations(id);
11503+
11504+
1148711505
--
1148811506
-- Name: applied_usage_thresholds fk_rails_1d112bf8a0; Type: FK CONSTRAINT; Schema: public; Owner: -
1148911507
--
@@ -11764,6 +11782,14 @@ ALTER TABLE ONLY public.credits
1176411782
ADD CONSTRAINT fk_rails_310fcb3585 FOREIGN KEY (credit_note_id) REFERENCES public.credit_notes(id);
1176511783

1176611784

11785+
--
11786+
-- Name: rate_phases fk_rails_32197619c6; Type: FK CONSTRAINT; Schema: public; Owner: -
11787+
--
11788+
11789+
ALTER TABLE ONLY public.rate_phases
11790+
ADD CONSTRAINT fk_rails_32197619c6 FOREIGN KEY (subscription_product_item_id) REFERENCES public.subscription_product_items(id);
11791+
11792+
1176711793
--
1176811794
-- Name: payment_requests fk_rails_32600e5a72; Type: FK CONSTRAINT; Schema: public; Owner: -
1176911795
--
@@ -12028,6 +12054,22 @@ ALTER TABLE ONLY public.billing_entities
1202812054
ADD CONSTRAINT fk_rails_4aa58496c3 FOREIGN KEY (applied_dunning_campaign_id) REFERENCES public.dunning_campaigns(id) ON DELETE SET NULL;
1202912055

1203012056

12057+
--
12058+
-- Name: product_item_filter_values fk_rails_4b395cde98; Type: FK CONSTRAINT; Schema: public; Owner: -
12059+
--
12060+
12061+
ALTER TABLE ONLY public.product_item_filter_values
12062+
ADD CONSTRAINT fk_rails_4b395cde98 FOREIGN KEY (billable_metric_filter_id) REFERENCES public.billable_metric_filters(id);
12063+
12064+
12065+
--
12066+
-- Name: fees fk_rails_4cadfc14f3; Type: FK CONSTRAINT; Schema: public; Owner: -
12067+
--
12068+
12069+
ALTER TABLE ONLY public.fees
12070+
ADD CONSTRAINT fk_rails_4cadfc14f3 FOREIGN KEY (rate_card_rate_id) REFERENCES public.rate_card_rates(id) NOT VALID;
12071+
12072+
1203112073
--
1203212074
-- Name: order_forms fk_rails_4ed54bfec0; Type: FK CONSTRAINT; Schema: public; Owner: -
1203312075
--
@@ -12748,6 +12790,14 @@ ALTER TABLE ONLY public.product_items
1274812790
ADD CONSTRAINT fk_rails_8c9cbcf514 FOREIGN KEY (charge_id) REFERENCES public.charges(id);
1274912791

1275012792

12793+
--
12794+
-- Name: rate_phases fk_rails_8d4c29e03f; Type: FK CONSTRAINT; Schema: public; Owner: -
12795+
--
12796+
12797+
ALTER TABLE ONLY public.rate_phases
12798+
ADD CONSTRAINT fk_rails_8d4c29e03f FOREIGN KEY (plan_product_item_id) REFERENCES public.plan_product_items(id);
12799+
12800+
1275112801
--
1275212802
-- Name: usage_thresholds fk_rails_8df9bf2b6c; Type: FK CONSTRAINT; Schema: public; Owner: -
1275312803
--
@@ -12956,14 +13006,6 @@ ALTER TABLE ONLY public.product_item_filter_values
1295613006
ADD CONSTRAINT fk_rails_a32a8f7fc6 FOREIGN KEY (organization_id) REFERENCES public.organizations(id);
1295713007

1295813008

12959-
--
12960-
-- Name: rate_phases fk_rails_a61520ac30; Type: FK CONSTRAINT; Schema: public; Owner: -
12961-
--
12962-
12963-
ALTER TABLE ONLY public.rate_phases
12964-
ADD CONSTRAINT fk_rails_a61520ac30 FOREIGN KEY (plan_product_item_id) REFERENCES public.plan_product_items(id);
12965-
12966-
1296713009
--
1296813010
-- Name: charges fk_rails_a710519346; Type: FK CONSTRAINT; Schema: public; Owner: -
1296913011
--
@@ -13157,18 +13199,21 @@ ALTER TABLE ONLY public.plans_taxes
1315713199

1315813200

1315913201
--
13160-
-- Name: wallet_transactions fk_rails_bcb5aecd6c; Type: FK CONSTRAINT; Schema: public; Owner: -
13161-
--
13162-
13163-
ALTER TABLE ONLY public.wallet_transactions
13164-
ADD CONSTRAINT fk_rails_bcb5aecd6c FOREIGN KEY (billing_entity_id) REFERENCES public.billing_entities(id) NOT VALID;
1316513202
-- Name: product_item_filter_values fk_rails_bbe7738882; Type: FK CONSTRAINT; Schema: public; Owner: -
1316613203
--
1316713204

1316813205
ALTER TABLE ONLY public.product_item_filter_values
1316913206
ADD CONSTRAINT fk_rails_bbe7738882 FOREIGN KEY (product_item_filter_id) REFERENCES public.product_item_filters(id);
1317013207

1317113208

13209+
--
13210+
-- Name: wallet_transactions fk_rails_bcb5aecd6c; Type: FK CONSTRAINT; Schema: public; Owner: -
13211+
--
13212+
13213+
ALTER TABLE ONLY public.wallet_transactions
13214+
ADD CONSTRAINT fk_rails_bcb5aecd6c FOREIGN KEY (billing_entity_id) REFERENCES public.billing_entities(id) NOT VALID;
13215+
13216+
1317213217
--
1317313218
-- Name: usage_monitoring_subscription_activities fk_rails_bda048a8d9; Type: FK CONSTRAINT; Schema: public; Owner: -
1317413219
--
@@ -13409,14 +13454,6 @@ ALTER TABLE ONLY public.subscription_fixed_charge_units_overrides
1340913454
ADD CONSTRAINT fk_rails_d72a9877be FOREIGN KEY (subscription_id) REFERENCES public.subscriptions(id);
1341013455

1341113456

13412-
--
13413-
-- Name: rate_phases fk_rails_d844d6b2b1; Type: FK CONSTRAINT; Schema: public; Owner: -
13414-
--
13415-
13416-
ALTER TABLE ONLY public.rate_phases
13417-
ADD CONSTRAINT fk_rails_d844d6b2b1 FOREIGN KEY (organization_id) REFERENCES public.organizations(id);
13418-
13419-
1342013457
--
1342113458
-- Name: wallets fk_rails_d9342a8ca7; Type: FK CONSTRAINT; Schema: public; Owner: -
1342213459
--
@@ -13681,14 +13718,6 @@ ALTER TABLE ONLY public.enriched_store_subscription_migrations
1368113718
ADD CONSTRAINT fk_rails_f232478e56 FOREIGN KEY (organization_id) REFERENCES public.organizations(id);
1368213719

1368313720

13684-
--
13685-
-- Name: rate_phases fk_rails_f2ab981080; Type: FK CONSTRAINT; Schema: public; Owner: -
13686-
--
13687-
13688-
ALTER TABLE ONLY public.rate_phases
13689-
ADD CONSTRAINT fk_rails_f2ab981080 FOREIGN KEY (subscription_product_item_id) REFERENCES public.subscription_product_items(id);
13690-
13691-
1369213721
--
1369313722
-- Name: wallet_transactions fk_rails_f32b205d44; Type: FK CONSTRAINT; Schema: public; Owner: -
1369413723
--
@@ -13849,6 +13878,7 @@ INSERT INTO "schema_migrations" (version) VALUES
1384913878
('20260608111837'),
1385013879
('20260608074112'),
1385113880
('20260605170919'),
13881+
('20260604182138'),
1385213882
('20260604181958'),
1385313883
('20260604181826'),
1385413884
('20260604181654'),

schema.graphql

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

schema.json

Lines changed: 6 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

spec/models/fee_spec.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
it { is_expected.to belong_to(:add_on).optional }
99
it { is_expected.to belong_to(:charge).optional }
1010
it { is_expected.to belong_to(:fixed_charge).optional }
11+
it { is_expected.to belong_to(:rate_card_rate).optional }
1112
it { is_expected.to have_many(:presentation_breakdowns) }
1213
it { is_expected.to have_one(:fixed_charge_add_on).through(:fixed_charge) }
1314
it { is_expected.to have_one(:adjusted_fee).dependent(:nullify) }

0 commit comments

Comments
 (0)