From c5a759c044a51988d9f5d32209b6048cfee4f333 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Romain=20Semp=C3=A9?= Date: Wed, 24 Aug 2022 12:07:40 +0200 Subject: [PATCH 1/9] misc: Rename unique_id to external_id --- .../api/v1/subscriptions_controller.rb | 2 +- app/models/subscription.rb | 10 ++--- app/serializers/v1/event_serializer.rb | 2 +- app/serializers/v1/subscription_serializer.rb | 2 +- app/services/subscriptions/create_service.rb | 16 +++---- ...ique_id_to_external_id_on_subscriptions.rb | 5 +++ db/schema.rb | 2 +- db/seeds.rb | 2 +- spec/factories/subscription_factory.rb | 2 +- spec/models/subscription_spec.rb | 20 ++++----- spec/requests/api/v1/subscriptions_spec.rb | 2 +- .../subscriptions/create_service_spec.rb | 42 +++++++++---------- 12 files changed, 56 insertions(+), 51 deletions(-) create mode 100644 db/migrate/20220823145421_rename_unique_id_to_external_id_on_subscriptions.rb diff --git a/app/controllers/api/v1/subscriptions_controller.rb b/app/controllers/api/v1/subscriptions_controller.rb index a0610df62ca..300e24d0c7e 100644 --- a/app/controllers/api/v1/subscriptions_controller.rb +++ b/app/controllers/api/v1/subscriptions_controller.rb @@ -86,7 +86,7 @@ def index def create_params params.require(:subscription) - .permit(:customer_id, :plan_code, :name, :subscription_id, :unique_id, :billing_time) + .permit(:customer_id, :plan_code, :name, :subscription_id, :external_id, :billing_time) end def update_params diff --git a/app/models/subscription.rb b/app/models/subscription.rb index b01884cde91..286b4454c9d 100644 --- a/app/models/subscription.rb +++ b/app/models/subscription.rb @@ -12,8 +12,8 @@ class Subscription < ApplicationRecord has_many :invoices, through: :invoice_subscriptions has_many :fees - validates :unique_id, presence: true - validate :validate_unique_id, on: :create + validates :external_id, presence: true + validate :validate_external_id, on: :create STATUSES = [ :pending, @@ -71,10 +71,10 @@ def already_billed? fees.subscription_kind.any? end - def validate_unique_id + def validate_external_id return unless active? - used_ids = customer&.active_subscriptions&.pluck(:unique_id) - errors.add(:unique_id, :value_already_exists) if used_ids&.include?(unique_id) + used_ids = customer&.active_subscriptions&.pluck(:external_id) + errors.add(:external_id, :value_already_exists) if used_ids&.include?(external_id) end end diff --git a/app/serializers/v1/event_serializer.rb b/app/serializers/v1/event_serializer.rb index 10121192c20..a365177643f 100644 --- a/app/serializers/v1/event_serializer.rb +++ b/app/serializers/v1/event_serializer.rb @@ -12,7 +12,7 @@ def serialize timestamp: model.timestamp.iso8601, properties: model.properties, lago_subscription_id: model.subscription_id, - subscription_unique_id: model.subscription&.unique_id, + external_subscription_id: model.subscription&.external_id, created_at: model.created_at.iso8601 } end diff --git a/app/serializers/v1/subscription_serializer.rb b/app/serializers/v1/subscription_serializer.rb index 8edc9b9f34d..289e3e5898b 100644 --- a/app/serializers/v1/subscription_serializer.rb +++ b/app/serializers/v1/subscription_serializer.rb @@ -5,10 +5,10 @@ class SubscriptionSerializer < ModelSerializer def serialize { lago_id: model.id, + external_id: model.external_id, lago_customer_id: model.customer_id, customer_id: model.customer.customer_id, name: model.name, - unique_id: model.unique_id, plan_code: model.plan.code, status: model.status, billing_time: model.billing_time, diff --git a/app/services/subscriptions/create_service.rb b/app/services/subscriptions/create_service.rb index 69fc1d66cdf..308cc1e57d4 100644 --- a/app/services/subscriptions/create_service.rb +++ b/app/services/subscriptions/create_service.rb @@ -2,7 +2,7 @@ module Subscriptions class CreateService < BaseService - attr_reader :current_customer, :current_plan, :current_subscription, :name, :unique_id, :billing_time + attr_reader :current_customer, :current_plan, :current_subscription, :name, :external_id, :billing_time def create_from_api(organization:, params:) if params[:customer_id] @@ -18,7 +18,7 @@ def create_from_api(organization:, params:) code: params[:plan_code]&.strip, ) @name = params[:name]&.strip - @unique_id = params[:unique_id]&.strip + @external_id = params[:external_id]&.strip @billing_time = params[:billing_time] @current_subscription = find_current_subscription(subscription_id: params[:subscription_id]) @@ -40,7 +40,7 @@ def create(**args) # NOTE: prepare subscription attributes @name = args[:name]&.strip - @unique_id = SecureRandom.uuid + @external_id = SecureRandom.uuid @billing_time = args[:billing_time] @current_subscription = find_current_subscription(subscription_id: args[:subscription_id]) @@ -97,7 +97,7 @@ def create_subscription plan_id: current_plan.id, subscription_date: Time.zone.now.to_date, name: name, - unique_id: unique_id || current_customer.customer_id, + external_id: external_id || current_customer.customer_id, billing_time: billing_time || :calendar, ) new_subscription.mark_as_active! @@ -117,7 +117,7 @@ def upgrade_subscription customer: current_customer, plan: current_plan, name: name, - unique_id: current_subscription.unique_id, + external_id: current_subscription.external_id, previous_subscription_id: current_subscription.id, subscription_date: current_subscription.subscription_date, billing_time: current_subscription.billing_time, @@ -159,7 +159,7 @@ def downgrade_subscription customer: current_customer, plan: current_plan, name: name, - unique_id: current_subscription.unique_id, + external_id: current_subscription.external_id, previous_subscription_id: current_subscription.id, subscription_date: current_subscription.subscription_date, status: :pending, @@ -215,9 +215,9 @@ def active_subscriptions def find_current_subscription(subscription_id:) return active_subscriptions&.find_by(id: subscription_id) if subscription_id - return active_subscriptions&.find_by(unique_id: unique_id) if unique_id + return active_subscriptions&.find_by(external_id: external_id) if external_id - active_subscriptions&.find_by(unique_id: current_customer.customer_id) + active_subscriptions&.find_by(external_id: current_customer.customer_id) end end end diff --git a/db/migrate/20220823145421_rename_unique_id_to_external_id_on_subscriptions.rb b/db/migrate/20220823145421_rename_unique_id_to_external_id_on_subscriptions.rb new file mode 100644 index 00000000000..b8117802d9c --- /dev/null +++ b/db/migrate/20220823145421_rename_unique_id_to_external_id_on_subscriptions.rb @@ -0,0 +1,5 @@ +class RenameUniqueIdToExternalIdOnSubscriptions < ActiveRecord::Migration[7.0] + def change + rename_column :subscriptions, :unique_id, :external_id + end +end diff --git a/db/schema.rb b/db/schema.rb index 5c6593012fa..f6f61020c20 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -346,7 +346,7 @@ t.uuid "previous_subscription_id" t.date "subscription_date" t.string "name" - t.string "unique_id", null: false + t.string "external_id", null: false t.integer "billing_time", default: 0, null: false t.index ["customer_id"], name: "index_subscriptions_on_customer_id" t.index ["plan_id"], name: "index_subscriptions_on_plan_id" diff --git a/db/seeds.rb b/db/seeds.rb index 6b4270f53cf..252e5e325a3 100644 --- a/db/seeds.rb +++ b/db/seeds.rb @@ -66,7 +66,7 @@ status: :active, ).find_or_create_by!( customer: customer, - unique_id: SecureRandom.uuid, + external_id: SecureRandom.uuid, plan: plan, ) diff --git a/spec/factories/subscription_factory.rb b/spec/factories/subscription_factory.rb index 4316614ee3a..fcf5937dd86 100644 --- a/spec/factories/subscription_factory.rb +++ b/spec/factories/subscription_factory.rb @@ -5,7 +5,7 @@ customer plan status { :active } - unique_id { SecureRandom.uuid } + external_id { SecureRandom.uuid } factory :active_subscription do status { :active } diff --git a/spec/models/subscription_spec.rb b/spec/models/subscription_spec.rb index 715919ecca8..a05b8e60c67 100644 --- a/spec/models/subscription_spec.rb +++ b/spec/models/subscription_spec.rb @@ -3,7 +3,7 @@ require 'rails_helper' RSpec.describe Subscription, type: :model do - describe '.upgraded?' do + describe '#upgraded?' do let(:previous_subscription) { nil } let(:plan) { create(:plan) } @@ -48,7 +48,7 @@ end end - describe '.downgraded?' do + describe '#downgraded?' do let(:previous_subscription) { nil } let(:plan) { create(:plan, amount_cents: 100) } @@ -93,7 +93,7 @@ end end - describe '.trial_end_date' do + describe '#trial_end_date' do let(:plan) { create(:plan, trial_period: 3) } let(:subscription) { create(:active_subscription, plan: plan) } @@ -115,24 +115,24 @@ end end - describe '.valid_unique_id' do + describe '#valid_external_id' do let(:organization) { create(:organization) } let(:customer) { create(:customer, organization: organization) } let(:plan) { create(:plan) } - let(:unique_id) { SecureRandom.uuid } + let(:external_id) { SecureRandom.uuid } let(:subscription) { create(:active_subscription, plan: plan, customer: customer) } - let(:new_subscription) { build(:active_subscription, plan: plan, unique_id: unique_id, customer: customer) } + let(:new_subscription) { build(:active_subscription, plan: plan, external_id: external_id, customer: customer) } before { subscription } - context 'when unique_id is unique' do - it 'does not raise validation error if unique_id is unique' do + context 'when external_id is unique' do + it 'does not raise validation error if external_id is unique' do expect(new_subscription).to be_valid end end - context 'when unique_id is NOT unique' do - let(:unique_id) { subscription.unique_id } + context 'when external_id is NOT unique' do + let(:external_id) { subscription.external_id } it 'raises validation error' do expect(new_subscription).not_to be_valid diff --git a/spec/requests/api/v1/subscriptions_spec.rb b/spec/requests/api/v1/subscriptions_spec.rb index ccff28e2c95..951276b9fa4 100644 --- a/spec/requests/api/v1/subscriptions_spec.rb +++ b/spec/requests/api/v1/subscriptions_spec.rb @@ -13,7 +13,7 @@ customer_id: customer.customer_id, plan_code: plan.code, name: 'subscription name', - unique_id: SecureRandom.uuid, + external_id: SecureRandom.uuid, billing_time: 'anniversary', } end diff --git a/spec/services/subscriptions/create_service_spec.rb b/spec/services/subscriptions/create_service_spec.rb index e84443783ef..56383806bf4 100644 --- a/spec/services/subscriptions/create_service_spec.rb +++ b/spec/services/subscriptions/create_service_spec.rb @@ -10,14 +10,14 @@ describe '.create_from_api' do let(:plan) { create(:plan, amount_cents: 100, organization: organization) } let(:customer) { create(:customer, organization: organization) } - let(:unique_id) { SecureRandom.uuid } + let(:external_id) { SecureRandom.uuid } let(:params) do { customer_id: customer.customer_id, plan_code: plan.code, name: 'invoice display name', - unique_id: unique_id, + external_id: external_id, billing_time: 'anniversary', } end @@ -43,21 +43,21 @@ expect(subscription.subscription_date).to be_present expect(subscription.name).to eq('invoice display name') expect(subscription).to be_active - expect(subscription.unique_id).to be_present + expect(subscription.external_id).to be_present expect(subscription).to be_anniversary end end - context 'when unique_id is not given' do - let(:unique_id) { nil } + context 'when external_id is not given' do + let(:external_id) { nil } - it 'sets customer_id as unique_id' do + it 'sets customer_id as external_id' do result = create_service.create_from_api( organization: organization, params: params, ) - expect(result.subscription.unique_id).to eq(customer.customer_id) + expect(result.subscription.external_id).to eq(customer.customer_id) end end @@ -67,7 +67,7 @@ customer_id: customer.customer_id, plan_code: plan.code, name: 'invoice display name', - unique_id: unique_id, + external_id: external_id, } end @@ -111,7 +111,7 @@ { customer_id: SecureRandom.uuid, plan_code: plan.code, - unique_id: unique_id, + external_id: external_id, } end @@ -153,7 +153,7 @@ { customer_id: nil, plan_code: plan.code, - unique_id: unique_id, + external_id: external_id, } end @@ -173,7 +173,7 @@ { customer_id: customer.customer_id, plan_code: 'invalid_plan', - unique_id: unique_id, + external_id: external_id, } end @@ -193,7 +193,7 @@ { customer_id: customer.id, plan_code: plan.code, - unique_id: unique_id, + external_id: external_id, billing_time: :foo, } end @@ -220,7 +220,7 @@ plan_code: plan.code, name: 'invoice display name', subscription_id: subscription.id, - unique_id: unique_id, + external_id: external_id, } end let(:subscription) do @@ -248,18 +248,18 @@ end end - context 'when unique_id is given but not subscription_id' do + context 'when external_id is given but not subscription_id' do let(:params) do { customer_id: customer.customer_id, plan_code: plan.code, name: 'invoice display name', - unique_id: unique_id, + external_id: external_id, } end it 'returns existing subscription' do - subscription.update!(unique_id: unique_id) + subscription.update!(external_id: external_id) result = create_service.create_from_api( organization: organization, @@ -271,7 +271,7 @@ end end - context 'when subscription_id and unique_id are not given' do + context 'when subscription_id and external_id are not given' do let(:params) do { customer_id: customer.customer_id, @@ -281,7 +281,7 @@ end it 'returns existing subscription' do - subscription.update!(unique_id: customer.customer_id) + subscription.update!(external_id: customer.customer_id) result = create_service.create_from_api( organization: organization, @@ -300,7 +300,7 @@ customer_id: customer.customer_id, plan_code: new_plan.code, name: 'invoice display name new', - unique_id: unique_id, + external_id: external_id, } end @@ -324,7 +324,7 @@ plan_code: higher_plan.code, name: 'invoice display name new', subscription_id: subscription.id, - unique_id: unique_id, + external_id: external_id, } end @@ -419,7 +419,7 @@ plan_code: lower_plan.code, name: 'invoice display name new', subscription_id: subscription.id, - unique_id: unique_id, + external_id: external_id, } end From b49adbd727239e8de4ad943439be39dc35f90627 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Romain=20Semp=C3=A9?= Date: Fri, 26 Aug 2022 17:39:50 +0200 Subject: [PATCH 2/9] misc: Refactor to use external_id on customers and subscriptions --- .../api/v1/applied_add_ons_controller.rb | 2 +- .../api/v1/applied_coupons_controller.rb | 2 +- .../api/v1/customers_controller.rb | 6 +- app/controllers/api/v1/events_controller.rb | 8 +- .../api/v1/subscriptions_controller.rb | 8 +- app/graphql/mutations/customers/create.rb | 2 +- app/graphql/mutations/customers/update.rb | 2 +- app/graphql/types/customers/object.rb | 2 +- app/graphql/types/events/object.rb | 10 +- app/models/customer.rb | 2 +- .../v1/applied_add_on_serializer.rb | 2 +- .../v1/applied_coupon_serializer.rb | 2 +- app/serializers/v1/customer_serializer.rb | 2 +- app/serializers/v1/event_serializer.rb | 3 +- .../customer_error_serializer.rb | 2 +- .../invoice_payment_error_serializer.rb | 2 +- app/serializers/v1/subscription_serializer.rb | 2 +- .../applied_add_ons/create_service.rb | 2 +- .../applied_coupons/create_service.rb | 2 +- app/services/customers/create_service.rb | 4 +- app/services/customers/update_service.rb | 6 +- app/services/events/create_batch_service.rb | 11 +- app/services/events/create_service.rb | 20 ++-- .../events/validate_creation_service.rb | 20 ++-- .../invoices/customer_usage_service.rb | 15 +-- .../create_service.rb | 2 +- .../stripe_service.rb | 2 +- app/services/subscriptions/create_service.rb | 13 ++- .../subscriptions/terminate_service.rb | 4 +- app/services/subscriptions/update_service.rb | 4 +- config/routes.rb | 6 +- ...customer_id_to_external_id_on_customers.rb | 5 + db/schema.rb | 4 +- db/seeds.rb | 2 +- schema.graphql | 10 +- schema.json | 54 +++++----- spec/factories/customer_factory.rb | 2 +- .../mutations/customers/create_spec.rb | 10 +- .../mutations/customers/update_spec.rb | 10 +- .../customers/update_vat_rate_spec.rb | 2 +- .../resolvers/customer_resolver_spec.rb | 2 +- .../resolvers/customers_resolver_spec.rb | 2 +- .../graphql/resolvers/events_resolver_spec.rb | 4 +- spec/models/customer_spec.rb | 4 +- spec/requests/api/v1/applied_add_ons_spec.rb | 4 +- spec/requests/api/v1/applied_coupons_spec.rb | 4 +- spec/requests/api/v1/customers_spec.rb | 12 +-- spec/requests/api/v1/events_spec.rb | 10 +- spec/requests/api/v1/subscriptions_spec.rb | 14 +-- .../customer_error_serializer_spec.rb | 2 +- .../invoice_payment_error_serializer_spec.rb | 2 +- .../applied_add_ons/create_service_spec.rb | 6 +- .../applied_coupons/create_service_spec.rb | 6 +- .../services/customers/create_service_spec.rb | 22 ++-- .../services/customers/update_service_spec.rb | 14 +-- .../events/create_batch_service_spec.rb | 8 +- spec/services/events/create_service_spec.rb | 33 +++--- .../events/validate_creation_service_spec.rb | 42 ++++---- .../subscriptions/create_service_spec.rb | 100 ++++++++---------- .../subscriptions/terminate_service_spec.rb | 9 +- .../subscriptions/update_service_spec.rb | 6 +- spec/services/webhooks/event_service_spec.rb | 2 +- 62 files changed, 282 insertions(+), 295 deletions(-) create mode 100644 db/migrate/20220824113131_rename_customer_id_to_external_id_on_customers.rb diff --git a/app/controllers/api/v1/applied_add_ons_controller.rb b/app/controllers/api/v1/applied_add_ons_controller.rb index 044015a1fb1..82e90547111 100644 --- a/app/controllers/api/v1/applied_add_ons_controller.rb +++ b/app/controllers/api/v1/applied_add_ons_controller.rb @@ -26,7 +26,7 @@ def create def create_params params.require(:applied_add_on).permit( - :customer_id, + :external_customer_id, :add_on_code, :amount_cents, :amount_currency, diff --git a/app/controllers/api/v1/applied_coupons_controller.rb b/app/controllers/api/v1/applied_coupons_controller.rb index 774d63977c9..1fa2d66c2ec 100644 --- a/app/controllers/api/v1/applied_coupons_controller.rb +++ b/app/controllers/api/v1/applied_coupons_controller.rb @@ -26,7 +26,7 @@ def create def create_params params.require(:applied_coupon).permit( - :customer_id, + :external_customer_id, :coupon_code, :amount_cents, :amount_currency, diff --git a/app/controllers/api/v1/customers_controller.rb b/app/controllers/api/v1/customers_controller.rb index 0ecf4c2fa85..b9c5c3d88d2 100644 --- a/app/controllers/api/v1/customers_controller.rb +++ b/app/controllers/api/v1/customers_controller.rb @@ -26,8 +26,8 @@ def current_usage service = Invoices::CustomerUsageService .new( nil, - customer_id: params[:customer_id], - subscription_id: params[:subscription_id], + customer_id: params[:customer_external_id], + subscription_id: params[:external_subscription_id], organization_id: current_organization.id, ) result = service.usage @@ -49,7 +49,7 @@ def current_usage def create_params params.require(:customer).permit( - :customer_id, + :external_id, :name, :country, :address_line1, diff --git a/app/controllers/api/v1/events_controller.rb b/app/controllers/api/v1/events_controller.rb index 45adda8e17f..b19ae73cf86 100644 --- a/app/controllers/api/v1/events_controller.rb +++ b/app/controllers/api/v1/events_controller.rb @@ -54,10 +54,10 @@ def create_params .require(:event) .permit( :transaction_id, - :customer_id, + :external_customer_id, :code, :timestamp, - :subscription_id, + :external_subscription_id, properties: {}, ) end @@ -67,10 +67,10 @@ def batch_params .require(:event) .permit( :transaction_id, - :customer_id, + :external_customer_id, :code, :timestamp, - subscription_ids: [], + external_subscription_ids: [], properties: {}, ) end diff --git a/app/controllers/api/v1/subscriptions_controller.rb b/app/controllers/api/v1/subscriptions_controller.rb index 300e24d0c7e..2425ec3491e 100644 --- a/app/controllers/api/v1/subscriptions_controller.rb +++ b/app/controllers/api/v1/subscriptions_controller.rb @@ -27,7 +27,7 @@ def terminate result = Subscriptions::TerminateService.new .terminate_from_api( organization: current_organization, - subscription_id: params[:id] + external_id: params[:external_id] ) if result.success? @@ -47,7 +47,7 @@ def update result = service.update_from_api( organization: current_organization, - id: params[:id], + external_id: params[:external_id], params: update_params ) @@ -64,7 +64,7 @@ def update end def index - customer = current_organization.customers.find_by(customer_id: params[:customer_id]) + customer = current_organization.customers.find_by(external_id: params[:external_customer_id]) return not_found_error unless customer @@ -86,7 +86,7 @@ def index def create_params params.require(:subscription) - .permit(:customer_id, :plan_code, :name, :subscription_id, :external_id, :billing_time) + .permit(:external_customer_id, :plan_code, :name, :subscription_id, :external_id, :billing_time) end def update_params diff --git a/app/graphql/mutations/customers/create.rb b/app/graphql/mutations/customers/create.rb index 51a66e03fed..3a3434ec6ab 100644 --- a/app/graphql/mutations/customers/create.rb +++ b/app/graphql/mutations/customers/create.rb @@ -10,7 +10,7 @@ class Create < BaseMutation description 'Creates a new customer' argument :name, String, required: true - argument :customer_id, String, required: true + argument :external_id, String, required: true argument :country, Types::CountryCodeEnum, required: false argument :address_line1, String, required: false argument :address_line2, String, required: false diff --git a/app/graphql/mutations/customers/update.rb b/app/graphql/mutations/customers/update.rb index b2d911c3986..feec4fecdfe 100644 --- a/app/graphql/mutations/customers/update.rb +++ b/app/graphql/mutations/customers/update.rb @@ -10,7 +10,7 @@ class Update < BaseMutation argument :id, ID, required: true argument :name, String, required: true - argument :customer_id, String, required: true + argument :external_id, String, required: true argument :country, Types::CountryCodeEnum, required: false argument :address_line1, String, required: false argument :address_line2, String, required: false diff --git a/app/graphql/types/customers/object.rb b/app/graphql/types/customers/object.rb index 3c3f0ef0c7a..ddc35b06699 100644 --- a/app/graphql/types/customers/object.rb +++ b/app/graphql/types/customers/object.rb @@ -7,7 +7,7 @@ class Object < Types::BaseObject field :id, ID, null: false - field :customer_id, String, null: false + field :external_id, String, null: false field :name, String field :sequential_id, String, null: false field :slug, String, null: false diff --git a/app/graphql/types/events/object.rb b/app/graphql/types/events/object.rb index 27e646c115d..b2dc152515e 100644 --- a/app/graphql/types/events/object.rb +++ b/app/graphql/types/events/object.rb @@ -1,5 +1,3 @@ -# r - module Types module Events class Object < Types::BaseObject @@ -8,7 +6,7 @@ class Object < Types::BaseObject field :id, ID, null: false field :code, String, null: false - field :customer_id, String, null: false + field :external_customer_id, String, null: false field :subscription_id, String, null: false field :transaction_id, String, null: true @@ -27,15 +25,15 @@ def received_at object.created_at end - def customer_id - object.customer.customer_id + def external_customer_id + object.customer.external_id end def payload { event: { transaction_id: object.transaction_id, - customer_id: object.customer.customer_id, + external_customer_id: object.customer.external_id, subscription_id: object.subscription_id, code: object.code, timestamp: object.timestamp.to_i, diff --git a/app/models/customer.rb b/app/models/customer.rb index 1a95ebab036..4123e0500be 100644 --- a/app/models/customer.rb +++ b/app/models/customer.rb @@ -27,7 +27,7 @@ class Customer < ApplicationRecord sequenced scope: ->(customer) { customer.organization.customers } - validates :customer_id, presence: true, uniqueness: { scope: :organization_id } + validates :external_id, presence: true, uniqueness: { scope: :organization_id } validates :country, country_code: true, unless: -> { country.nil? } validates :vat_rate, numericality: { less_than_or_equal_to: 100, greater_than_or_equal_to: 0 }, allow_nil: true validates :payment_provider, inclusion: { in: PAYMENT_PROVIDERS }, allow_nil: true diff --git a/app/serializers/v1/applied_add_on_serializer.rb b/app/serializers/v1/applied_add_on_serializer.rb index 12aabdfb2e2..fe5e5c00dfd 100644 --- a/app/serializers/v1/applied_add_on_serializer.rb +++ b/app/serializers/v1/applied_add_on_serializer.rb @@ -7,8 +7,8 @@ def serialize lago_id: model.id, lago_add_on_id: model.add_on.id, add_on_code: model.add_on.code, - customer_id: model.customer.customer_id, lago_customer_id: model.customer.id, + external_customer_id: model.customer.external_id, amount_cents: model.amount_cents, amount_currency: model.amount_currency, created_at: model.created_at.iso8601, diff --git a/app/serializers/v1/applied_coupon_serializer.rb b/app/serializers/v1/applied_coupon_serializer.rb index 06d8bf7b3b3..0ecd0e56daf 100644 --- a/app/serializers/v1/applied_coupon_serializer.rb +++ b/app/serializers/v1/applied_coupon_serializer.rb @@ -7,8 +7,8 @@ def serialize lago_id: model.id, lago_coupon_id: model.coupon.id, coupon_code: model.coupon.code, - customer_id: model.customer.customer_id, lago_customer_id: model.customer.id, + external_customer_id: model.customer.external_id, amount_cents: model.amount_cents, amount_currency: model.amount_currency, expiration_date: model.coupon.expiration_date&.iso8601, diff --git a/app/serializers/v1/customer_serializer.rb b/app/serializers/v1/customer_serializer.rb index ca69164216e..390de160997 100644 --- a/app/serializers/v1/customer_serializer.rb +++ b/app/serializers/v1/customer_serializer.rb @@ -5,7 +5,7 @@ class CustomerSerializer < ModelSerializer def serialize { lago_id: model.id, - customer_id: model.customer_id, + external_id: model.external_id, name: model.name, sequential_id: model.sequential_id, slug: model.slug, diff --git a/app/serializers/v1/event_serializer.rb b/app/serializers/v1/event_serializer.rb index a365177643f..e855746e509 100644 --- a/app/serializers/v1/event_serializer.rb +++ b/app/serializers/v1/event_serializer.rb @@ -1,5 +1,4 @@ # frozen_string_literal: true -# module V1 class EventSerializer < ModelSerializer def serialize @@ -7,7 +6,7 @@ def serialize lago_id: model.id, transaction_id: model.transaction_id, lago_customer_id: model.customer_id, - customer_id: model.customer&.customer_id, + external_customer_id: model.customer&.external_id, code: model.code, timestamp: model.timestamp.iso8601, properties: model.properties, diff --git a/app/serializers/v1/payment_providers/customer_error_serializer.rb b/app/serializers/v1/payment_providers/customer_error_serializer.rb index b5760d71a1e..14e1b3b01c9 100644 --- a/app/serializers/v1/payment_providers/customer_error_serializer.rb +++ b/app/serializers/v1/payment_providers/customer_error_serializer.rb @@ -6,7 +6,7 @@ class CustomerErrorSerializer < ModelSerializer def serialize { lago_customer_id: model.id, - customer_id: model.customer_id, + external_customer_id: model.external_id, payment_provider: model.payment_provider, provider_error: options[:provider_error], } diff --git a/app/serializers/v1/payment_providers/invoice_payment_error_serializer.rb b/app/serializers/v1/payment_providers/invoice_payment_error_serializer.rb index ef27ed39d0d..997ba60adb7 100644 --- a/app/serializers/v1/payment_providers/invoice_payment_error_serializer.rb +++ b/app/serializers/v1/payment_providers/invoice_payment_error_serializer.rb @@ -9,7 +9,7 @@ def serialize { lago_invoice_id: invoice.id, lago_customer_id: invoice.customer.id, - customer_id: invoice.customer.customer_id, + external_customer_id: invoice.customer.external_id, provider_customer_id: options[:provider_customer_id], payment_provider: invoice.customer.payment_provider, provider_error: options[:provider_error], diff --git a/app/serializers/v1/subscription_serializer.rb b/app/serializers/v1/subscription_serializer.rb index 289e3e5898b..36069b68a07 100644 --- a/app/serializers/v1/subscription_serializer.rb +++ b/app/serializers/v1/subscription_serializer.rb @@ -7,7 +7,7 @@ def serialize lago_id: model.id, external_id: model.external_id, lago_customer_id: model.customer_id, - customer_id: model.customer.customer_id, + external_customer_id: model.customer.external_id, name: model.name, plan_code: model.plan.code, status: model.status, diff --git a/app/services/applied_add_ons/create_service.rb b/app/services/applied_add_ons/create_service.rb index 5fe5e0cd27b..d46440155dc 100644 --- a/app/services/applied_add_ons/create_service.rb +++ b/app/services/applied_add_ons/create_service.rb @@ -21,7 +21,7 @@ def create(**args) def create_from_api(organization:, args:) @customer = Customer.find_by( - customer_id: args[:customer_id], + external_id: args[:external_customer_id], organization_id: organization.id, ) diff --git a/app/services/applied_coupons/create_service.rb b/app/services/applied_coupons/create_service.rb index 8b2cbb8bb5d..4574000d4cc 100644 --- a/app/services/applied_coupons/create_service.rb +++ b/app/services/applied_coupons/create_service.rb @@ -21,7 +21,7 @@ def create(**args) def create_from_api(organization:, args:) @customer = Customer.find_by( - customer_id: args[:customer_id], + external_id: args[:external_customer_id], organization_id: organization.id, ) diff --git a/app/services/customers/create_service.rb b/app/services/customers/create_service.rb index 52969b1bb7e..d4e238c5031 100644 --- a/app/services/customers/create_service.rb +++ b/app/services/customers/create_service.rb @@ -3,7 +3,7 @@ module Customers class CreateService < BaseService def create_from_api(organization:, params:) - customer = organization.customers.find_or_initialize_by(customer_id: params[:customer_id]) + customer = organization.customers.find_or_initialize_by(external_id: params[:external_id]) customer.name = params[:name] if params.key?(:name) customer.country = params[:country]&.upcase if params.key?(:country) @@ -35,7 +35,7 @@ def create_from_api(organization:, params:) def create(**args) customer = Customer.create!( organization_id: args[:organization_id], - customer_id: args[:customer_id], + external_id: args[:external_id], name: args[:name], country: args[:country]&.upcase, address_line1: args[:address_line1], diff --git a/app/services/customers/update_service.rb b/app/services/customers/update_service.rb index 8697def8498..fd68fbbf518 100644 --- a/app/services/customers/update_service.rb +++ b/app/services/customers/update_service.rb @@ -22,9 +22,9 @@ def update(**args) customer.vat_rate = args[:vat_rate] if args.key?(:vat_rate) customer.payment_provider = args[:payment_provider] if args.key?(:payment_provider) - # NOTE: Customer_id is not editable if customer is attached to subscriptions - if !customer.attached_to_subscriptions? && args.key?(:customer_id) - customer.customer_id = args[:customer_id] + # NOTE: external_id is not editable if customer is attached to subscriptions + if !customer.attached_to_subscriptions? && args.key?(:external_id) + customer.external_id = args[:external_id] end customer.save! diff --git a/app/services/events/create_batch_service.rb b/app/services/events/create_batch_service.rb index 3437a122cfd..973466dadac 100644 --- a/app/services/events/create_batch_service.rb +++ b/app/services/events/create_batch_service.rb @@ -2,7 +2,7 @@ module Events class CreateBatchService < BaseService - ALL_REQUIRED_PARAMS = %i[transaction_id code subscription_ids].freeze + ALL_REQUIRED_PARAMS = %i[transaction_id code external_subscription_ids].freeze def validate_params(params:) missing_params = ALL_REQUIRED_PARAMS.select { |key| params[key].blank? } @@ -13,7 +13,7 @@ def validate_params(params:) def call(organization:, params:, timestamp:, metadata:) customer = organization.subscriptions.find_by( - id: params[:subscription_ids]&.first + external_id: params[:external_subscription_ids]&.first )&.customer Events::ValidateCreationService.call( @@ -27,8 +27,9 @@ def call(organization:, params:, timestamp:, metadata:) events = [] ActiveRecord::Base.transaction do - params[:subscription_ids].each do |id| - event = organization.events.find_by(transaction_id: params[:transaction_id], subscription_id: id) + params[:external_subscription_ids].each do |id| + subscription = Subscription.find_by(external_id: id) + event = organization.events.find_by(transaction_id: params[:transaction_id], subscription_id: subscription.id) if event events << event @@ -40,7 +41,7 @@ def call(organization:, params:, timestamp:, metadata:) event.code = params[:code] event.transaction_id = params[:transaction_id] event.customer = customer - event.subscription_id = id + event.subscription_id = subscription.id event.properties = params[:properties] || {} event.metadata = metadata || {} diff --git a/app/services/events/create_service.rb b/app/services/events/create_service.rb index c9e2f7c752a..d63c9a0febf 100644 --- a/app/services/events/create_service.rb +++ b/app/services/events/create_service.rb @@ -3,17 +3,17 @@ module Events class CreateService < BaseService ALL_REQUIRED_PARAMS = %i[transaction_id code].freeze - ONE_REQUIRED_PARAMS = %i[subscription_id customer_id].freeze + ONE_REQUIRED_PARAMS = %i[external_subscription_id external_customer_id].freeze def validate_params(params:) missing_params = ALL_REQUIRED_PARAMS.select { |key| params[key].blank? } missing_params |= ONE_REQUIRED_PARAMS if ONE_REQUIRED_PARAMS.all? { |key| params[key].blank? } # NOTE: In case of multiple subscriptions, we return an error if subscription_id is not given. - if params[:customer_id].present? && params[:subscription_id].blank? - customer = Customer.find_by(customer_id: params[:customer_id]) + if params[:external_customer_id].present? && params[:external_subscription_id].blank? + customer = Customer.find_by(external_id: params[:external_customer_id]) subscriptions_count = customer ? customer.active_subscriptions.count : 0 - missing_params |= %i[subscription_id] if subscriptions_count > 1 + missing_params |= %i[external_subscription_id] if subscriptions_count > 1 end return result if missing_params.blank? @@ -22,10 +22,10 @@ def validate_params(params:) end def call(organization:, params:, timestamp:, metadata:) - customer = if params[:subscription_id] - organization.subscriptions.find_by(id: params[:subscription_id])&.customer + customer = if params[:external_subscription_id] + organization.subscriptions.find_by(external_id: params[:external_subscription_id])&.customer else - Customer.find_by(customer_id: params[:customer_id], organization_id: organization.id) + Customer.find_by(external_id: params[:external_customer_id], organization_id: organization.id) end Events::ValidateCreationService.call( @@ -37,8 +37,8 @@ def call(organization:, params:, timestamp:, metadata:) return result unless result.success? - subscription_id = params[:subscription_id] || customer&.active_subscriptions&.pluck(:id).first - event = organization.events.find_by(transaction_id: params[:transaction_id], subscription_id: subscription_id) + subscription = Subscription.find_by(external_id: params[:external_subscription_id]) || customer&.active_subscriptions&.first + event = organization.events.find_by(transaction_id: params[:transaction_id], subscription_id: subscription.id) if event result.event = event @@ -49,7 +49,7 @@ def call(organization:, params:, timestamp:, metadata:) event.code = params[:code] event.transaction_id = params[:transaction_id] event.customer = customer - event.subscription_id = subscription_id + event.subscription_id = subscription.id event.properties = params[:properties] || {} event.metadata = metadata || {} diff --git a/app/services/events/validate_creation_service.rb b/app/services/events/validate_creation_service.rb index 78ba3e1249e..3af9ce1c01c 100644 --- a/app/services/events/validate_creation_service.rb +++ b/app/services/events/validate_creation_service.rb @@ -23,10 +23,10 @@ def call attr_reader :organization, :params, :result, :customer, :batch def validate_create_batch - return blank_subscription_error if params[:subscription_ids].blank? + return blank_subscription_error if params[:external_subscription_ids].blank? return invalid_customer_error unless customer - invalid_subscriptions = params[:subscription_ids].select { |arg| !customer_subscription_ids.include?(arg) } + invalid_subscriptions = params[:external_subscription_ids].select { |arg| !customer_external_subscription_ids.include?(arg) } return invalid_subscription_error if invalid_subscriptions.present? return invalid_code_error unless valid_code? end @@ -34,20 +34,20 @@ def validate_create_batch def validate_create return invalid_customer_error unless customer - if customer_subscription_ids.count > 1 - return blank_subscription_error if params[:subscription_id].blank? + if customer_external_subscription_ids.count > 1 + return blank_subscription_error if params[:external_subscription_id].blank? return invalid_subscription_error unless valid_subscription_id? - elsif params[:subscription_id] + elsif params[:external_subscription_id] return invalid_subscription_error unless valid_subscription_id? else - return blank_subscription_error if customer_subscription_ids.blank? + return blank_subscription_error if customer_external_subscription_ids.blank? end return invalid_code_error unless valid_code? end def valid_subscription_id? - customer_subscription_ids.include?(params[:subscription_id]) + customer_external_subscription_ids.include?(params[:external_subscription_id]) end def valid_code? @@ -66,8 +66,8 @@ def send_webhook_notice SendWebhookJob.perform_later(:event, object) end - def customer_subscription_ids - @customer_subscription_ids ||= customer&.active_subscriptions&.pluck(:id) + def customer_external_subscription_ids + @customer_external_subscription_ids ||= customer&.active_subscriptions&.pluck(:external_id) end def blank_subscription_error @@ -76,7 +76,7 @@ def blank_subscription_error end def invalid_subscription_error - result.fail!(code: 'invalid_argument', message: 'subscription_id is invalid') + result.fail!(code: 'invalid_argument', message: 'external_subscription_id is invalid') send_webhook_notice end diff --git a/app/services/invoices/customer_usage_service.rb b/app/services/invoices/customer_usage_service.rb index d65a00cfb8f..60713ae2c4f 100644 --- a/app/services/invoices/customer_usage_service.rb +++ b/app/services/invoices/customer_usage_service.rb @@ -2,20 +2,19 @@ module Invoices class CustomerUsageService < BaseService + # NOTE: customer_id can reference the lago id or the external id of the customer + # NOTE: subscription_id can reference the lago id or the external id of the subscription def initialize(current_user, customer_id:, subscription_id:, organization_id: nil) super(current_user) if organization_id.present? @organization_id = organization_id - @customer = Customer.find_by!( - customer_id: customer_id, - organization_id: organization_id, - ) + @customer = Customer.find_by!(external_id: customer_id, organization_id: organization_id) + @subscription = @customer&.active_subscriptions&.find_by(external_id: subscription_id) else customer(customer_id: customer_id) + @subscription = @customer&.active_subscriptions&.find_by(id: subscription_id) end - - @subscription = find_subscription(subscription_id) rescue ActiveRecord::RecordNotFound result.fail!(code: 'not_found') end @@ -60,10 +59,6 @@ def customer(customer_id: nil) ) end - def find_subscription(subscription_id) - customer&.active_subscriptions&.find_by(id: subscription_id) - end - def add_charge_fee query = subscription.plan.charges.joins(:billable_metric) .order(Arel.sql('lower(unaccent(billable_metrics.name)) ASC')) diff --git a/app/services/payment_provider_customers/create_service.rb b/app/services/payment_provider_customers/create_service.rb index 7f6ae441a11..2b9a5a799c9 100644 --- a/app/services/payment_provider_customers/create_service.rb +++ b/app/services/payment_provider_customers/create_service.rb @@ -10,7 +10,7 @@ def initialize(customer) def create_or_update(customer_class:, payment_provider_id:, params:, async: true) provider_customer = customer_class.find_or_initialize_by( - customer_id: customer.id, + customer_id: customer.id, # TODO: Why? payment_provider_id: payment_provider_id, ) diff --git a/app/services/payment_provider_customers/stripe_service.rb b/app/services/payment_provider_customers/stripe_service.rb index 6e0f1d6561d..96bab5d5bdf 100644 --- a/app/services/payment_provider_customers/stripe_service.rb +++ b/app/services/payment_provider_customers/stripe_service.rb @@ -113,7 +113,7 @@ def stripe_create_payload name: customer.name, metadata: { lago_customer_id: customer.id, - customer_id: customer.customer_id, + customer_id: customer.external_id, }, phone: customer.phone, } diff --git a/app/services/subscriptions/create_service.rb b/app/services/subscriptions/create_service.rb index 308cc1e57d4..debbe5be66a 100644 --- a/app/services/subscriptions/create_service.rb +++ b/app/services/subscriptions/create_service.rb @@ -5,9 +5,9 @@ class CreateService < BaseService attr_reader :current_customer, :current_plan, :current_subscription, :name, :external_id, :billing_time def create_from_api(organization:, params:) - if params[:customer_id] + if params[:external_customer_id] @current_customer = Customer.find_or_create_by!( - customer_id: params[:customer_id]&.strip, + external_id: params[:external_customer_id]&.strip, organization_id: organization.id, ) end @@ -20,7 +20,7 @@ def create_from_api(organization:, params:) @name = params[:name]&.strip @external_id = params[:external_id]&.strip @billing_time = params[:billing_time] - @current_subscription = find_current_subscription(subscription_id: params[:subscription_id]) + @current_subscription = find_current_subscription process_create rescue ActiveRecord::RecordInvalid => e @@ -43,7 +43,6 @@ def create(**args) @external_id = SecureRandom.uuid @billing_time = args[:billing_time] @current_subscription = find_current_subscription(subscription_id: args[:subscription_id]) - process_create end @@ -97,7 +96,7 @@ def create_subscription plan_id: current_plan.id, subscription_date: Time.zone.now.to_date, name: name, - external_id: external_id || current_customer.customer_id, + external_id: external_id || current_customer.external_id, billing_time: billing_time || :calendar, ) new_subscription.mark_as_active! @@ -213,11 +212,11 @@ def active_subscriptions @active_subscriptions ||= current_customer&.active_subscriptions end - def find_current_subscription(subscription_id:) + def find_current_subscription(subscription_id: nil) return active_subscriptions&.find_by(id: subscription_id) if subscription_id return active_subscriptions&.find_by(external_id: external_id) if external_id - active_subscriptions&.find_by(external_id: current_customer.customer_id) + active_subscriptions&.find_by(external_id: current_customer.external_id) end end end diff --git a/app/services/subscriptions/terminate_service.rb b/app/services/subscriptions/terminate_service.rb index 7b13154f0af..046148eaaed 100644 --- a/app/services/subscriptions/terminate_service.rb +++ b/app/services/subscriptions/terminate_service.rb @@ -9,8 +9,8 @@ def terminate(subscription_id) process_terminate(subscription) end - def terminate_from_api(organization:, subscription_id:) - subscription = organization.subscriptions.find_by(id: subscription_id) + def terminate_from_api(organization:, external_id:) + subscription = organization.subscriptions.find_by(external_id: external_id) return result.fail!(code: 'not_found', message: 'subscription is not found') if subscription.blank? process_terminate(subscription) diff --git a/app/services/subscriptions/update_service.rb b/app/services/subscriptions/update_service.rb index 97c0922cfae..5e8c1aeb2fc 100644 --- a/app/services/subscriptions/update_service.rb +++ b/app/services/subscriptions/update_service.rb @@ -16,8 +16,8 @@ def update(**args) result.fail_with_validations!(e.record) end - def update_from_api(organization:, id:, params:) - subscription = organization.subscriptions.find_by(id: id) + def update_from_api(organization:, external_id:, params:) + subscription = organization.subscriptions.find_by(external_id: external_id) return result.fail!(code: 'not_found', message: 'subscription is not found') unless subscription subscription.name = params[:name] if params.key?(:name) diff --git a/config/routes.rb b/config/routes.rb index 70f091f3e35..575d2e00a8d 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -16,12 +16,12 @@ namespace :api do namespace :v1 do - resources :customers, only: %i[create] do + resources :customers, param: :external_id, only: %i[create] do get :current_usage end - resources :subscriptions, only: %i[create update index] - delete '/subscriptions/:id', to: 'subscriptions#terminate', as: :terminate + resources :subscriptions, only: %i[create update index], param: :external_id + delete '/subscriptions/:external_id', to: 'subscriptions#terminate', as: :terminate resources :add_ons, param: :code resources :billable_metrics, param: :code diff --git a/db/migrate/20220824113131_rename_customer_id_to_external_id_on_customers.rb b/db/migrate/20220824113131_rename_customer_id_to_external_id_on_customers.rb new file mode 100644 index 00000000000..e68ea4040c4 --- /dev/null +++ b/db/migrate/20220824113131_rename_customer_id_to_external_id_on_customers.rb @@ -0,0 +1,5 @@ +class RenameCustomerIdToExternalIdOnCustomers < ActiveRecord::Migration[7.0] + def change + rename_column :customers, :customer_id, :external_id + end +end diff --git a/db/schema.rb b/db/schema.rb index f6f61020c20..ee7d0680210 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -136,7 +136,7 @@ end create_table "customers", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| - t.string "customer_id", null: false + t.string "external_id", null: false t.string "name" t.uuid "organization_id", null: false t.datetime "created_at", null: false @@ -157,7 +157,7 @@ t.string "payment_provider" t.string "slug" t.bigint "sequential_id" - t.index ["customer_id"], name: "index_customers_on_customer_id" + t.index ["external_id"], name: "index_customers_on_external_id" t.index ["organization_id"], name: "index_customers_on_organization_id" end diff --git a/db/seeds.rb b/db/seeds.rb index 252e5e325a3..2435d08b67a 100644 --- a/db/seeds.rb +++ b/db/seeds.rb @@ -58,7 +58,7 @@ legal_number: Faker::Company.duns_number, ).find_or_create_by!( organization: organization, - customer_id: "cust_#{i + 1}", + external_id: "cust_#{i + 1}", ) sub = Subscription.create_with( diff --git a/schema.graphql b/schema.graphql index dbe4406c8bc..307241e227d 100644 --- a/schema.graphql +++ b/schema.graphql @@ -1594,8 +1594,8 @@ input CreateCustomerInput { """ clientMutationId: String country: CountryCode - customerId: String! email: String + externalId: String! legalName: String legalNumber: String logoUrl: String @@ -2377,8 +2377,8 @@ type Customer { city: String country: CountryCode createdAt: ISO8601DateTime! - customerId: String! email: String + externalId: String! """ Define if a customer has an active wallet @@ -2425,8 +2425,8 @@ type CustomerDetails { country: CountryCode createdAt: ISO8601DateTime! currency: CurrencyEnum - customerId: String! email: String + externalId: String! """ Define if a customer has an active wallet @@ -2620,7 +2620,7 @@ type Event { apiClient: String billableMetricName: String code: String! - customerId: String! + externalCustomerId: String! id: ID! ipAddress: String matchBillableMetric: Boolean! @@ -3516,8 +3516,8 @@ input UpdateCustomerInput { """ clientMutationId: String country: CountryCode - customerId: String! email: String + externalId: String! id: ID! legalName: String legalNumber: String diff --git a/schema.json b/schema.json index 3aeeca7449e..59700629dfb 100644 --- a/schema.json +++ b/schema.json @@ -4519,7 +4519,7 @@ "deprecationReason": null }, { - "name": "customerId", + "name": "externalId", "description": null, "type": { "kind": "NON_NULL", @@ -6169,16 +6169,12 @@ ] }, { - "name": "customerId", + "name": "email", "description": null, "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "String", - "ofType": null - } + "kind": "SCALAR", + "name": "String", + "ofType": null }, "isDeprecated": false, "deprecationReason": null, @@ -6187,12 +6183,16 @@ ] }, { - "name": "email", + "name": "externalId", "description": null, "type": { - "kind": "SCALAR", - "name": "String", - "ofType": null + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } }, "isDeprecated": false, "deprecationReason": null, @@ -6705,16 +6705,12 @@ ] }, { - "name": "customerId", + "name": "email", "description": null, "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "String", - "ofType": null - } + "kind": "SCALAR", + "name": "String", + "ofType": null }, "isDeprecated": false, "deprecationReason": null, @@ -6723,12 +6719,16 @@ ] }, { - "name": "email", + "name": "externalId", "description": null, "type": { - "kind": "SCALAR", - "name": "String", - "ofType": null + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } }, "isDeprecated": false, "deprecationReason": null, @@ -7827,7 +7827,7 @@ ] }, { - "name": "customerId", + "name": "externalCustomerId", "description": null, "type": { "kind": "NON_NULL", @@ -12829,7 +12829,7 @@ "deprecationReason": null }, { - "name": "customerId", + "name": "externalId", "description": null, "type": { "kind": "NON_NULL", diff --git a/spec/factories/customer_factory.rb b/spec/factories/customer_factory.rb index 940ec9108e0..b4ff189d06c 100644 --- a/spec/factories/customer_factory.rb +++ b/spec/factories/customer_factory.rb @@ -4,7 +4,7 @@ factory :customer do organization name { Faker::TvShows::SiliconValley.character } - customer_id { SecureRandom.uuid } + external_id { SecureRandom.uuid } country { Faker::Address.country_code } address_line1 { Faker::Address.street_address } address_line2 { Faker::Address.secondary_address } diff --git a/spec/graphql/mutations/customers/create_spec.rb b/spec/graphql/mutations/customers/create_spec.rb index cbe0cc080b8..b7caccc7620 100644 --- a/spec/graphql/mutations/customers/create_spec.rb +++ b/spec/graphql/mutations/customers/create_spec.rb @@ -13,7 +13,7 @@ createCustomer(input: $input) { id, name, - customerId, + externalId, city country paymentProvider @@ -33,7 +33,7 @@ variables: { input: { name: 'John Doe', - customerId: 'john_doe_2', + externalId: 'john_doe_2', city: 'London', country: 'GB', paymentProvider: 'stripe', @@ -49,7 +49,7 @@ aggregate_failures do expect(result_data['id']).to be_present expect(result_data['name']).to eq('John Doe') - expect(result_data['customerId']).to eq('john_doe_2') + expect(result_data['externalId']).to eq('john_doe_2') expect(result_data['city']).to eq('London') expect(result_data['country']).to eq('GB') expect(result_data['paymentProvider']).to eq('stripe') @@ -66,7 +66,7 @@ variables: { input: { name: 'John Doe', - customerId: 'john_doe_2', + externalId: 'john_doe_2', }, }, ) @@ -83,7 +83,7 @@ variables: { input: { name: 'John Doe', - customerId: 'john_doe_2', + externalId: 'john_doe_2', }, }, ) diff --git a/spec/graphql/mutations/customers/update_spec.rb b/spec/graphql/mutations/customers/update_spec.rb index 65edf7dda66..44771d8ccea 100644 --- a/spec/graphql/mutations/customers/update_spec.rb +++ b/spec/graphql/mutations/customers/update_spec.rb @@ -14,7 +14,7 @@ updateCustomer(input: $input) { id, name, - customerId + externalId paymentProvider stripeCustomer { id, providerCustomerId } } @@ -24,7 +24,7 @@ it 'updates a customer' do stripe_provider - customer_id = SecureRandom.uuid + external_id = SecureRandom.uuid result = execute_graphql( current_user: membership.user, @@ -33,7 +33,7 @@ input: { id: customer.id, name: 'Updated customer', - customerId: customer_id, + externalId: external_id, paymentProvider: 'stripe', stripeCustomer: { providerCustomerId: 'cu_12345', @@ -47,7 +47,7 @@ aggregate_failures do expect(result_data['id']).to be_present expect(result_data['name']).to eq('Updated customer') - expect(result_data['customerId']).to eq(customer_id) + expect(result_data['externalId']).to eq(external_id) expect(result_data['paymentProvider']).to eq('stripe') expect(result_data['stripeCustomer']['id']).to be_present expect(result_data['stripeCustomer']['providerCustomerId']).to eq('cu_12345') @@ -62,7 +62,7 @@ input: { id: customer.id, name: 'Updated customer', - customerId: SecureRandom.uuid, + externalId: SecureRandom.uuid, }, }, ) diff --git a/spec/graphql/mutations/customers/update_vat_rate_spec.rb b/spec/graphql/mutations/customers/update_vat_rate_spec.rb index 7b1a528d755..572f30ecdf0 100644 --- a/spec/graphql/mutations/customers/update_vat_rate_spec.rb +++ b/spec/graphql/mutations/customers/update_vat_rate_spec.rb @@ -13,7 +13,7 @@ updateCustomerVatRate(input: $input) { id, name, - customerId, + externalId, vatRate } } diff --git a/spec/graphql/resolvers/customer_resolver_spec.rb b/spec/graphql/resolvers/customer_resolver_spec.rb index 5b63bb4575c..74f028d0fad 100644 --- a/spec/graphql/resolvers/customer_resolver_spec.rb +++ b/spec/graphql/resolvers/customer_resolver_spec.rb @@ -7,7 +7,7 @@ <<~GQL query($customerId: ID!) { customer(id: $customerId) { - id customerId name currency + id externalId name currency invoices { id invoiceType status } subscriptions(status: [active]) { id, status } appliedCoupons { id amountCents amountCurrency coupon { id name } } diff --git a/spec/graphql/resolvers/customers_resolver_spec.rb b/spec/graphql/resolvers/customers_resolver_spec.rb index cb35a01456d..753b43128b9 100644 --- a/spec/graphql/resolvers/customers_resolver_spec.rb +++ b/spec/graphql/resolvers/customers_resolver_spec.rb @@ -7,7 +7,7 @@ <<~GQL query { customers(limit: 5) { - collection { id customerId name } + collection { id externalId name } metadata { currentPage, totalCount } } } diff --git a/spec/graphql/resolvers/events_resolver_spec.rb b/spec/graphql/resolvers/events_resolver_spec.rb index 54e62248185..d3931fb49ba 100644 --- a/spec/graphql/resolvers/events_resolver_spec.rb +++ b/spec/graphql/resolvers/events_resolver_spec.rb @@ -10,7 +10,7 @@ collection { id, code, - customerId, + externalCustomerId, transactionId, timestamp, receivedAt, @@ -58,7 +58,7 @@ expect(events_response['collection'].count).to eq(organization.events.count) expect(events_response['collection'].first['id']).to eq(event.id) expect(events_response['collection'].first['code']).to eq(event.code) - expect(events_response['collection'].first['customerId']).to eq(event.customer.customer_id) + expect(events_response['collection'].first['externalCustomerId']).to eq(event.customer.external_id) expect(events_response['collection'].first['transactionId']).to eq(event.transaction_id) expect(events_response['collection'].first['timestamp']).to eq(event.timestamp.iso8601) expect(events_response['collection'].first['receivedAt']).to eq(event.created_at.iso8601) diff --git a/spec/models/customer_spec.rb b/spec/models/customer_spec.rb index 370f8dcd585..f47eb002c51 100644 --- a/spec/models/customer_spec.rb +++ b/spec/models/customer_spec.rb @@ -9,11 +9,11 @@ subject(:customer) do described_class.new( organization: organization, - customer_id: customer_id, + external_id: external_id, ) end - let(:customer_id) { SecureRandom.uuid } + let(:external_id) { SecureRandom.uuid } it 'validates the country' do expect(customer).to be_valid diff --git a/spec/requests/api/v1/applied_add_ons_spec.rb b/spec/requests/api/v1/applied_add_ons_spec.rb index 5cc494024c4..d497522a0e8 100644 --- a/spec/requests/api/v1/applied_add_ons_spec.rb +++ b/spec/requests/api/v1/applied_add_ons_spec.rb @@ -14,7 +14,7 @@ let(:params) do { - customer_id: customer.customer_id, + external_customer_id: customer.external_id, add_on_code: add_on.code, } end @@ -33,8 +33,8 @@ aggregate_failures do expect(result[:lago_id]).to be_present expect(result[:lago_add_on_id]).to eq(add_on.id) - expect(result[:customer_id]).to eq(customer.customer_id) expect(result[:lago_customer_id]).to eq(customer.id) + expect(result[:external_customer_id]).to eq(customer.external_id) expect(result[:amount_cents]).to eq(add_on.amount_cents) expect(result[:amount_currency]).to eq(add_on.amount_currency) expect(result[:created_at]).to be_present diff --git a/spec/requests/api/v1/applied_coupons_spec.rb b/spec/requests/api/v1/applied_coupons_spec.rb index 54824b76433..810a390232f 100644 --- a/spec/requests/api/v1/applied_coupons_spec.rb +++ b/spec/requests/api/v1/applied_coupons_spec.rb @@ -14,7 +14,7 @@ let(:params) do { - customer_id: customer.customer_id, + external_customer_id: customer.external_id, coupon_code: coupon.code, } end @@ -33,8 +33,8 @@ aggregate_failures do expect(result[:lago_id]).to be_present expect(result[:lago_coupon_id]).to eq(coupon.id) - expect(result[:customer_id]).to eq(customer.customer_id) expect(result[:lago_customer_id]).to eq(customer.id) + expect(result[:external_customer_id]).to eq(customer.external_id) expect(result[:amount_cents]).to eq(coupon.amount_cents) expect(result[:amount_currency]).to eq(coupon.amount_currency) expect(result[:expiration_date]).to be_nil diff --git a/spec/requests/api/v1/customers_spec.rb b/spec/requests/api/v1/customers_spec.rb index 2a43ef4edd7..c915a6a3423 100644 --- a/spec/requests/api/v1/customers_spec.rb +++ b/spec/requests/api/v1/customers_spec.rb @@ -7,7 +7,7 @@ let(:organization) { create(:organization) } let(:create_params) do { - customer_id: SecureRandom.uuid, + external_id: SecureRandom.uuid, name: 'Foo Bar' } end @@ -19,7 +19,7 @@ result = JSON.parse(response.body, symbolize_names: true)[:customer] expect(result[:lago_id]).to be_present - expect(result[:customer_id]).to eq(create_params[:customer_id]) + expect(result[:external_id]).to eq(create_params[:external_id]) expect(result[:name]).to eq(create_params[:name]) expect(result[:created_at]).to be_present end @@ -27,7 +27,7 @@ context 'with billing configuration' do let(:create_params) do { - customer_id: SecureRandom.uuid, + external_id: SecureRandom.uuid, name: 'Foo Bar', billing_configuration: { payment_provider: 'stripe', @@ -43,7 +43,7 @@ result = JSON.parse(response.body, symbolize_names: true)[:customer] expect(result[:lago_id]).to be_present - expect(result[:customer_id]).to eq(create_params[:customer_id]) + expect(result[:external_id]).to eq(create_params[:external_id]) expect(result[:billing_configuration]).to be_present expect(result[:billing_configuration][:payment_provider]).to eq('stripe') @@ -114,7 +114,7 @@ it 'returns the usage for the customer' do get_with_token(organization, - "/api/v1/customers/#{customer.customer_id}/current_usage?subscription_id=#{subscription.id}" + "/api/v1/customers/#{customer.external_id}/current_usage?external_subscription_id=#{subscription.external_id}" ) aggregate_failures do @@ -148,7 +148,7 @@ it 'returns not found' do get_with_token( organization, - "/api/v1/customers/#{customer.customer_id}/current_usage?subscription_id=#{subscription.id}", + "/api/v1/customers/#{customer.external_id}/current_usage?external_subscription_id=#{subscription.external_id}", ) expect(response).to have_http_status(:not_found) diff --git a/spec/requests/api/v1/events_spec.rb b/spec/requests/api/v1/events_spec.rb index b133a517d4d..0402c74386f 100644 --- a/spec/requests/api/v1/events_spec.rb +++ b/spec/requests/api/v1/events_spec.rb @@ -13,7 +13,7 @@ event: { code: 'event_code', transaction_id: SecureRandom.uuid, - customer_id: SecureRandom.uuid, + external_customer_id: SecureRandom.uuid, timestamp: Time.zone.now.to_i, properties: { foo: 'bar', @@ -30,7 +30,7 @@ post_with_token( organization, '/api/v1/events', - event: { customer_id: SecureRandom.uuid }, + event: { external_customer_id: SecureRandom.uuid }, ) expect(response).to have_http_status(:unprocessable_entity) @@ -48,8 +48,8 @@ event: { code: 'event_code', transaction_id: SecureRandom.uuid, - customer_id: SecureRandom.uuid, - subscription_ids: %w[id1 id2], + external_customer_id: SecureRandom.uuid, + external_subscription_ids: %w[id1 id2], timestamp: Time.zone.now.to_i, properties: { foo: 'bar', @@ -69,7 +69,7 @@ event: { code: 'event_code', transaction_id: SecureRandom.uuid, - customer_id: SecureRandom.uuid, + external_customer_id: SecureRandom.uuid, timestamp: Time.zone.now.to_i, properties: { foo: 'bar', diff --git a/spec/requests/api/v1/subscriptions_spec.rb b/spec/requests/api/v1/subscriptions_spec.rb index 951276b9fa4..fbf292458c2 100644 --- a/spec/requests/api/v1/subscriptions_spec.rb +++ b/spec/requests/api/v1/subscriptions_spec.rb @@ -10,7 +10,7 @@ describe 'create' do let(:params) do { - customer_id: customer.customer_id, + external_customer_id: customer.external_id, plan_code: plan.code, name: 'subscription name', external_id: SecureRandom.uuid, @@ -26,7 +26,7 @@ result = JSON.parse(response.body, symbolize_names: true)[:subscription] expect(result[:lago_id]).to be_present - expect(result[:customer_id]).to eq(customer.customer_id) + expect(result[:external_customer_id]).to eq(customer.external_id) expect(result[:lago_customer_id]).to eq(customer.id) expect(result[:plan_code]).to eq(plan.code) expect(result[:status]).to eq('active') @@ -56,7 +56,7 @@ before { subscription } it 'terminates a subscription' do - delete_with_token(organization, "/api/v1/subscriptions/#{subscription.id}") + delete_with_token(organization, "/api/v1/subscriptions/#{subscription.external_id}") expect(response).to have_http_status(:success) @@ -83,7 +83,7 @@ before { subscription } it 'updates a subscription' do - put_with_token(organization, "/api/v1/subscriptions/#{subscription.id}", { subscription: update_params }) + put_with_token(organization, "/api/v1/subscriptions/#{subscription.external_id}", { subscription: update_params }) expect(response).to have_http_status(:success) @@ -108,7 +108,7 @@ before { subscription1 } it 'returns subscriptions' do - get_with_token(organization, "/api/v1/subscriptions?customer_id=#{customer.customer_id}") + get_with_token(organization, "/api/v1/subscriptions?external_customer_id=#{customer.external_id}") expect(response).to have_http_status(:success) @@ -125,7 +125,7 @@ before { subscription2 } it 'returns subscriptions with correct meta data' do - get_with_token(organization, "/api/v1/subscriptions?customer_id=#{customer.customer_id}&page=1&per_page=1") + get_with_token(organization, "/api/v1/subscriptions?external_customer_id=#{customer.external_id}&page=1&per_page=1") expect(response).to have_http_status(:success) @@ -142,7 +142,7 @@ context 'with invalid customer' do it 'returns not_found error' do - get_with_token(organization, '/api/v1/subscriptions?customer_id=invalid') + get_with_token(organization, '/api/v1/subscriptions?external_customer_id=invalid') expect(response).to have_http_status(:not_found) end diff --git a/spec/serializers/v1/payment_providers/customer_error_serializer_spec.rb b/spec/serializers/v1/payment_providers/customer_error_serializer_spec.rb index 9ae817429db..e79ef8b2002 100644 --- a/spec/serializers/v1/payment_providers/customer_error_serializer_spec.rb +++ b/spec/serializers/v1/payment_providers/customer_error_serializer_spec.rb @@ -20,7 +20,7 @@ aggregate_failures do expect(result['data']['lago_customer_id']).to eq(customer.id) - expect(result['data']['customer_id']).to eq(customer.customer_id) + expect(result['data']['external_customer_id']).to eq(customer.external_id) expect(result['data']['payment_provider']).to eq(customer.payment_provider) expect(result['data']['provider_error']).to eq(options[:provider_error]) end diff --git a/spec/serializers/v1/payment_providers/invoice_payment_error_serializer_spec.rb b/spec/serializers/v1/payment_providers/invoice_payment_error_serializer_spec.rb index c93ec23d7d2..c9f50ac5243 100644 --- a/spec/serializers/v1/payment_providers/invoice_payment_error_serializer_spec.rb +++ b/spec/serializers/v1/payment_providers/invoice_payment_error_serializer_spec.rb @@ -22,7 +22,7 @@ aggregate_failures do expect(result['data']['lago_invoice_id']).to eq(invoice.id) expect(result['data']['lago_customer_id']).to eq(invoice.customer.id) - expect(result['data']['customer_id']).to eq(invoice.customer.customer_id) + expect(result['data']['external_customer_id']).to eq(invoice.customer.external_id) expect(result['data']['provider_customer_id']).to eq(options[:provider_customer_id]) expect(result['data']['payment_provider']).to eq(invoice.customer.payment_provider) expect(result['data']['provider_error']).to eq(options[:provider_error]) diff --git a/spec/services/applied_add_ons/create_service_spec.rb b/spec/services/applied_add_ons/create_service_spec.rb index fac25032d86..ee37e2e3992 100644 --- a/spec/services/applied_add_ons/create_service_spec.rb +++ b/spec/services/applied_add_ons/create_service_spec.rb @@ -114,12 +114,12 @@ describe 'create_from_api' do let(:add_on_code) { add_on&.code } - let(:external_customer_id) { customer&.customer_id } + let(:external_customer_id) { customer&.external_id } let(:create_args) do { add_on_code: add_on_code, - customer_id: external_customer_id, + external_customer_id: external_customer_id, amount_cents: amount_cents, amount_currency: amount_currency, } @@ -180,7 +180,7 @@ context 'when customer is not found' do let(:customer) { nil } - let(:customer_id) { 'foo' } + let(:external_customer_id) { 'foo' } it { expect(create_result).not_to be_success } it { expect(create_result.error_code).to eq('missing_argument') } diff --git a/spec/services/applied_coupons/create_service_spec.rb b/spec/services/applied_coupons/create_service_spec.rb index 9e3a40a50e8..040961dae7e 100644 --- a/spec/services/applied_coupons/create_service_spec.rb +++ b/spec/services/applied_coupons/create_service_spec.rb @@ -135,12 +135,12 @@ describe 'create_from_api' do let(:coupon_code) { coupon&.code } - let(:external_customer_id) { customer&.customer_id } + let(:external_customer_id) { customer&.external_id } let(:create_args) do { coupon_code: coupon_code, - customer_id: external_customer_id, + external_customer_id: external_customer_id, amount_cents: amount_cents, amount_currency: amount_currency, } @@ -198,7 +198,7 @@ context 'when customer is not found' do let(:customer) { nil } - let(:customer_id) { 'foo' } + let(:external_customer_id) { 'foo' } it { expect(create_result).not_to be_success } it { expect(create_result.error_code).to eq('missing_argument') } diff --git a/spec/services/customers/create_service_spec.rb b/spec/services/customers/create_service_spec.rb index 2b31f1d5d44..89b06ad0904 100644 --- a/spec/services/customers/create_service_spec.rb +++ b/spec/services/customers/create_service_spec.rb @@ -12,7 +12,7 @@ describe 'create_from_api' do let(:create_args) do { - customer_id: SecureRandom.uuid, + external_id: SecureRandom.uuid, name: 'Foo Bar', } end @@ -32,7 +32,7 @@ customer = result.customer expect(customer.id).to be_present expect(customer.organization_id).to eq(organization.id) - expect(customer.customer_id).to eq(create_args[:customer_id]) + expect(customer.external_id).to eq(create_args[:external_id]) expect(customer.name).to eq(create_args[:name]) end @@ -59,7 +59,7 @@ create( :customer, organization: organization, - customer_id: create_args[:customer_id], + external_id: create_args[:external_id], email: 'foo@bar.com', ) end @@ -74,7 +74,7 @@ expect(result).to be_success expect(result.customer).to eq(customer) expect(result.customer.name).to eq(create_args[:name]) - expect(result.customer.customer_id).to eq(create_args[:customer_id]) + expect(result.customer.external_id).to eq(create_args[:external_id]) # NOTE: It should not erase exsting properties expect(result.customer.country).to eq(customer.country) @@ -113,7 +113,7 @@ context 'with stripe configuration' do let(:create_args) do { - customer_id: SecureRandom.uuid, + external_id: SecureRandom.uuid, name: 'Foo Bar', billing_configuration: { payment_provider: 'stripe', @@ -147,7 +147,7 @@ context 'with unknown payment provider' do let(:create_args) do { - customer_id: SecureRandom.uuid, + external_id: SecureRandom.uuid, name: 'Foo Bar', billing_configuration: { payment_provider: 'foo', @@ -202,7 +202,7 @@ create( :customer, organization: organization, - customer_id: create_args[:customer_id], + external_id: create_args[:external_id], email: 'foo@bar.com', ) end @@ -229,7 +229,7 @@ describe 'create' do let(:create_args) do { - customer_id: SecureRandom.uuid, + external_id: SecureRandom.uuid, name: 'Foo Bar', organization_id: organization.id, } @@ -248,7 +248,7 @@ customer = result.customer expect(customer.id).to be_present expect(customer.organization_id).to eq(organization.id) - expect(customer.customer_id).to eq(create_args[:customer_id]) + expect(customer.external_id).to eq(create_args[:external_id]) expect(customer.name).to eq(create_args[:name]) end end @@ -270,7 +270,7 @@ context 'when customer already exists' do let(:customer) do - create(:customer, organization: organization, customer_id: create_args[:customer_id]) + create(:customer, organization: organization, external_id: create_args[:external_id]) end before { customer } @@ -321,7 +321,7 @@ context 'with provider customer id' do let(:create_args) do { - customer_id: SecureRandom.uuid, + external_id: SecureRandom.uuid, name: 'Foo Bar', organization_id: organization.id, payment_provider: 'stripe', diff --git a/spec/services/customers/update_service_spec.rb b/spec/services/customers/update_service_spec.rb index 738bbd3b52a..487deef5984 100644 --- a/spec/services/customers/update_service_spec.rb +++ b/spec/services/customers/update_service_spec.rb @@ -13,13 +13,13 @@ let(:user) { membership.user } let(:customer) { create(:customer, organization: organization) } - let(:customer_id) { SecureRandom.uuid } + let(:external_id) { SecureRandom.uuid } let(:update_args) do { id: customer.id, name: 'Updated customer name', - customer_id: customer_id, + external_id: external_id, } end @@ -33,7 +33,7 @@ end context 'with validation error' do - let(:customer_id) { nil } + let(:external_id) { nil } it 'returns an error' do result = customers_service.update(**update_args) @@ -54,7 +54,7 @@ updated_customer = result.customer aggregate_failures do expect(updated_customer.name).to eq('Updated customer name') - expect(updated_customer.customer_id).to eq(customer.customer_id) + expect(updated_customer.external_id).to eq(customer.external_id) end end end @@ -64,7 +64,7 @@ { id: customer.id, name: 'Updated customer name', - customer_id: customer_id, + external_id: external_id, payment_provider: 'stripe', } end @@ -85,7 +85,7 @@ let(:update_args) do { id: customer.id, - customer_id: SecureRandom.uuid, + external_id: SecureRandom.uuid, name: 'Foo Bar', organization_id: organization.id, payment_provider: 'stripe', @@ -111,7 +111,7 @@ let(:update_args) do { id: customer.id, - customer_id: SecureRandom.uuid, + external_id: SecureRandom.uuid, name: 'Foo Bar', organization_id: organization.id, payment_provider: nil, diff --git a/spec/services/events/create_batch_service_spec.rb b/spec/services/events/create_batch_service_spec.rb index 83d83585b6e..2bf1747bbfa 100644 --- a/spec/services/events/create_batch_service_spec.rb +++ b/spec/services/events/create_batch_service_spec.rb @@ -6,14 +6,14 @@ subject(:create_batch_service) { described_class.new } let(:organization) { create(:organization) } - let(:billable_metric) { create(:billable_metric, organization: organization) } + let(:billable_metric) { create(:billable_metric, organization: organization) } let(:customer) { create(:customer, organization: organization) } describe '#validate_params' do let(:event_arguments) do { transaction_id: SecureRandom.uuid, - subscription_ids: %w[id1 id2], + external_subscription_ids: %w[id1 id2], code: 'foo', } end @@ -40,7 +40,7 @@ expect(result.error_code).to eq('missing_mandatory_param') expect(result.error_details).to include(:transaction_id) expect(result.error_details).to include(:code) - expect(result.error_details).to include(:subscription_ids) + expect(result.error_details).to include(:external_subscription_ids) end end end @@ -53,7 +53,7 @@ let(:create_args) do { - subscription_ids: [subscription.id, subscription2.id], + external_subscription_ids: [subscription.external_id, subscription2.external_id], code: billable_metric.code, transaction_id: transaction_id, properties: { foo: 'bar' }, diff --git a/spec/services/events/create_service_spec.rb b/spec/services/events/create_service_spec.rb index 5d0f7dfaf8a..e7ac5287c56 100644 --- a/spec/services/events/create_service_spec.rb +++ b/spec/services/events/create_service_spec.rb @@ -13,7 +13,7 @@ let(:params) do { transaction_id: SecureRandom.uuid, - customer_id: SecureRandom.uuid, + external_customer_id: SecureRandom.uuid, code: 'foo', } end @@ -27,7 +27,7 @@ context 'with missing or nil arguments' do let(:params) do { - customer_id: SecureRandom.uuid, + external_customer_id: SecureRandom.uuid, code: nil, } end @@ -45,13 +45,13 @@ end end - context 'when customer_id and subscription_id but multiple subscriptions' do + context 'when external_customer_id and subscription_id but multiple subscriptions' do let(:subscription) { create(:subscription, customer: customer) } let(:params) do { transaction_id: SecureRandom.uuid, - customer_id: customer.customer_id, - subscription_id: subscription.id, + external_customer_id: customer.external_id, + external_subscription_id: subscription.external_id, code: 'code' } end @@ -67,11 +67,11 @@ end end - context 'when only customer_id but multiple subscriptions' do + context 'when only external_customer_id but multiple subscriptions' do let(:params) do { transaction_id: SecureRandom.uuid, - customer_id: customer.customer_id, + external_customer_id: customer.external_id, code: 'code' } end @@ -87,7 +87,7 @@ aggregate_failures do expect(result.error_code).to eq('missing_mandatory_param') - expect(result.error_details).to include(:subscription_id) + expect(result.error_details).to include(:external_subscription_id) end end end @@ -98,7 +98,7 @@ let(:create_args) do { - customer_id: customer.customer_id, + external_customer_id: customer.external_id, code: billable_metric.code, transaction_id: SecureRandom.uuid, properties: { foo: 'bar' }, @@ -137,7 +137,7 @@ { code: billable_metric.code, transaction_id: SecureRandom.uuid, - subscription_id: subscription.id, + external_subscription_id: subscription.external_id, properties: { foo: 'bar' }, timestamp: Time.zone.now.to_i, } @@ -172,7 +172,7 @@ { code: billable_metric.code, transaction_id: SecureRandom.uuid, - subscription_id: subscription2.id, + external_subscription_id: subscription2.external_id, properties: { foo: 'bar' }, timestamp: Time.zone.now.to_i, } @@ -200,10 +200,11 @@ context 'when event already exists' do let(:existing_event) do - create(:event, - organization: organization, - transaction_id: create_args[:transaction_id], - subscription_id: subscription.id + create( + :event, + organization: organization, + transaction_id: create_args[:transaction_id], + subscription_id: subscription.id ) end @@ -224,7 +225,7 @@ context 'when properties are empty' do let(:create_args) do { - customer_id: customer.customer_id, + external_customer_id: customer.external_id, code: billable_metric.code, transaction_id: SecureRandom.uuid, timestamp: Time.zone.now.to_i, diff --git a/spec/services/events/validate_creation_service_spec.rb b/spec/services/events/validate_creation_service_spec.rb index facce76dc36..02ce33377ba 100644 --- a/spec/services/events/validate_creation_service_spec.rb +++ b/spec/services/events/validate_creation_service_spec.rb @@ -18,16 +18,16 @@ let(:customer) { create(:customer, organization: organization) } let(:billable_metric) { create(:billable_metric, organization: organization) } let(:params) do - { customer_id: customer.customer_id, code: billable_metric.code } + { external_customer_id: customer.external_id, code: billable_metric.code } end describe '.call' do let!(:subscription) { create(:active_subscription, customer: customer, organization: organization) } - context "when batch is false" do + context 'when batch is false' do let(:batch) { false } - context 'when customer has only one active subscription and subscription_id is not given' do + context 'when customer has only one active subscription and external_subscription_id is not given' do it 'does not return any validation errors' do expect(validate_event).to be_nil expect(result).to be_success @@ -36,7 +36,7 @@ context 'when customer has only one active subscription and customer is not given' do let(:params) do - { code: billable_metric.code, subscription_id: subscription.id } + { code: billable_metric.code, external_subscription_id: subscription.external_id } end it 'does not return any validation errors' do @@ -49,7 +49,7 @@ before { create(:active_subscription, customer: customer, organization: organization) } let(:params) do - { code: billable_metric.code, subscription_id: subscription.id } + { code: billable_metric.code, external_subscription_id: subscription.external_id } end it 'does not return any validation errors' do @@ -84,7 +84,7 @@ end end - context 'when there are two active subscriptions but subscription_id is not given' do + context 'when there are two active subscriptions but external_subscription_id is not given' do before do create(:active_subscription, customer: customer, organization: organization) end @@ -101,12 +101,12 @@ end end - context 'when there are two active subscriptions but subscription_id is invalid' do + context 'when there are two active subscriptions but external_subscription_id is invalid' do let(:params) do { code: billable_metric.code, - subscription_id: SecureRandom.uuid, - customer_id: customer.customer_id + external_subscription_id: SecureRandom.uuid, + external_customer_id: customer.external_id } end @@ -118,7 +118,7 @@ validate_event expect(result).not_to be_success - expect(result.error).to eq('subscription_id is invalid') + expect(result.error).to eq('external_subscription_id is invalid') end it 'enqueues a SendWebhookJob' do @@ -128,7 +128,7 @@ context 'when code does not exist' do let(:params) do - { customer_id: customer.customer_id, code: 'event_code' } + { external_customer_id: customer.external_id, code: 'event_code' } end it 'returns code does not exist error' do @@ -144,12 +144,12 @@ end end - context "when batch is true" do + context 'when batch is true' do let(:batch) { true } context 'when everything is passing' do let(:params) do - { subscription_ids: [subscription.id], code: billable_metric.code } + { external_subscription_ids: [subscription.external_id], code: billable_metric.code } end it 'does not return any validation errors' do @@ -158,9 +158,9 @@ end end - context 'when subscription_ids is blank' do + context 'when external_subscription_ids is blank' do let(:params) do - { subscription_ids: [] } + { external_subscription_ids: [] } end it 'returns subscription is not given error' do @@ -177,7 +177,7 @@ context 'when customer is not given' do let(:params) do - { code: billable_metric.code, subscription_ids: [SecureRandom.uuid] } + { code: billable_metric.code, external_subscription_ids: [SecureRandom.uuid] } end let(:validate_event) do @@ -206,8 +206,8 @@ let(:params) do { code: billable_metric.code, - subscription_ids: [SecureRandom.uuid], - customer_id: customer.customer_id + external_subscription_ids: [SecureRandom.uuid], + external_customer_id: customer.external_id } end @@ -219,7 +219,7 @@ validate_event expect(result).not_to be_success - expect(result.error).to eq('subscription_id is invalid') + expect(result.error).to eq('external_subscription_id is invalid') end it 'enqueues a SendWebhookJob' do @@ -231,8 +231,8 @@ let(:params) do { code: 'event_code', - subscription_ids: [subscription.id], - customer_id: customer.customer_id + external_subscription_ids: [subscription.external_id], + external_customer_id: customer.external_id } end diff --git a/spec/services/subscriptions/create_service_spec.rb b/spec/services/subscriptions/create_service_spec.rb index 56383806bf4..db7a6d64aea 100644 --- a/spec/services/subscriptions/create_service_spec.rb +++ b/spec/services/subscriptions/create_service_spec.rb @@ -14,7 +14,7 @@ let(:params) do { - customer_id: customer.customer_id, + external_customer_id: customer.external_id, plan_code: plan.code, name: 'invoice display name', external_id: external_id, @@ -48,6 +48,27 @@ end end + it 'calls SegmentTrackJob' do + subscription = create_service.create_from_api( + organization: organization, + params: params, + ).subscription + + expect(SegmentTrackJob).to have_received(:perform_later).with( + membership_id: CurrentContext.membership, + event: 'subscription_created', + properties: { + created_at: subscription.created_at, + customer_id: subscription.customer_id, + plan_code: subscription.plan.code, + plan_name: subscription.plan.name, + subscription_type: 'create', + organization_id: subscription.organization.id, + billing_time: 'anniversary', + }, + ) + end + context 'when external_id is not given' do let(:external_id) { nil } @@ -57,14 +78,14 @@ params: params, ) - expect(result.subscription.external_id).to eq(customer.customer_id) + expect(result.subscription.external_id).to eq(customer.external_id) end end context 'when billing_time is not provided' do let(:params) do { - customer_id: customer.customer_id, + external_customer_id: customer.external_id, plan_code: plan.code, name: 'invoice display name', external_id: external_id, @@ -85,31 +106,10 @@ end end - it 'calls SegmentTrackJob' do - subscription = create_service.create_from_api( - organization: organization, - params: params, - ).subscription - - expect(SegmentTrackJob).to have_received(:perform_later).with( - membership_id: CurrentContext.membership, - event: 'subscription_created', - properties: { - created_at: subscription.created_at, - customer_id: subscription.customer_id, - plan_code: subscription.plan.code, - plan_name: subscription.plan.name, - subscription_type: 'create', - organization_id: subscription.organization.id, - billing_time: 'anniversary', - }, - ) - end - context 'when customer does not exists' do let(:params) do { - customer_id: SecureRandom.uuid, + external_customer_id: SecureRandom.uuid, plan_code: plan.code, external_id: external_id, } @@ -126,7 +126,7 @@ subscription = result.subscription aggregate_failures do - expect(subscription.customer.customer_id).to eq(params[:customer_id]) + expect(subscription.customer.external_id).to eq(params[:external_customer_id]) expect(subscription.plan_id).to eq(plan.id) expect(subscription.started_at).to be_present expect(subscription.subscription_date).to be_present @@ -148,10 +148,10 @@ end end - context 'when customer id is missing' do + context 'when external customer id is missing' do let(:params) do { - customer_id: nil, + external_customer_id: nil, plan_code: plan.code, external_id: external_id, } @@ -168,10 +168,10 @@ end end - context 'when plan doest not exists' do + context 'when plan does not exists' do let(:params) do { - customer_id: customer.customer_id, + external_customer_id: customer.external_id, plan_code: 'invalid_plan', external_id: external_id, } @@ -191,7 +191,7 @@ context 'when billing_time is invalid' do let(:params) do { - customer_id: customer.id, + external_customer_id: customer.id, plan_code: plan.code, external_id: external_id, billing_time: :foo, @@ -216,10 +216,9 @@ context 'when an active subscription already exists' do let(:params) do { - customer_id: customer.customer_id, + external_customer_id: customer.external_id, plan_code: plan.code, name: 'invoice display name', - subscription_id: subscription.id, external_id: external_id, } end @@ -236,22 +235,10 @@ before { subscription } - context 'when subscription_id is given' do - it 'returns existing subscription' do - result = create_service.create_from_api( - organization: organization, - params: params, - ) - - expect(result).to be_success - expect(result.subscription.id).to eq(subscription.id) - end - end - - context 'when external_id is given but not subscription_id' do + context 'when external_id is given' do let(:params) do { - customer_id: customer.customer_id, + external_customer_id: customer.external_id, plan_code: plan.code, name: 'invoice display name', external_id: external_id, @@ -271,17 +258,17 @@ end end - context 'when subscription_id and external_id are not given' do + context 'when external_id is not given' do let(:params) do { - customer_id: customer.customer_id, + external_customer_id: customer.external_id, plan_code: plan.code, name: 'invoice display name', } end it 'returns existing subscription' do - subscription.update!(external_id: customer.customer_id) + subscription.update!(external_id: customer.external_id) result = create_service.create_from_api( organization: organization, @@ -297,7 +284,7 @@ let(:new_plan) { create(:plan, amount_cents: 200, organization: organization, amount_currency: 'USD') } let(:params) do { - customer_id: customer.customer_id, + external_customer_id: customer.external_id, plan_code: new_plan.code, name: 'invoice display name new', external_id: external_id, @@ -320,11 +307,10 @@ let(:higher_plan) { create(:plan, amount_cents: 200, organization: organization) } let(:params) do { - customer_id: customer.customer_id, + external_customer_id: customer.external_id, plan_code: higher_plan.code, name: 'invoice display name new', - subscription_id: subscription.id, - external_id: external_id, + external_id: subscription.external_id, } end @@ -334,6 +320,7 @@ params: params, ) + old_subscription = Subscription.find(subscription.id) expect(old_subscription).to be_terminated @@ -415,11 +402,10 @@ let(:params) do { - customer_id: customer.customer_id, + external_customer_id: customer.external_id, plan_code: lower_plan.code, name: 'invoice display name new', - subscription_id: subscription.id, - external_id: external_id, + external_id: subscription.external_id, } end diff --git a/spec/services/subscriptions/terminate_service_spec.rb b/spec/services/subscriptions/terminate_service_spec.rb index d2645a74304..2d9fe04ba61 100644 --- a/spec/services/subscriptions/terminate_service_spec.rb +++ b/spec/services/subscriptions/terminate_service_spec.rb @@ -66,7 +66,7 @@ it 'terminates a subscription' do result = terminate_service.terminate_from_api( organization: organization, - subscription_id: subscription.id + external_id: subscription.external_id ) aggregate_failures do @@ -78,7 +78,10 @@ it 'enqueues a BillSubscriptionJob' do expect do - terminate_service.terminate(subscription.id) + terminate_service.terminate_from_api( + organization: organization, + external_id: subscription.external_id + ) end.to have_enqueued_job(BillSubscriptionJob) end @@ -86,7 +89,7 @@ it 'returns an error' do result = terminate_service.terminate_from_api( organization: organization, - subscription_id: subscription.id + '123' + external_id: subscription.external_id + '123' ) expect(result.error_code).to eq('not_found') diff --git a/spec/services/subscriptions/update_service_spec.rb b/spec/services/subscriptions/update_service_spec.rb index 76fa5eafa74..3bb44ec3024 100644 --- a/spec/services/subscriptions/update_service_spec.rb +++ b/spec/services/subscriptions/update_service_spec.rb @@ -61,7 +61,7 @@ it 'updates the subscription' do result = update_service.update_from_api( organization: organization, - id: subscription.id, + external_id: subscription.external_id, params: update_args ) @@ -72,11 +72,11 @@ end end - context 'with invalid id' do + context 'with invalid external_id' do it 'returns an error' do result = update_service.update_from_api( organization: organization, - id: subscription.id + '123', + external_id: subscription.external_id + '123', params: update_args ) diff --git a/spec/services/webhooks/event_service_spec.rb b/spec/services/webhooks/event_service_spec.rb index 45df5f6fd55..7ce7d9100a6 100644 --- a/spec/services/webhooks/event_service_spec.rb +++ b/spec/services/webhooks/event_service_spec.rb @@ -10,7 +10,7 @@ let(:object) do { input_params: { - customer_id: 'customer', + external_customer_id: 'customer', transaction_id: SecureRandom.uuid, code: 'code' }, From 58c051e083f749a34d167b083167e564e6227a97 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Romain=20Semp=C3=A9?= Date: Wed, 31 Aug 2022 10:50:52 +0200 Subject: [PATCH 3/9] misc: Add index for external_id on subscriptions --- app/services/payment_provider_customers/create_service.rb | 2 +- ...23145421_rename_unique_id_to_external_id_on_subscriptions.rb | 1 + db/schema.rb | 1 + 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/app/services/payment_provider_customers/create_service.rb b/app/services/payment_provider_customers/create_service.rb index 2b9a5a799c9..7f6ae441a11 100644 --- a/app/services/payment_provider_customers/create_service.rb +++ b/app/services/payment_provider_customers/create_service.rb @@ -10,7 +10,7 @@ def initialize(customer) def create_or_update(customer_class:, payment_provider_id:, params:, async: true) provider_customer = customer_class.find_or_initialize_by( - customer_id: customer.id, # TODO: Why? + customer_id: customer.id, payment_provider_id: payment_provider_id, ) diff --git a/db/migrate/20220823145421_rename_unique_id_to_external_id_on_subscriptions.rb b/db/migrate/20220823145421_rename_unique_id_to_external_id_on_subscriptions.rb index b8117802d9c..497502ce8d6 100644 --- a/db/migrate/20220823145421_rename_unique_id_to_external_id_on_subscriptions.rb +++ b/db/migrate/20220823145421_rename_unique_id_to_external_id_on_subscriptions.rb @@ -1,5 +1,6 @@ class RenameUniqueIdToExternalIdOnSubscriptions < ActiveRecord::Migration[7.0] def change rename_column :subscriptions, :unique_id, :external_id + add_index :subscriptions, :external_id end end diff --git a/db/schema.rb b/db/schema.rb index ee7d0680210..935c534f89d 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -349,6 +349,7 @@ t.string "external_id", null: false t.integer "billing_time", default: 0, null: false t.index ["customer_id"], name: "index_subscriptions_on_customer_id" + t.index ["external_id"], name: "index_subscriptions_on_external_id" t.index ["plan_id"], name: "index_subscriptions_on_plan_id" end From 70a38f5502d861bad2e9bcd4e2baf2b10c7742b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Romain=20Semp=C3=A9?= Date: Wed, 31 Aug 2022 17:27:31 +0200 Subject: [PATCH 4/9] misc: Rename customer_id to external_customer_id on wallets --- app/controllers/api/v1/wallets_controller.rb | 4 ++-- spec/requests/api/v1/wallets_spec.rb | 6 +++--- spec/services/wallet_transactions/validate_service_spec.rb | 2 +- spec/services/wallets/create_service_spec.rb | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/app/controllers/api/v1/wallets_controller.rb b/app/controllers/api/v1/wallets_controller.rb index 52ae6af997b..5fe7bdbe018 100644 --- a/app/controllers/api/v1/wallets_controller.rb +++ b/app/controllers/api/v1/wallets_controller.rb @@ -57,7 +57,7 @@ def show end def index - customer = Customer.find_by(customer_id: params[:external_customer_id]) + customer = Customer.find_by(external_id: params[:external_customer_id]) return not_found_error unless customer @@ -99,7 +99,7 @@ def update_params end def customer - Customer.find_by(customer_id: customer_params[:external_customer_id], organization_id: current_organization.id) + Customer.find_by(external_id: customer_params[:external_customer_id], organization_id: current_organization.id) end def render_wallet(wallet) diff --git a/spec/requests/api/v1/wallets_spec.rb b/spec/requests/api/v1/wallets_spec.rb index 5a3eba4cb89..906fe476461 100644 --- a/spec/requests/api/v1/wallets_spec.rb +++ b/spec/requests/api/v1/wallets_spec.rb @@ -12,7 +12,7 @@ describe 'create' do let(:create_params) do { - external_customer_id: customer.customer_id, + external_customer_id: customer.external_id, rate_amount: '1', name: 'Wallet1', paid_credits: '10', @@ -135,7 +135,7 @@ before { wallet } it 'returns wallets' do - get_with_token(organization, "/api/v1/wallets?external_customer_id=#{customer.customer_id}") + get_with_token(organization, "/api/v1/wallets?external_customer_id=#{customer.external_id}") expect(response).to have_http_status(:success) @@ -152,7 +152,7 @@ before { wallet2 } it 'returns wallets with correct meta data' do - get_with_token(organization, "/api/v1/wallets?external_customer_id=#{customer.customer_id}&page=1&per_page=1") + get_with_token(organization, "/api/v1/wallets?external_customer_id=#{customer.external_id}&page=1&per_page=1") expect(response).to have_http_status(:success) diff --git a/spec/services/wallet_transactions/validate_service_spec.rb b/spec/services/wallet_transactions/validate_service_spec.rb index 3f03a6f4b9b..3b5afc498d2 100644 --- a/spec/services/wallet_transactions/validate_service_spec.rb +++ b/spec/services/wallet_transactions/validate_service_spec.rb @@ -17,7 +17,7 @@ let(:args) do { wallet_id: wallet_id, - customer_id: customer.customer_id, + customer_id: customer.external_id, organization_id: organization.id, paid_credits: paid_credits, granted_credits: granted_credits, diff --git a/spec/services/wallets/create_service_spec.rb b/spec/services/wallets/create_service_spec.rb index b401a78514a..d489012e255 100644 --- a/spec/services/wallets/create_service_spec.rb +++ b/spec/services/wallets/create_service_spec.rb @@ -7,7 +7,7 @@ let(:membership) { create(:membership) } let(:organization) { membership.organization } - let(:customer) { create(:customer, organization: organization, customer_id: 'foobar') } + let(:customer) { create(:customer, organization: organization, external_id: 'foobar') } let(:subscription) { create(:subscription, customer: customer) } before { subscription } From e21bb602686b15e7bb621d25d3219c4af7ab38a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Romain=20Semp=C3=A9?= Date: Thu, 1 Sep 2022 11:36:56 +0200 Subject: [PATCH 5/9] misc: Add external_customer_id on wallet response --- app/serializers/v1/wallet_serializer.rb | 2 +- spec/requests/api/v1/wallets_spec.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/serializers/v1/wallet_serializer.rb b/app/serializers/v1/wallet_serializer.rb index 7052b6aeb53..c19711b8bcb 100644 --- a/app/serializers/v1/wallet_serializer.rb +++ b/app/serializers/v1/wallet_serializer.rb @@ -6,7 +6,7 @@ def serialize { lago_id: model.id, lago_customer_id: model.customer_id, - external_customer_id: model.customer.customer_id, + external_customer_id: model.customer.external_id, status: model.status, currency: model.currency, name: model.name, diff --git a/spec/requests/api/v1/wallets_spec.rb b/spec/requests/api/v1/wallets_spec.rb index 906fe476461..340763b7cd0 100644 --- a/spec/requests/api/v1/wallets_spec.rb +++ b/spec/requests/api/v1/wallets_spec.rb @@ -29,7 +29,7 @@ result = JSON.parse(response.body, symbolize_names: true)[:wallet] expect(result[:lago_id]).to be_present expect(result[:name]).to eq(create_params[:name]) - expect(result[:external_customer_id]).to eq(customer.customer_id) + expect(result[:external_customer_id]).to eq(customer.external_id) end end From b410891652d2c2ecc48deae525b9360619da5f28 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Romain=20Semp=C3=A9?= Date: Thu, 1 Sep 2022 11:54:12 +0200 Subject: [PATCH 6/9] misc: Put external id as mandatory on subscriptions from API --- app/models/subscription.rb | 3 +- app/services/subscriptions/create_service.rb | 14 +++------ spec/models/subscription_spec.rb | 18 ++++++++++-- spec/requests/api/v1/subscriptions_spec.rb | 1 + .../subscriptions/create_service_spec.rb | 29 +++---------------- 5 files changed, 27 insertions(+), 38 deletions(-) diff --git a/app/models/subscription.rb b/app/models/subscription.rb index 286b4454c9d..4b0bb8a3d1e 100644 --- a/app/models/subscription.rb +++ b/app/models/subscription.rb @@ -74,7 +74,8 @@ def already_billed? def validate_external_id return unless active? - used_ids = customer&.active_subscriptions&.pluck(:external_id) + # NOTE: We want unique external id per organization. + used_ids = organization.subscriptions.active.pluck(:external_id) errors.add(:external_id, :value_already_exists) if used_ids&.include?(external_id) end end diff --git a/app/services/subscriptions/create_service.rb b/app/services/subscriptions/create_service.rb index debbe5be66a..971bd3ac9c9 100644 --- a/app/services/subscriptions/create_service.rb +++ b/app/services/subscriptions/create_service.rb @@ -20,7 +20,7 @@ def create_from_api(organization:, params:) @name = params[:name]&.strip @external_id = params[:external_id]&.strip @billing_time = params[:billing_time] - @current_subscription = find_current_subscription + @current_subscription = active_subscriptions&.find_by(external_id: external_id) process_create rescue ActiveRecord::RecordInvalid => e @@ -42,7 +42,8 @@ def create(**args) @name = args[:name]&.strip @external_id = SecureRandom.uuid @billing_time = args[:billing_time] - @current_subscription = find_current_subscription(subscription_id: args[:subscription_id]) + @current_subscription = active_subscriptions&.find_by(id: args[:subscription_id]) + process_create end @@ -96,7 +97,7 @@ def create_subscription plan_id: current_plan.id, subscription_date: Time.zone.now.to_date, name: name, - external_id: external_id || current_customer.external_id, + external_id: external_id, billing_time: billing_time || :calendar, ) new_subscription.mark_as_active! @@ -211,12 +212,5 @@ def currency_missmatch?(old_plan, new_plan) def active_subscriptions @active_subscriptions ||= current_customer&.active_subscriptions end - - def find_current_subscription(subscription_id: nil) - return active_subscriptions&.find_by(id: subscription_id) if subscription_id - return active_subscriptions&.find_by(external_id: external_id) if external_id - - active_subscriptions&.find_by(external_id: current_customer.external_id) - end end end diff --git a/spec/models/subscription_spec.rb b/spec/models/subscription_spec.rb index a05b8e60c67..bed8a235211 100644 --- a/spec/models/subscription_spec.rb +++ b/spec/models/subscription_spec.rb @@ -120,8 +120,22 @@ let(:customer) { create(:customer, organization: organization) } let(:plan) { create(:plan) } let(:external_id) { SecureRandom.uuid } - let(:subscription) { create(:active_subscription, plan: plan, customer: customer) } - let(:new_subscription) { build(:active_subscription, plan: plan, external_id: external_id, customer: customer) } + let(:subscription) do + create( + :active_subscription, + plan: plan, + customer: create(:customer, organization: organization) + ) + end + + let(:new_subscription) do + build( + :active_subscription, + plan: plan, + external_id: external_id, + customer: create(:customer, organization: organization) + ) + end before { subscription } diff --git a/spec/requests/api/v1/subscriptions_spec.rb b/spec/requests/api/v1/subscriptions_spec.rb index fbf292458c2..cc1686a42ee 100644 --- a/spec/requests/api/v1/subscriptions_spec.rb +++ b/spec/requests/api/v1/subscriptions_spec.rb @@ -26,6 +26,7 @@ result = JSON.parse(response.body, symbolize_names: true)[:subscription] expect(result[:lago_id]).to be_present + expect(result[:external_id]).to be_present expect(result[:external_customer_id]).to eq(customer.external_id) expect(result[:lago_customer_id]).to eq(customer.id) expect(result[:plan_code]).to eq(plan.code) diff --git a/spec/services/subscriptions/create_service_spec.rb b/spec/services/subscriptions/create_service_spec.rb index db7a6d64aea..6c87c11a20a 100644 --- a/spec/services/subscriptions/create_service_spec.rb +++ b/spec/services/subscriptions/create_service_spec.rb @@ -43,7 +43,7 @@ expect(subscription.subscription_date).to be_present expect(subscription.name).to eq('invoice display name') expect(subscription).to be_active - expect(subscription.external_id).to be_present + expect(subscription.external_id).to eq(external_id) expect(subscription).to be_anniversary end end @@ -72,13 +72,14 @@ context 'when external_id is not given' do let(:external_id) { nil } - it 'sets customer_id as external_id' do + it 'returns an error' do result = create_service.create_from_api( organization: organization, params: params, ) - expect(result.subscription.external_id).to eq(customer.external_id) + expect(result).not_to be_success + expect(result.error_details[:external_id]).to eq(['value_is_mandatory']) end end @@ -258,28 +259,6 @@ end end - context 'when external_id is not given' do - let(:params) do - { - external_customer_id: customer.external_id, - plan_code: plan.code, - name: 'invoice display name', - } - end - - it 'returns existing subscription' do - subscription.update!(external_id: customer.external_id) - - result = create_service.create_from_api( - organization: organization, - params: params, - ) - - expect(result).to be_success - expect(result.subscription.id).to eq(subscription.id) - end - end - context 'when new plan has different currency than the old plan' do let(:new_plan) { create(:plan, amount_cents: 200, organization: organization, amount_currency: 'USD') } let(:params) do From bfe089c5d524f9f246a2e0d47851bec6385683c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Romain=20Semp=C3=A9?= Date: Fri, 2 Sep 2022 09:46:32 +0200 Subject: [PATCH 7/9] misc: Use external_subscription_id on GraphQL event type --- app/graphql/types/events/object.rb | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/app/graphql/types/events/object.rb b/app/graphql/types/events/object.rb index b2dc152515e..51e8df34adf 100644 --- a/app/graphql/types/events/object.rb +++ b/app/graphql/types/events/object.rb @@ -7,7 +7,7 @@ class Object < Types::BaseObject field :code, String, null: false field :external_customer_id, String, null: false - field :subscription_id, String, null: false + field :external_subscription_id, String, null: false field :transaction_id, String, null: true field :timestamp, GraphQL::Types::ISO8601DateTime, null: true @@ -29,12 +29,16 @@ def external_customer_id object.customer.external_id end + def external_subscription_id + object.subscription.external_id + end + def payload { event: { transaction_id: object.transaction_id, external_customer_id: object.customer.external_id, - subscription_id: object.subscription_id, + external_subscription_id: object.subscription.external_id, code: object.code, timestamp: object.timestamp.to_i, properties: object.properties || {}, From 7269e8d179ea253be1fa6f890187224411b8b860 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Romain=20Semp=C3=A9?= Date: Fri, 2 Sep 2022 09:50:04 +0200 Subject: [PATCH 8/9] misc: Add external_id on GraphQL subscription type --- app/graphql/types/subscriptions/object.rb | 1 + schema.graphql | 3 +- schema.json | 54 +++++++++++++++-------- 3 files changed, 39 insertions(+), 19 deletions(-) diff --git a/app/graphql/types/subscriptions/object.rb b/app/graphql/types/subscriptions/object.rb index f32efe360de..4060cdbb2ba 100644 --- a/app/graphql/types/subscriptions/object.rb +++ b/app/graphql/types/subscriptions/object.rb @@ -6,6 +6,7 @@ class Object < Types::BaseObject graphql_name 'Subscription' field :id, ID, null: false + field :external_id, String, null: false field :customer, Types::Customers::Object, null: false field :plan, Types::Plans::Object, null: false diff --git a/schema.graphql b/schema.graphql index 307241e227d..ad0d096d3f9 100644 --- a/schema.graphql +++ b/schema.graphql @@ -2621,13 +2621,13 @@ type Event { billableMetricName: String code: String! externalCustomerId: String! + externalSubscriptionId: String! id: ID! ipAddress: String matchBillableMetric: Boolean! matchCustomField: Boolean! payload: JSON! receivedAt: ISO8601DateTime! - subscriptionId: String! timestamp: ISO8601DateTime transactionId: String } @@ -3394,6 +3394,7 @@ type Subscription { canceledAt: ISO8601DateTime createdAt: ISO8601DateTime! customer: Customer! + externalId: String! id: ID! name: String nextName: String diff --git a/schema.json b/schema.json index 59700629dfb..175b7fe6865 100644 --- a/schema.json +++ b/schema.json @@ -7844,6 +7844,24 @@ ] }, + { + "name": "externalSubscriptionId", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null, + "args": [ + + ] + }, { "name": "id", "description": null, @@ -7948,24 +7966,6 @@ ] }, - { - "name": "subscriptionId", - "description": null, - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "String", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null, - "args": [ - - ] - }, { "name": "timestamp", "description": null, @@ -12093,6 +12093,24 @@ ] }, + { + "name": "externalId", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null, + "args": [ + + ] + }, { "name": "id", "description": null, From 7a0be052c3383cbc8546ec21bd8a34866e4d1fcd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Romain=20Semp=C3=A9?= Date: Mon, 5 Sep 2022 17:16:59 +0200 Subject: [PATCH 9/9] misc: Use external_id for persisted events --- .../billable_metrics/aggregations/recurring_count_service.rb | 2 +- .../aggregations/recurring_count_service_spec.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/services/billable_metrics/aggregations/recurring_count_service.rb b/app/services/billable_metrics/aggregations/recurring_count_service.rb index 38b285f5490..31a819dfa51 100644 --- a/app/services/billable_metrics/aggregations/recurring_count_service.rb +++ b/app/services/billable_metrics/aggregations/recurring_count_service.rb @@ -54,7 +54,7 @@ def base_scope PersistedEvent .where(billable_metric_id: billable_metric.id) .where(customer_id: subscription.customer_id) - .where(external_subscription_id: subscription.unique_id) + .where(external_subscription_id: subscription.external_id) end # NOTE: Full period duration to take upgrade, terminate diff --git a/spec/services/billable_metrics/aggregations/recurring_count_service_spec.rb b/spec/services/billable_metrics/aggregations/recurring_count_service_spec.rb index 8ecdb439b8a..734b5e498db 100644 --- a/spec/services/billable_metrics/aggregations/recurring_count_service_spec.rb +++ b/spec/services/billable_metrics/aggregations/recurring_count_service_spec.rb @@ -43,7 +43,7 @@ customer: customer, added_at: added_at, removed_at: removed_at, - external_subscription_id: subscription.unique_id, + external_subscription_id: subscription.external_id, billable_metric: billable_metric, ) end