Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(event): Add event list API #2601

Open
wants to merge 5 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 33 additions & 0 deletions app/controllers/api/v1/events_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,30 @@ def show
)
end

def index
result = EventsQuery.call(
organization: current_organization,
pagination: {
page: params[:page],
limit: params[:per_page] || PER_PAGE
},
filters: index_filters
)

if result.success?
render(
json: ::CollectionSerializer.new(
result.events,
::V1::EventSerializer,
collection_name: 'events',
meta: pagination_metadata(result.events)
)
)
else
render_error_response(result)
end
end

def estimate_fees
result = Fees::EstimatePayInAdvanceService.call(
organization: current_organization,
Expand Down Expand Up @@ -107,6 +131,15 @@ def batch_params
).to_h.deep_symbolize_keys
end

def index_filters
params.permit(
:code,
:external_subscription_id,
:timestamp_from,
:timestamp_to
)
end

def event_metadata
{
user_agent: request.user_agent,
Expand Down
42 changes: 42 additions & 0 deletions app/queries/events_query.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# frozen_string_literal: true

class EventsQuery < BaseQuery
def call
events = organization.events
events = paginate(events)
events = events.order(created_at: :desc)

events = with_code(events) if filters.code
events = with_external_subscription_id(events) if filters.external_subscription_id
events = with_timestamp_range(events) if filters.timestamp_from || filters.timestamp_to

result.events = events
result
rescue BaseService::FailedResult
result
end

private

def with_code(scope)
scope.where(code: filters.code)
end

def with_external_subscription_id(scope)
scope.where(external_subscription_id: filters.external_subscription_id)
end

def with_timestamp_range(scope)
scope = scope.where(timestamp: timestamp_from..) if filters.timestamp_from
scope = scope.where(timestamp: ..timestamp_to) if filters.timestamp_to
scope
end

def timestamp_from
@timestamp_from ||= parse_datetime_filter(:timestamp_from)
end

def timestamp_to
@timestamp_to ||= parse_datetime_filter(:timestamp_to)
end
end
2 changes: 1 addition & 1 deletion config/routes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@
put :void, on: :member
post :estimate, on: :collection
end
resources :events, only: %i[create show] do
resources :events, only: %i[create show index] do
post :estimate_fees, on: :collection
end
resources :applied_coupons, only: %i[create index]
Expand Down
85 changes: 85 additions & 0 deletions spec/queries/events_query_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
# frozen_string_literal: true

require 'rails_helper'

RSpec.describe EventsQuery, type: :query do
subject(:events_query) { described_class.new(organization:, pagination:, filters:) }

let(:organization) { create(:organization) }
let(:pagination) { nil }
let(:filters) { {} }

let(:event) { create(:event, timestamp: 1.days.ago.to_date, organization:) }

before { event }
earthpyy marked this conversation as resolved.
Show resolved Hide resolved

describe 'call' do
it 'returns a list of events' do
result = events_query.call

aggregate_failures do
expect(result).to be_success
expect(result.events.count).to eq(1)
expect(result.events).to eq([event])
end
end

context 'with pagination' do
let(:pagination) { {page: 2, limit: 10} }

it 'applies the pagination' do
result = events_query.call

aggregate_failures do
expect(result).to be_success
expect(result.events.count).to eq(0)
expect(result.events.current_page).to eq(2)
end
end
end

context 'with code filter' do
let(:filters) { {code: event.code} }

it 'applies the filter' do
result = events_query.call

aggregate_failures do
expect(result).to be_success
expect(result.events.count).to eq(1)
end
end
end

context 'with external subscription id filter' do
let(:filters) { {external_customer_id: event.external_subscription_id} }

it 'applies the filter' do
result = events_query.call

aggregate_failures do
expect(result).to be_success
expect(result.events.count).to eq(1)
end
end
end

context 'with timestamp from filter' do
let(:filters) {
{
timestamp_from: 2.days.ago.iso8601.to_date.to_s,
timestamp_to: Date.tomorrow.iso8601.to_date.to_s
}
}

it 'applies the filter' do
result = events_query.call

aggregate_failures do
expect(result).to be_success
expect(result.events.count).to eq(1)
end
end
end
end
end
74 changes: 74 additions & 0 deletions spec/requests/api/v1/events_controller_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,80 @@
end
end

describe 'GET /events' do
let(:event1) { create(:event, timestamp: 5.days.ago.to_date, organization:) }

before { event1 }

it 'returns events' do
get_with_token(organization, '/api/v1/events')

expect(response).to have_http_status(:ok)
expect(json[:events].count).to eq(1)
expect(json[:events].first[:lago_id]).to eq(event1.id)
end

context 'with pagination' do
let(:event2) { create(:event, organization:) }

before { event2 }

it 'returns events with correct meta data' do
get_with_token(organization, '/api/v1/events?page=1&per_page=1')

expect(response).to have_http_status(:ok)

expect(json[:events].count).to eq(1)
expect(json[:meta][:current_page]).to eq(1)
expect(json[:meta][:next_page]).to eq(2)
expect(json[:meta][:prev_page]).to eq(nil)
expect(json[:meta][:total_pages]).to eq(2)
expect(json[:meta][:total_count]).to eq(2)
end
end

context 'with code' do
it 'returns events' do
get_with_token(organization, "/api/v1/events?code=#{event1.code}")

expect(response).to have_http_status(:ok)
expect(json[:events].count).to eq(1)
expect(json[:events].first[:lago_id]).to eq(event1.id)
end
end

context 'with external subscription id' do
it 'returns events' do
get_with_token(organization, "/api/v1/events?external_subscription_id=#{event1.external_subscription_id}")

expect(response).to have_http_status(:ok)
expect(json[:events].count).to eq(1)
expect(json[:events].first[:lago_id]).to eq(event1.id)
end
end
earthpyy marked this conversation as resolved.
Show resolved Hide resolved

context 'with timestamp' do
let(:event2) { create(:event, timestamp: 3.days.ago.to_date, organization:) }
let(:event3) { create(:event, timestamp: 1.day.ago.to_date, organization:) }

before do
event2
event3
end

it 'returns events with correct timestamp' do
get_with_token(
organization,
"/api/v1/events?timestamp_from=#{2.days.ago.to_date}&timestamp_to=#{Date.tomorrow.to_date}"
)

expect(response).to have_http_status(:ok)
expect(json[:events].count).to eq(1)
expect(json[:events].first[:lago_id]).to eq(event3.id)
end
end
end

describe 'GET /events/:id' do
let(:event) { create(:event) }

Expand Down