diff --git a/api/.rspec b/api/.rspec new file mode 100644 index 000000000..cad23e794 --- /dev/null +++ b/api/.rspec @@ -0,0 +1,3 @@ +--color +--backtrace +--require spec_helper diff --git a/api/app/controllers/mno_enterprise/jpi/v1/admin/organizations_controller.rb b/api/app/controllers/mno_enterprise/jpi/v1/admin/organizations_controller.rb index fe9ae1da8..18b3b619b 100644 --- a/api/app/controllers/mno_enterprise/jpi/v1/admin/organizations_controller.rb +++ b/api/app/controllers/mno_enterprise/jpi/v1/admin/organizations_controller.rb @@ -7,7 +7,7 @@ class Jpi::V1::Admin::OrganizationsController < Jpi::V1::Admin::BaseResourceCont :geo_country_code, :geo_state_code, :geo_city, :geo_tz, :geo_currency, :metadata, :industry, :size, :financial_year_end_month, :credit_card, - :financial_metrics, :created_at] + :financial_metrics, :created_at, :external_id] # GET /mnoe/jpi/v1/admin/organizations def index if params[:terms] diff --git a/api/app/controllers/mno_enterprise/jpi/v1/admin/subscription_events_controller.rb b/api/app/controllers/mno_enterprise/jpi/v1/admin/subscription_events_controller.rb new file mode 100644 index 000000000..87cffe255 --- /dev/null +++ b/api/app/controllers/mno_enterprise/jpi/v1/admin/subscription_events_controller.rb @@ -0,0 +1,5 @@ +module MnoEnterprise + class Jpi::V1::Admin::SubscriptionEventsController < Jpi::V1::Admin::BaseResourceController + include MnoEnterprise::Concerns::Controllers::Jpi::V1::Admin::SubscriptionEventsController + end +end diff --git a/api/app/controllers/mno_enterprise/jpi/v1/subscription_events_controller.rb b/api/app/controllers/mno_enterprise/jpi/v1/subscription_events_controller.rb new file mode 100644 index 000000000..a8b2c89a2 --- /dev/null +++ b/api/app/controllers/mno_enterprise/jpi/v1/subscription_events_controller.rb @@ -0,0 +1,5 @@ +module MnoEnterprise + class Jpi::V1::SubscriptionEventsController < Jpi::V1::BaseResourceController + include MnoEnterprise::Concerns::Controllers::Jpi::V1::SubscriptionEventsController + end +end diff --git a/api/app/views/mno_enterprise/jpi/v1/admin/organizations/_organization.json.jbuilder b/api/app/views/mno_enterprise/jpi/v1/admin/organizations/_organization.json.jbuilder index 05397d30e..656210906 100644 --- a/api/app/views/mno_enterprise/jpi/v1/admin/organizations/_organization.json.jbuilder +++ b/api/app/views/mno_enterprise/jpi/v1/admin/organizations/_organization.json.jbuilder @@ -1 +1 @@ -json.extract! organization, :id, :name, :uid, :soa_enabled, :created_at, :account_frozen, :financial_metrics, :billing_currency +json.extract! organization, :id, :name, :uid, :soa_enabled, :created_at, :account_frozen, :financial_metrics, :billing_currency, :external_id diff --git a/api/app/views/mno_enterprise/jpi/v1/admin/subscription_events/_subscription_event.json.jbuilder b/api/app/views/mno_enterprise/jpi/v1/admin/subscription_events/_subscription_event.json.jbuilder new file mode 100644 index 000000000..8f9d41a00 --- /dev/null +++ b/api/app/views/mno_enterprise/jpi/v1/admin/subscription_events/_subscription_event.json.jbuilder @@ -0,0 +1,7 @@ +json.id subscription_event.id +json.event_type subscription_event.event_type +json.status subscription_event.status +json.message subscription_event.message +json.provisioning_data subscription_event.provisioning_data +json.created_at subscription_event.created_at +json.updated_at subscription_event.updated_at diff --git a/api/app/views/mno_enterprise/jpi/v1/admin/subscription_events/index.json.jbuilder b/api/app/views/mno_enterprise/jpi/v1/admin/subscription_events/index.json.jbuilder new file mode 100644 index 000000000..389802eb5 --- /dev/null +++ b/api/app/views/mno_enterprise/jpi/v1/admin/subscription_events/index.json.jbuilder @@ -0,0 +1 @@ +json.subscription_events @subscription_events, partial: 'subscription_event', as: :subscription_event diff --git a/api/app/views/mno_enterprise/jpi/v1/admin/subscription_events/show.json.jbuilder b/api/app/views/mno_enterprise/jpi/v1/admin/subscription_events/show.json.jbuilder new file mode 100644 index 000000000..62b9781e2 --- /dev/null +++ b/api/app/views/mno_enterprise/jpi/v1/admin/subscription_events/show.json.jbuilder @@ -0,0 +1,3 @@ +json.subscription_event do + json.partial! 'subscription_event', subscription_event: @subscription_event +end diff --git a/api/app/views/mno_enterprise/jpi/v1/admin/subscriptions/_subscription.json.jbuilder b/api/app/views/mno_enterprise/jpi/v1/admin/subscriptions/_subscription.json.jbuilder index 65e40d7f9..2b6b2aafc 100644 --- a/api/app/views/mno_enterprise/jpi/v1/admin/subscriptions/_subscription.json.jbuilder +++ b/api/app/views/mno_enterprise/jpi/v1/admin/subscriptions/_subscription.json.jbuilder @@ -3,6 +3,7 @@ json.status subscription.status json.subscription_type subscription.subscription_type json.start_date subscription.start_date json.end_date subscription.end_date +json.currency subscription.currency json.max_licenses subscription.max_licenses json.available_licenses subscription.available_licenses json.external_id subscription.external_id diff --git a/api/app/views/mno_enterprise/jpi/v1/subscription_events/_subscription_event.json.jbuilder b/api/app/views/mno_enterprise/jpi/v1/subscription_events/_subscription_event.json.jbuilder new file mode 100644 index 000000000..8f9d41a00 --- /dev/null +++ b/api/app/views/mno_enterprise/jpi/v1/subscription_events/_subscription_event.json.jbuilder @@ -0,0 +1,7 @@ +json.id subscription_event.id +json.event_type subscription_event.event_type +json.status subscription_event.status +json.message subscription_event.message +json.provisioning_data subscription_event.provisioning_data +json.created_at subscription_event.created_at +json.updated_at subscription_event.updated_at diff --git a/api/app/views/mno_enterprise/jpi/v1/subscription_events/index.json.jbuilder b/api/app/views/mno_enterprise/jpi/v1/subscription_events/index.json.jbuilder new file mode 100644 index 000000000..389802eb5 --- /dev/null +++ b/api/app/views/mno_enterprise/jpi/v1/subscription_events/index.json.jbuilder @@ -0,0 +1 @@ +json.subscription_events @subscription_events, partial: 'subscription_event', as: :subscription_event diff --git a/api/app/views/mno_enterprise/jpi/v1/subscription_events/show.json.jbuilder b/api/app/views/mno_enterprise/jpi/v1/subscription_events/show.json.jbuilder new file mode 100644 index 000000000..62b9781e2 --- /dev/null +++ b/api/app/views/mno_enterprise/jpi/v1/subscription_events/show.json.jbuilder @@ -0,0 +1,3 @@ +json.subscription_event do + json.partial! 'subscription_event', subscription_event: @subscription_event +end diff --git a/api/app/views/mno_enterprise/jpi/v1/subscriptions/_subscription.json.jbuilder b/api/app/views/mno_enterprise/jpi/v1/subscriptions/_subscription.json.jbuilder index 7da1e2f9a..ef67be70a 100644 --- a/api/app/views/mno_enterprise/jpi/v1/subscriptions/_subscription.json.jbuilder +++ b/api/app/views/mno_enterprise/jpi/v1/subscriptions/_subscription.json.jbuilder @@ -3,6 +3,7 @@ json.status subscription.status json.subscription_type subscription.subscription_type json.start_date subscription.start_date json.end_date subscription.end_date +json.currency subscription.currency json.max_licenses subscription.max_licenses json.available_licenses subscription.available_licenses json.external_id subscription.external_id diff --git a/api/config/routes.rb b/api/config/routes.rb index 6d1c41165..832dcd30d 100644 --- a/api/config/routes.rb +++ b/api/config/routes.rb @@ -154,6 +154,8 @@ member do post :cancel end + + resources :subscription_events, only: [:index, :show] end end end @@ -258,6 +260,8 @@ post :approve post :fulfill end + + resources :subscription_events, only: [:index, :show] end end end diff --git a/api/lib/mno_enterprise/concerns/controllers/jpi/v1/admin/subscription_events_controller.rb b/api/lib/mno_enterprise/concerns/controllers/jpi/v1/admin/subscription_events_controller.rb new file mode 100644 index 000000000..922643834 --- /dev/null +++ b/api/lib/mno_enterprise/concerns/controllers/jpi/v1/admin/subscription_events_controller.rb @@ -0,0 +1,39 @@ +module MnoEnterprise::Concerns::Controllers::Jpi::V1::Admin::SubscriptionEventsController + extend ActiveSupport::Concern + + SUBSCRIPTION_EVENT_INCLUDES ||= [:'subscription'] + + #================================================================== + # Instance methods + #================================================================== + # GET /mnoe/jpi/v1/admin/organizations/1/subscriptions/xyz/subscription_events + def index + query = fetch_subscription_events(params[:organization_id], params[:subscription_id]) + @subscription_events = query.to_a + response.headers['X-Total-Count'] = query.meta.record_count + end + + # GET /mnoe/jpi/v1/admin/organizations/1/subscriptions/xyz/subscription_events/id + def show + @subscription_event = fetch_subscription_event(params[:organization_id], params[:subscription_id], params[:id], SUBSCRIPTION_EVENT_INCLUDES) + return render_not_found('SubscriptionEvent') unless @subscription_event + end + + protected + + def fetch_subscription_events(organization_id, subscription_id) + MnoEnterprise::SubscriptionEvent + .apply_query_params(params) + .with_params(_metadata: { act_as_manager: current_user.id, organization_id: organization_id }) + .includes(SUBSCRIPTION_EVENT_INCLUDES) + .where('subscription.id' => subscription_id) + end + + def fetch_subscription_event(organization_id, subscription_id, id, includes = nil) + rel = MnoEnterprise::SubscriptionEvent + .with_params(_metadata: { act_as_manager: current_user.id, organization_id: organization_id }) + .where('subscription.id' => subscription_id, id: id) + rel = rel.includes(*includes) if includes.present? + rel.first + end +end diff --git a/api/lib/mno_enterprise/concerns/controllers/jpi/v1/admin/subscriptions_controller.rb b/api/lib/mno_enterprise/concerns/controllers/jpi/v1/admin/subscriptions_controller.rb index b611d6f6d..b2ec9d42e 100644 --- a/api/lib/mno_enterprise/concerns/controllers/jpi/v1/admin/subscriptions_controller.rb +++ b/api/lib/mno_enterprise/concerns/controllers/jpi/v1/admin/subscriptions_controller.rb @@ -1,7 +1,7 @@ module MnoEnterprise::Concerns::Controllers::Jpi::V1::Admin::SubscriptionsController extend ActiveSupport::Concern - SUBSCRIPTION_INCLUDES ||= [:product_instance, :'product_pricing.product', :product_contract, :organization, :user, :'license_assignments.user', :'product_instance.product'] + SUBSCRIPTION_INCLUDES ||= [:'product_pricing.product', :product_contract, :organization, :user, :'license_assignments.user', :'product_instance.product'] #================================================================== # Instance methods diff --git a/api/lib/mno_enterprise/concerns/controllers/jpi/v1/subscription_events_controller.rb b/api/lib/mno_enterprise/concerns/controllers/jpi/v1/subscription_events_controller.rb new file mode 100644 index 000000000..0f81787de --- /dev/null +++ b/api/lib/mno_enterprise/concerns/controllers/jpi/v1/subscription_events_controller.rb @@ -0,0 +1,32 @@ +module MnoEnterprise::Concerns::Controllers::Jpi::V1::SubscriptionEventsController + extend ActiveSupport::Concern + + SUBSCRIPTION_EVENT_INCLUDES ||= [:'subscription'] + + #================================================================== + # Instance methods + #================================================================== + # GET /mnoe/jpi/v1/organizations/1/subscriptions/xyz/subscription_events + def index + authorize! :manage_app_instances, parent_organization + @subscription_events = fetch_subscription_events(parent_organization.id, params[:subscription_id]) + end + + # GET /mnoe/jpi/v1/organizations/1/subscriptions/xyz/subscription_events/id + def show + authorize! :manage_app_instances, parent_organization + @subscription_event = fetch_subscription_event(parent_organization.id, params[:subscription_id], params[:id]) + end + + protected + + def fetch_subscription_events(organization_id, subscription_id) + query = MnoEnterprise::SubscriptionEvent.with_params(_metadata: { organization_id: organization_id }) + MnoEnterprise::SubscriptionEvent.fetch_all(query.includes(*SUBSCRIPTION_EVENT_INCLUDES).where('subscription.id' => subscription_id)) + end + + def fetch_subscription_event(organization_id, subscription_id, id) + query = MnoEnterprise::SubscriptionEvent.with_params(_metadata: { organization_id: organization_id }) + query.includes(*SUBSCRIPTION_EVENT_INCLUDES).where('subscription.id' => subscription_id, id: id).first + end +end diff --git a/api/lib/mno_enterprise/concerns/controllers/jpi/v1/subscriptions_controller.rb b/api/lib/mno_enterprise/concerns/controllers/jpi/v1/subscriptions_controller.rb index 22bd2c38d..5d3e28983 100644 --- a/api/lib/mno_enterprise/concerns/controllers/jpi/v1/subscriptions_controller.rb +++ b/api/lib/mno_enterprise/concerns/controllers/jpi/v1/subscriptions_controller.rb @@ -1,7 +1,7 @@ module MnoEnterprise::Concerns::Controllers::Jpi::V1::SubscriptionsController extend ActiveSupport::Concern - SUBSCRIPTION_INCLUDES ||= [:product_instance, :'product_pricing.product', :product_contract, :organization, :user, :'license_assignments.user', :'product_instance.product'] + SUBSCRIPTION_INCLUDES ||= [:'product_pricing.product', :product_contract, :organization, :user, :'license_assignments.user', :'product_instance.product'] #================================================================== # Instance methods diff --git a/api/lib/mno_enterprise/csv_importer.rb b/api/lib/mno_enterprise/csv_importer.rb index f89c22a0f..056c190ef 100644 --- a/api/lib/mno_enterprise/csv_importer.rb +++ b/api/lib/mno_enterprise/csv_importer.rb @@ -48,7 +48,7 @@ def self.process(file_path) address = MnoEnterprise::Address.new( city: row['city'], country_code: row['country'], - street: [row['address1'], row['address2']].reject(&:empty?).join(' '), + street: [row['address1'], row['address2']].reject(&:blank?).join(' '), state_code: row['state_province'], postal_code: row['postal_code'] ) diff --git a/api/spec/controllers/mno_enterprise/jpi/v1/admin/organizations_controller_spec.rb b/api/spec/controllers/mno_enterprise/jpi/v1/admin/organizations_controller_spec.rb index 1f7aebcc7..2870426db 100644 --- a/api/spec/controllers/mno_enterprise/jpi/v1/admin/organizations_controller_spec.rb +++ b/api/spec/controllers/mno_enterprise/jpi/v1/admin/organizations_controller_spec.rb @@ -32,7 +32,7 @@ module MnoEnterprise { organizations: [ :uid, :name, :account_frozen, :soa_enabled, :mails, :logo, :latitude, :longitude, :geo_country_code, :geo_state_code, - :geo_city, :geo_tz, :geo_currency, :metadata, :industry, :size, :financial_year_end_month, :credit_card, :financial_metrics, :created_at + :geo_city, :geo_tz, :geo_currency, :metadata, :industry, :size, :financial_year_end_month, :credit_card, :financial_metrics, :created_at, :external_id ].join(',') } end diff --git a/api/spec/controllers/mno_enterprise/jpi/v1/admin/subscription_events_controller_spec.rb b/api/spec/controllers/mno_enterprise/jpi/v1/admin/subscription_events_controller_spec.rb new file mode 100644 index 000000000..b731a335a --- /dev/null +++ b/api/spec/controllers/mno_enterprise/jpi/v1/admin/subscription_events_controller_spec.rb @@ -0,0 +1,72 @@ +require 'rails_helper' + +module MnoEnterprise + describe Jpi::V1::Admin::SubscriptionEventsController, type: :controller do + include MnoEnterprise::TestingSupport::SharedExamples::JpiV1Admin + + render_views + routes { MnoEnterprise::Engine.routes } + before { request.env["HTTP_ACCEPT"] = 'application/json' } + + before(:each) do + Settings.merge!(dashboard: { marketplace: {provisioning: true } }) + Rails.application.reload_routes! + end + + #=============================================== + # Assignments + #=============================================== + let(:user) { build(:user, :admin) } + let!(:current_user_stub) { stub_user(user) } + + let(:organization) { build(:organization) } + let(:subscription) { build(:subscription) } + let(:subscription_event) { build(:subscription_event, subscription: subscription) } + + #=============================================== + # Specs + #=============================================== + before { sign_in user } + + describe 'GET #index' do + subject { get :index, organization_id: organization.id, subscription_id: subscription.id } + + let(:data) { JSON.parse(response.body) } + let(:includes) { [:'subscription'] } + let(:expected_params) { { filter: { 'subscription.id': subscription.id }, _metadata: { act_as_manager: user.id, organization_id: organization.id } } } + + before { stub_api_v2(:get, "/subscription_events", [subscription_event], includes, expected_params) } + + it_behaves_like 'a jpi v1 admin action' + + it 'returns the subscription events' do + subject + expect(data['subscription_events'].first['id']).to eq(subscription_event.id) + end + end + + describe 'GET #show' do + subject { get :show, id: subscription_event.id, organization_id: organization.id, subscription_id: subscription.id } + + let(:data) { JSON.parse(response.body) } + let(:includes) { [:'subscription'] } + let(:expected_params) do + { + filter: { id: subscription_event.id, 'subscription.id': subscription.id }, + _metadata: { act_as_manager: user.id, organization_id: organization.id }, + page: { number: 1, size: 1 } } + end + + before { allow(subscription_event).to receive(:license_assignments).and_return([]) } + before { allow(subscription_event).to receive(:organization).and_return(organization) } + before { stub_api_v2(:get, "/subscription_events", subscription_event, includes, expected_params) } + + it_behaves_like 'a jpi v1 admin action' + + it 'returns the subscription event' do + subject + expect(data['subscription_event']['id']).to eq(subscription_event.id) + end + end + end +end diff --git a/api/spec/controllers/mno_enterprise/jpi/v1/admin/subscriptions_controller_spec.rb b/api/spec/controllers/mno_enterprise/jpi/v1/admin/subscriptions_controller_spec.rb index d447de8bf..d20d8bd6b 100644 --- a/api/spec/controllers/mno_enterprise/jpi/v1/admin/subscriptions_controller_spec.rb +++ b/api/spec/controllers/mno_enterprise/jpi/v1/admin/subscriptions_controller_spec.rb @@ -31,7 +31,7 @@ module MnoEnterprise subject { get :index } let(:data) { JSON.parse(response.body) } - let(:includes) { [:product_instance, :'product_pricing.product', :product_contract, :organization, :user, :'license_assignments.user', :'product_instance.product'] } + let(:includes) { [:'product_pricing.product', :product_contract, :organization, :user, :'license_assignments.user', :'product_instance.product'] } let(:expected_params) { { _metadata: { act_as_manager: user.id } } } before { allow(subscription).to receive(:license_assignments).and_return([]) } @@ -45,7 +45,7 @@ module MnoEnterprise subject { get :show, id: subscription.id, organization_id: organization.id } let(:data) { JSON.parse(response.body) } - let(:includes) { [:product_instance, :'product_pricing.product', :product_contract, :organization, :user, :'license_assignments.user', :'product_instance.product'] } + let(:includes) { [:'product_pricing.product', :product_contract, :organization, :user, :'license_assignments.user', :'product_instance.product'] } let(:expected_params) do { filter: { id: subscription.id, organization_id: organization.id }, diff --git a/api/spec/controllers/mno_enterprise/jpi/v1/subscription_events_controller_spec.rb b/api/spec/controllers/mno_enterprise/jpi/v1/subscription_events_controller_spec.rb new file mode 100644 index 000000000..febcbff57 --- /dev/null +++ b/api/spec/controllers/mno_enterprise/jpi/v1/subscription_events_controller_spec.rb @@ -0,0 +1,65 @@ +require 'rails_helper' + +module MnoEnterprise + describe Jpi::V1::SubscriptionEventsController, type: :controller do + include MnoEnterprise::TestingSupport::JpiV1TestHelper + render_views + routes { MnoEnterprise::Engine.routes } + before { request.env['HTTP_ACCEPT'] = 'application/json' } + + before(:all) do + Settings.merge!(dashboard: {marketplace: {provisioning: true}}) + Rails.application.reload_routes! + end + + # Stub controller ability + let!(:ability) { stub_ability } + before { allow(ability).to receive(:can?).with(any_args).and_return(true) } + + # Stub user and user call + let!(:user) { build(:user) } + let!(:current_user_stub) { stub_user(user) } + + # Stub organization and association + let!(:organization) { build(:organization, orga_relations: []) } + let!(:orga_relation) { organization.orga_relations << build(:orga_relation, user_id: user.id, organization_id: organization.id, role: 'Super Admin') } + let!(:organization_stub) { stub_api_v2(:get, "/organizations/#{organization.id}", organization, %i(orga_relations users)) } + + describe 'GET #index' do + let(:subscription) { build(:subscription) } + let(:subscription_event) { build(:subscription_event, subscription: subscription) } + + let(:expected_params) do + { + filter: { 'subscription.id': subscription.id }, + _metadata: { organization_id: organization.id } + } + end + before { stub_api_v2(:get, "/subscription_events", [subscription_event], [:subscription], expected_params) } + before { sign_in user } + + subject { get :index, organization_id: organization.id, subscription_id: subscription.id } + + it_behaves_like 'jpi v1 protected action' + end + + describe 'GET #show' do + let(:subscription) { build(:subscription) } + let(:subscription_event) { build(:subscription_event, subscription: subscription) } + + let(:expected_params) do + { + filter: { id: subscription_event.id, 'subscription.id': subscription.id }, + _metadata: { organization_id: organization.id }, + page: { number: 1, size: 1 } + } + end + before { stub_api_v2(:get, "/subscription_events", subscription_event, [:subscription], expected_params) } + before { sign_in user } + + subject { get :show, organization_id: organization.id, subscription_id: subscription.id, id: subscription_event.id } + + it_behaves_like 'jpi v1 protected action' + end + end +end diff --git a/api/spec/controllers/mno_enterprise/jpi/v1/subscriptions_controller_spec.rb b/api/spec/controllers/mno_enterprise/jpi/v1/subscriptions_controller_spec.rb index 0297b01f4..33eca247a 100644 --- a/api/spec/controllers/mno_enterprise/jpi/v1/subscriptions_controller_spec.rb +++ b/api/spec/controllers/mno_enterprise/jpi/v1/subscriptions_controller_spec.rb @@ -31,7 +31,7 @@ module MnoEnterprise describe 'GET #index' do let(:subscription) { build(:subscription) } - before { stub_api_v2(:get, "/subscriptions", [subscription], [:product_instance, :'product_pricing.product', :product_contract, :organization, :user, :'license_assignments.user', :'product_instance.product'], {filter: {organization_id: organization.id}, '_metadata[organization_id]' => organization.id}) } + before { stub_api_v2(:get, "/subscriptions", [subscription], [:'product_pricing.product', :product_contract, :organization, :user, :'license_assignments.user', :'product_instance.product'], {filter: {organization_id: organization.id}, '_metadata[organization_id]' => organization.id}) } before { sign_in user } subject { get :index, organization_id: organization.id } @@ -42,7 +42,7 @@ module MnoEnterprise describe 'GET #show' do let(:subscription) { build(:subscription) } - before { stub_api_v2(:get, "/subscriptions", subscription, [:product_instance, :'product_pricing.product', :product_contract, :organization, :user, :'license_assignments.user', :'product_instance.product'], {filter: {organization_id: organization.id, id: subscription.id}, 'page[number]' => 1, 'page[size]' => 1, '_metadata[organization_id]' => organization.id}) } + before { stub_api_v2(:get, "/subscriptions", subscription, [:'product_pricing.product', :product_contract, :organization, :user, :'license_assignments.user', :'product_instance.product'], {filter: {organization_id: organization.id, id: subscription.id}, 'page[number]' => 1, 'page[size]' => 1, '_metadata[organization_id]' => organization.id}) } before { sign_in user } subject { get :show, organization_id: organization.id, id: subscription.id } @@ -57,7 +57,7 @@ module MnoEnterprise before { stub_audit_events } before { stub_api_v2(:post, "/subscriptions", subscription, [], {}) } - before { stub_api_v2(:get, "/subscriptions", subscription, [:product_instance, :'product_pricing.product', :product_contract, :organization, :user, :'license_assignments.user', :'product_instance.product'], {filter: {organization_id: organization.id, id: subscription.id}, 'page[number]' => 1, 'page[size]' => 1, '_metadata[organization_id]' => organization.id}) } + before { stub_api_v2(:get, "/subscriptions", subscription, [:'product_pricing.product', :product_contract, :organization, :user, :'license_assignments.user', :'product_instance.product'], {filter: {organization_id: organization.id, id: subscription.id}, 'page[number]' => 1, 'page[size]' => 1, '_metadata[organization_id]' => organization.id}) } before { sign_in user } subject { post :create, organization_id: organization.id, subscription: {custom_data: {foo: :bar}.to_json, product_pricing_id: product_pricing.id} } @@ -91,7 +91,7 @@ module MnoEnterprise before { stub_audit_events } before { stub_api_v2(:post, "/subscriptions/#{subscription.id}/modify", subscription, [], {}) } before { stub_api_v2(:get, "/subscriptions", subscription, [], {filter: {organization_id: organization.id, id: subscription.id}, 'page[number]' => 1, 'page[size]' => 1}) } - before { stub_api_v2(:get, "/subscriptions", subscription, [:product_instance, :'product_pricing.product', :product_contract, :organization, :user, :'license_assignments.user', :'product_instance.product'], {filter: {organization_id: organization.id, id: subscription.id}, 'page[number]' => 1, 'page[size]' => 1, '_metadata[organization_id]' => organization.id}) } + before { stub_api_v2(:get, "/subscriptions", subscription, [:'product_pricing.product', :product_contract, :organization, :user, :'license_assignments.user', :'product_instance.product'], {filter: {organization_id: organization.id, id: subscription.id}, 'page[number]' => 1, 'page[size]' => 1, '_metadata[organization_id]' => organization.id}) } before { sign_in user } subject { put :update, organization_id: organization.id, id: subscription.id, subscription: {custom_data: {foo: :bar}.to_json, product_pricing_id: product_pricing.id} } @@ -124,7 +124,7 @@ module MnoEnterprise before { stub_audit_events } before { stub_api_v2(:post, "/subscriptions/#{subscription.id}/cancel", subscription, [], {}) } before { stub_api_v2(:get, "/subscriptions", subscription, [], {filter: {organization_id: organization.id, id: subscription.id}, 'page[number]' => 1, 'page[size]' => 1}) } - before { stub_api_v2(:get, "/subscriptions", subscription, [:product_instance, :'product_pricing.product', :product_contract, :organization, :user, :'license_assignments.user', :'product_instance.product'], {filter: {organization_id: organization.id, id: subscription.id}, 'page[number]' => 1, 'page[size]' => 1, '_metadata[organization_id]' => organization.id}) } + before { stub_api_v2(:get, "/subscriptions", subscription, [:'product_pricing.product', :product_contract, :organization, :user, :'license_assignments.user', :'product_instance.product'], {filter: {organization_id: organization.id, id: subscription.id}, 'page[number]' => 1, 'page[size]' => 1, '_metadata[organization_id]' => organization.id}) } before { sign_in user } subject { post :cancel, organization_id: organization.id, id: subscription.id } diff --git a/api/spec/fixtures/batch-example.csv b/api/spec/fixtures/batch-example.csv index 8a016d023..8c726988f 100644 --- a/api/spec/fixtures/batch-example.csv +++ b/api/spec/fixtures/batch-example.csv @@ -1,3 +1,3 @@ external_id,company_name,billing_currency,name,surname,address1,address2,city,state_province,country,postal_code,phone,email -O1,Company Name 1,EUR,John,Doe,123 Main Street,Anytown,AnyCity,AnyState,GB,1225-5848,10987654321,john.doe@example.com -O2,Company Name 2,EUR,Jane,Doe,123 Main Street,Anytown,AnyCity,AnyState,US,1225-5848,10987654321,jane.doe@example.com +O1,Company Name 1,EUR,John,Doe,123 Main Street,,Anytown,AnyState,GB,1225-5848,10987654321,john.doe@example.com +O2,Company Name 2,EUR,Jane,Doe,123 Main Street,,Anytown,AnyState,US,1225-5848,10987654321,jane.doe@example.com diff --git a/api/spec/routing/mno_enterprise/jpi/v1/admin/subscription_events_controller_routing_spec.rb b/api/spec/routing/mno_enterprise/jpi/v1/admin/subscription_events_controller_routing_spec.rb new file mode 100644 index 000000000..a3b43255d --- /dev/null +++ b/api/spec/routing/mno_enterprise/jpi/v1/admin/subscription_events_controller_routing_spec.rb @@ -0,0 +1,29 @@ +require 'rails_helper' + +module MnoEnterprise + RSpec.describe Jpi::V1::Admin::SubscriptionEventsController, type: :routing do + routes { MnoEnterprise::Engine.routes } + + context 'Product provisioning is enabled' do + before(:all) do + Settings.merge!(dashboard: {marketplace: {provisioning: true}}) + Rails.application.reload_routes! + end + + it 'routes to #index' do + expect(get('/jpi/v1/admin/organizations/1/subscriptions/xyz/subscription_events')).to route_to('mno_enterprise/jpi/v1/admin/subscription_events#index', organization_id: '1', subscription_id: 'xyz', format: 'json') + end + end + + context 'Product provisioning is disabled' do + before(:all) do + Settings.merge!(dashboard: {marketplace: {provisioning: false}}) + Rails.application.reload_routes! + end + + it 'does not route to #index' do + expect(get('/jpi/v1/admin/organizations/1/subscription_events')).not_to be_routable + end + end + end +end diff --git a/api/spec/routing/mno_enterprise/jpi/v1/admin/subscriptions_controller_routing_spec.rb b/api/spec/routing/mno_enterprise/jpi/v1/admin/subscriptions_controller_routing_spec.rb index 75d91756e..6ca4b2b7a 100644 --- a/api/spec/routing/mno_enterprise/jpi/v1/admin/subscriptions_controller_routing_spec.rb +++ b/api/spec/routing/mno_enterprise/jpi/v1/admin/subscriptions_controller_routing_spec.rb @@ -25,11 +25,11 @@ module MnoEnterprise Rails.application.reload_routes! end - it 'routes to #show' do + it 'does not route to #show' do expect(get('/jpi/v1/admin/subscriptions')).not_to be_routable end - it 'routes to #index' do + it 'does not route to #index' do expect(get('/jpi/v1/admin/organizations/1/subscriptions')).not_to be_routable end end diff --git a/api/spec/routing/mno_enterprise/jpi/v1/subscription_events_controller_routing_spec.rb b/api/spec/routing/mno_enterprise/jpi/v1/subscription_events_controller_routing_spec.rb new file mode 100644 index 000000000..9f46747ff --- /dev/null +++ b/api/spec/routing/mno_enterprise/jpi/v1/subscription_events_controller_routing_spec.rb @@ -0,0 +1,37 @@ +require "rails_helper" + +module MnoEnterprise + RSpec.describe Jpi::V1::SubscriptionEventsController, type: :routing do + routes { MnoEnterprise::Engine.routes } + + context "Product provisioning is enabled" do + before(:all) do + Settings.merge!(dashboard: {marketplace: {provisioning: true}}) + Rails.application.reload_routes! + end + + it 'routes to #index' do + expect(get('/jpi/v1/organizations/1/subscriptions/xyz/subscription_events')).to route_to("mno_enterprise/jpi/v1/subscription_events#index", organization_id: '1', subscription_id: 'xyz') + end + + it 'routes to #show' do + expect(get('/jpi/v1/organizations/1/subscriptions/xyz/subscription_events/abc')).to route_to("mno_enterprise/jpi/v1/subscription_events#show", id: 'abc', organization_id: '1', subscription_id: 'xyz') + end + end + + context "Product provisioning is disabled" do + before(:all) do + Settings.merge!(dashboard: {marketplace: {provisioning: false}}) + Rails.application.reload_routes! + end + + it 'does not route to #index' do + expect(get('/jpi/v1/organizations/1/subscription_events')).not_to be_routable + end + + it 'does not route to #show' do + expect(get('/jpi/v1/organizations/1/subscription_events/abc')).not_to be_routable + end + end + end +end diff --git a/api/spec/routing/mno_enterprise/jpi/v1/subscriptions_controller_routing_spec.rb b/api/spec/routing/mno_enterprise/jpi/v1/subscriptions_controller_routing_spec.rb index 13e639285..1bf46326d 100644 --- a/api/spec/routing/mno_enterprise/jpi/v1/subscriptions_controller_routing_spec.rb +++ b/api/spec/routing/mno_enterprise/jpi/v1/subscriptions_controller_routing_spec.rb @@ -37,19 +37,19 @@ module MnoEnterprise Rails.application.reload_routes! end - it 'routes to #index' do + it 'does not route to #index' do expect(get('/jpi/v1/organizations/1/subscriptions')).not_to be_routable end - it 'routes to #show' do + it 'does not route to #show' do expect(get('/jpi/v1/organizations/1/subscriptions/abc')).not_to be_routable end - it 'routes to #create' do + it 'does not route to #create' do expect(post('/jpi/v1/organizations/1/subscriptions')).not_to be_routable end - it 'routes to #update' do + it 'does not route to #update' do expect(put('/jpi/v1/organizations/1/subscriptions/abc')).not_to be_routable end end diff --git a/core/.rspec b/core/.rspec new file mode 100644 index 000000000..cad23e794 --- /dev/null +++ b/core/.rspec @@ -0,0 +1,3 @@ +--color +--backtrace +--require spec_helper diff --git a/core/app/models/mno_enterprise/subscription_event.rb b/core/app/models/mno_enterprise/subscription_event.rb new file mode 100644 index 000000000..374362b04 --- /dev/null +++ b/core/app/models/mno_enterprise/subscription_event.rb @@ -0,0 +1,24 @@ +module MnoEnterprise + class SubscriptionEvent < BaseResource + property :created_at, type: :time + property :updated_at, type: :time + + property :uid, type: :string + property :status, type: :string + property :event_type, type: :string + property :message, type: :string + property :provisioning_data + + has_one :subscription + + def to_audit_event + event = {id: id, status: status} + if relationships.respond_to?(:subscription) + subscription = relationships.subscription + event[:subscription_id] = subscription&.dig('data', 'id') + event[:organization_id] = subscription.relationships.organization&.dig('data', 'id') if subscription.relationships.respond_to?(:subscription) + end + event + end + end +end diff --git a/core/app/views/system_notifications/invoice.html.erb b/core/app/views/system_notifications/invoice.html.erb index e35d7581b..0d8221260 100644 --- a/core/app/views/system_notifications/invoice.html.erb +++ b/core/app/views/system_notifications/invoice.html.erb @@ -14,7 +14,7 @@ <%= @info[:started_at] %> to <%= @info[:ended_at] %>.
- The amount due for this invoice is <%= @info[:currency]%> <%= @info[:price_cents]%>. + The amount due for this invoice is <%= @info[:currency]%> <%= "#{ Money.new(@info[:price_cents], @info[:currency]).format(symbol: false) }" %>. Your designated credit card will be charged on the 2nd of next month.
diff --git a/core/app/views/system_notifications/invoice.text.erb b/core/app/views/system_notifications/invoice.text.erb index c4c8f1308..32a3d1e7c 100644 --- a/core/app/views/system_notifications/invoice.text.erb +++ b/core/app/views/system_notifications/invoice.text.erb @@ -3,7 +3,7 @@ Hi <%= @info[:first_name]%>, Please find attached your invoice from <%= @info[:started_at] %> to <%= @info[:ended_at] %>. -The amount due for this invoice is <%= @info[:currency]%> <%= @info[:price_cents]%>. +The amount due for this invoice is <%= @info[:currency]%> <%= "#{ Money.new(@info[:price_cents], @info[:currency]).format(symbol: false) }" %>. Your designated credit card will be charged on the 2nd of next month. You can check your current spendings as well as your billing history in your <%= @info[:dashboard_link] %> dashboard. diff --git a/core/config/locales/templates/dashboard/provisioning/en.yml b/core/config/locales/templates/dashboard/provisioning/en.yml index 1f7a42216..d50ddbe8f 100644 --- a/core/config/locales/templates/dashboard/provisioning/en.yml +++ b/core/config/locales/templates/dashboard/provisioning/en.yml @@ -50,10 +50,12 @@ en: status: "Status" amount: "Amount" provisioning_data: "Provisioning data" + provisioning_data_root_name: "Provisioning Data" no_provisioning_data: "No provisioning data" custom_data: "Information provided by the customer" no_custom_data: "No information provided by the customer" licenses: "Licenses" + events: "Provisioning events" subscriptions: title: "Manage your subscriptions" currency_warning: "Some prices are missing for your current currency. Please contact your administrator for more information." @@ -69,11 +71,11 @@ en: status: "Status" states: requested: requested - approved: approved - provisoining: provisoining + provisioning: provisioning fulfilled: fulfilled expired: expired suspended: suspended + cancelling: cancelling cancelled: cancelled aborted: aborted modify: "Modify subscription" diff --git a/core/lib/mno_enterprise/concerns/models/organization.rb b/core/lib/mno_enterprise/concerns/models/organization.rb index 75ca9858b..3c6ef1680 100644 --- a/core/lib/mno_enterprise/concerns/models/organization.rb +++ b/core/lib/mno_enterprise/concerns/models/organization.rb @@ -34,6 +34,7 @@ module MnoEnterprise::Concerns::Models::Organization property :credit_card_id property :financial_metrics property :billing_currency + property :external_id, type: :string end #================================================================== diff --git a/core/lib/mno_enterprise/testing_support/factories/subscription.rb b/core/lib/mno_enterprise/testing_support/factories/subscription.rb index bc5dc22d0..1132d2302 100644 --- a/core/lib/mno_enterprise/testing_support/factories/subscription.rb +++ b/core/lib/mno_enterprise/testing_support/factories/subscription.rb @@ -4,6 +4,7 @@ status 'requested' start_date Date.today end_date Date.today + 1.year + currency 'USD' max_licenses 10 available_licenses 10 diff --git a/core/lib/mno_enterprise/testing_support/factories/subscription_event.rb b/core/lib/mno_enterprise/testing_support/factories/subscription_event.rb new file mode 100644 index 000000000..20e13af42 --- /dev/null +++ b/core/lib/mno_enterprise/testing_support/factories/subscription_event.rb @@ -0,0 +1,7 @@ +FactoryGirl.define do + factory :subscription_event, class: MnoEnterprise::SubscriptionEvent do + sequence(:id, &:to_s) + + subscription { build(:subscription) } + end +end