diff --git a/app/controllers/api/v1/customers/payment_methods_controller.rb b/app/controllers/api/v1/customers/payment_methods_controller.rb index ab70e326f9c..ed8d4389143 100644 --- a/app/controllers/api/v1/customers/payment_methods_controller.rb +++ b/app/controllers/api/v1/customers/payment_methods_controller.rb @@ -10,11 +10,32 @@ def index payment_method_index(external_customer_id: customer.external_id) end + def set_as_default + payment_method = customer.payment_methods.find_by(id: params[:id]) + return not_found_error(resource: "payment_method") unless payment_method + + result = PaymentMethods::SetAsDefaultService.call(payment_method:) + if result.success? + render_payment_method(result.payment_method) + else + render_error_response(result) + end + end + private def resource_name "payment_method" end + + def render_payment_method(payment_method) + render( + json: ::V1::PaymentMethodSerializer.new( + payment_method, + root_name: "payment_method" + ) + ) + end end end end diff --git a/config/routes.rb b/config/routes.rb index 7f4c29ec8d8..37af58cbbcf 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -43,10 +43,12 @@ resources :credit_notes, only: %i[index] resources :invoices, only: %i[index] resources :payments, only: %i[index] - resources :payment_methods, only: %i[index] resources :payment_requests, only: %i[index] resources :subscriptions, only: %i[index] resources :wallets, only: %i[index] + resources :payment_methods, only: %i[index] do + put :set_as_default, on: :member + end end end diff --git a/spec/requests/api/v1/customers/payment_methods_controller_spec.rb b/spec/requests/api/v1/customers/payment_methods_controller_spec.rb index 4066afe1fc9..69f1549080f 100644 --- a/spec/requests/api/v1/customers/payment_methods_controller_spec.rb +++ b/spec/requests/api/v1/customers/payment_methods_controller_spec.rb @@ -3,13 +3,14 @@ require "rails_helper" RSpec.describe Api::V1::Customers::PaymentMethodsController, type: :request do + let(:customer) { create(:customer, organization:) } + let(:organization) { create(:organization) } + let(:external_id) { customer.external_id } + let(:payment_method) { create(:payment_method, customer:, organization:) } + describe "GET /api/v1/customers/:external_id/payment_methods" do subject { get_with_token(organization, "/api/v1/customers/#{external_id}/payment_methods", {}) } - let(:customer) { create(:customer, organization:) } - let(:organization) { create(:organization) } - let(:external_id) { customer.external_id } - let(:payment_method) { create(:payment_method, customer:, organization:) } let(:second_payment_method) { create(:payment_method, organization:, customer:, is_default: false) } include_examples "requires API permission", "payment_method", "read" @@ -54,4 +55,78 @@ end end end + + describe "PUT /api/v1/customers/:external_id/payment_methods/:id/set_as_default" do + subject { put_with_token(organization, "/api/v1/customers/#{external_id}/payment_methods/#{payment_method.id}/set_as_default") } + + include_examples "requires API permission", "payment_method", "write" + + context "with unknown customer" do + let(:external_id) { SecureRandom.uuid } + + it "returns a not found error" do + subject + + expect(response).to have_http_status(:not_found) + expect(json[:code]).to eq("customer_not_found") + end + end + + context "with unknown payment method" do + subject { put_with_token(organization, "/api/v1/customers/#{external_id}/payment_methods/invalid/set_as_default") } + + it "returns a not found error" do + subject + + expect(response).to have_http_status(:not_found) + expect(json[:code]).to eq("payment_method_not_found") + end + end + + context "when payment method is already default" do + let(:payment_method) { create(:payment_method, customer:, organization:, is_default: true) } + let(:payment_method2) { create(:payment_method, customer:, organization:, is_default: false) } + let(:payment_method3) { create(:payment_method, customer:, organization:, is_default: false) } + + before do + payment_method + payment_method2 + payment_method3 + end + + it "returns valid payment method" do + subject + + expect(response).to have_http_status(:success) + expect(json[:payment_method][:lago_id]).to eq(payment_method.id) + expect(json[:payment_method][:is_default]).to eq(true) + expect(payment_method.reload.is_default).to eq(true) + expect(payment_method2.reload.is_default).to eq(false) + expect(payment_method2.reload.is_default).to eq(false) + end + end + + context "when payment method is not default" do + let(:payment_method) { create(:payment_method, customer:, organization:, is_default: false) } + let(:payment_method2) { create(:payment_method, customer:, organization:, is_default: true) } + let(:payment_method3) { create(:payment_method, customer:, organization:, is_default: false) } + + before do + payment_method + payment_method2 + payment_method3 + end + + it "sets payment method to default and returns valid payment method" do + subject + + expect(response).to have_http_status(:success) + expect(json[:payment_method][:lago_id]).to eq(payment_method.id) + expect(json[:payment_method][:is_default]).to eq(true) + expect(payment_method.reload.is_default).to eq(true) + expect(payment_method2.reload.is_default).to eq(false) + expect(payment_method2.reload.is_default).to eq(false) + end + end + end end