diff --git a/app/controllers/api/v1/invoices_controller.rb b/app/controllers/api/v1/invoices_controller.rb index 825224f3b1b..d21526ed87a 100644 --- a/app/controllers/api/v1/invoices_controller.rb +++ b/app/controllers/api/v1/invoices_controller.rb @@ -245,7 +245,7 @@ def render_invoice(invoice) json: ::V1::InvoiceSerializer.new( invoice, root_name: 'invoice', - includes: %i[customer integration_customers subscriptions fees credits metadata applied_taxes error_details applied_invoice_custom_sections] + includes: %i[customer integration_customers billing_periods subscriptions fees credits metadata applied_taxes error_details applied_invoice_custom_sections] ) ) end diff --git a/app/serializers/v1/invoice_serializer.rb b/app/serializers/v1/invoice_serializer.rb index ef1169162e3..fbb1aff7d14 100644 --- a/app/serializers/v1/invoice_serializer.rb +++ b/app/serializers/v1/invoice_serializer.rb @@ -33,6 +33,7 @@ def serialize payload.merge!(customer) if include?(:customer) payload.merge!(subscriptions) if include?(:subscriptions) + payload.merge!(billing_periods) if include?(:billing_periods) payload.merge!(fees) if include?(:fees) payload.merge!(credits) if include?(:credits) payload.merge!(metadata) if include?(:metadata) @@ -121,5 +122,13 @@ def applied_invoice_custom_sections collection_name: 'applied_invoice_custom_sections' ).serialize end + + def billing_periods + ::CollectionSerializer.new( + model.invoice_subscriptions, + ::V1::Invoices::BillingPeriodSerializer, + collection_name: 'billing_periods' + ).serialize + end end end diff --git a/app/serializers/v1/invoices/billing_period_serializer.rb b/app/serializers/v1/invoices/billing_period_serializer.rb new file mode 100644 index 00000000000..cc2252fe21d --- /dev/null +++ b/app/serializers/v1/invoices/billing_period_serializer.rb @@ -0,0 +1,20 @@ +# frozen_string_literal: true + +module V1 + module Invoices + class BillingPeriodSerializer < ModelSerializer + def serialize + { + lago_subscription_id: model.subscription_id, + external_subscription_id: model.subscription&.external_id, + lago_plan_id: model.subscription&.plan_id, + subscription_from_datetime: model.from_datetime.iso8601, + subscription_to_datetime: model.to_datetime.iso8601, + charges_from_datetime: model.charges_from_datetime.iso8601, + charges_to_datetime: model.charges_to_datetime.iso8601, + invoicing_reason: model.invoicing_reason + } + end + end + end +end diff --git a/app/services/webhooks/invoices/created_service.rb b/app/services/webhooks/invoices/created_service.rb index 48e395326a6..0135a95dfaf 100644 --- a/app/services/webhooks/invoices/created_service.rb +++ b/app/services/webhooks/invoices/created_service.rb @@ -13,7 +13,7 @@ def object_serializer ::V1::InvoiceSerializer.new( object, root_name: 'invoice', - includes: %i[customer subscriptions fees credits applied_taxes applied_invoice_custom_sections] + includes: %i[customer subscriptions billing_periods fees credits applied_taxes applied_invoice_custom_sections] ) end diff --git a/app/services/webhooks/invoices/drafted_service.rb b/app/services/webhooks/invoices/drafted_service.rb index 54f2a0f4dcc..44a882f9521 100644 --- a/app/services/webhooks/invoices/drafted_service.rb +++ b/app/services/webhooks/invoices/drafted_service.rb @@ -11,7 +11,7 @@ def object_serializer ::V1::InvoiceSerializer.new( object, root_name: 'invoice', - includes: %i[customer subscriptions fees credits applied_taxes error_details] + includes: %i[customer subscriptions billing_periods fees credits applied_taxes error_details] ) end diff --git a/app/services/webhooks/invoices/resynced_service.rb b/app/services/webhooks/invoices/resynced_service.rb index ff928d85ff5..c6a4900c1ac 100644 --- a/app/services/webhooks/invoices/resynced_service.rb +++ b/app/services/webhooks/invoices/resynced_service.rb @@ -13,7 +13,7 @@ def object_serializer ::V1::InvoiceSerializer.new( object, root_name: 'invoice', - includes: %i[customer integration_customers subscriptions fees credits applied_taxes] + includes: %i[customer billing_periods integration_customers subscriptions fees credits applied_taxes] ) end diff --git a/app/services/webhooks/invoices/voided_service.rb b/app/services/webhooks/invoices/voided_service.rb index 90ae068821d..06e84922137 100644 --- a/app/services/webhooks/invoices/voided_service.rb +++ b/app/services/webhooks/invoices/voided_service.rb @@ -11,7 +11,7 @@ def object_serializer ::V1::InvoiceSerializer.new( object, root_name: 'invoice', - includes: %i[customer subscriptions fees credits applied_taxes] + includes: %i[customer billing_periods subscriptions fees credits applied_taxes] ) end diff --git a/spec/factories/invoice_subscriptions.rb b/spec/factories/invoice_subscriptions.rb index 3c6e2b8dac1..0032166191e 100644 --- a/spec/factories/invoice_subscriptions.rb +++ b/spec/factories/invoice_subscriptions.rb @@ -6,5 +6,14 @@ invoice recurring { false } + + trait :boundaries do + timestamp { Time.current } + + from_datetime { timestamp.beginning_of_month } + to_datetime { timestamp.end_of_month } + charges_from_datetime { from_datetime - 1.month } + charges_to_datetime { to_datetime.end_of_month } + end end end diff --git a/spec/serializers/v1/invoice_serializer_spec.rb b/spec/serializers/v1/invoice_serializer_spec.rb index 708660bb731..07d5c00f954 100644 --- a/spec/serializers/v1/invoice_serializer_spec.rb +++ b/spec/serializers/v1/invoice_serializer_spec.rb @@ -3,7 +3,9 @@ require "rails_helper" RSpec.describe ::V1::InvoiceSerializer do - subject(:serializer) { described_class.new(invoice, root_name: "invoice", includes: %i[metadata error_details]) } + subject(:serializer) { described_class.new(invoice, root_name: "invoice", includes:) } + + let(:includes) { %i[metadata error_details] } let(:invoice) { create(:invoice) } let(:metadata) { create(:invoice_metadata, invoice:) } @@ -75,4 +77,17 @@ expect(result["invoice"]["applied_usage_thresholds"].count).to eq(1) end end + + context 'when including billing periods' do + let(:includes) { %i[billing_periods] } + let(:invoice_subscription) { create(:invoice_subscription, :boundaries, invoice:) } + + before { invoice_subscription } + + it 'serializes the invoice_subscription' do + result = JSON.parse(serializer.to_json) + + expect(result['invoice']['billing_periods']).to be_present + end + end end diff --git a/spec/serializers/v1/invoices/billing_period_serializer_spec.rb b/spec/serializers/v1/invoices/billing_period_serializer_spec.rb new file mode 100644 index 00000000000..8322ee4ed92 --- /dev/null +++ b/spec/serializers/v1/invoices/billing_period_serializer_spec.rb @@ -0,0 +1,24 @@ +# frozen_string_literal: true + +require 'rails_helper' + +RSpec.describe ::V1::Invoices::BillingPeriodSerializer do + subject(:serializer) { described_class.new(invoice_subscription, root_name: 'billing_period') } + + let(:invoice_subscription) { build(:invoice_subscription, :boundaries) } + + it 'serializes the object' do + result = JSON.parse(serializer.to_json) + + aggregate_failures do + expect(result['billing_period']['lago_subscription_id']).to eq(invoice_subscription.subscription_id) + expect(result['billing_period']['external_subscription_id']).to eq(invoice_subscription.subscription.external_id) + expect(result['billing_period']['lago_plan_id']).to eq(invoice_subscription.subscription.plan_id) + expect(result['billing_period']['subscription_from_datetime']).to eq(invoice_subscription.from_datetime.iso8601) + expect(result['billing_period']['subscription_to_datetime']).to eq(invoice_subscription.to_datetime.iso8601) + expect(result['billing_period']['charges_from_datetime']).to eq(invoice_subscription.charges_from_datetime.iso8601) + expect(result['billing_period']['charges_to_datetime']).to eq(invoice_subscription.charges_to_datetime.iso8601) + expect(result['billing_period']['invoicing_reason']).to eq(invoice_subscription.invoicing_reason) + end + end +end