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

fix: Ensure consistent order of results on list responses (frontend and API) #2934

Merged
merged 36 commits into from
Dec 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
6cda3d9
Ensure credit notes consistent order on same created_at
ancorcruz Dec 9, 2024
5adb4af
Add external_customer_id filter to CreditNotesQuery
ancorcruz Dec 9, 2024
9cf21da
CreditNotes API v1 endpoint uses CreditNotesQuery for consistency
ancorcruz Dec 9, 2024
267e1e7
Apply consistent order for AddOnsQuery object
ancorcruz Dec 9, 2024
1c53b1b
Apply consistent ordering to AppliedCouponsQuery
ancorcruz Dec 9, 2024
df04a71
Use apply_consistent_ordering helper method in CreditNotesQuery object
ancorcruz Dec 9, 2024
e51a3f5
Apply consistent ordering to BillableMetricsQuery
ancorcruz Dec 9, 2024
93ca07d
apply consistent ordering to CouponsQuery
ancorcruz Dec 9, 2024
cd0a8b2
Apply consistent ordering to CustomersQuery
ancorcruz Dec 9, 2024
37c0e87
Apply consistent ordering to DunningCampaignsQuery
ancorcruz Dec 9, 2024
c57573b
Apply consistent ordering to EventsQuery
ancorcruz Dec 9, 2024
aeb8e05
Apply consistent ordering to FeesQuery
ancorcruz Dec 9, 2024
4ee8ed4
Apply consitent ordering to integration colletcion mappings query
ancorcruz Dec 9, 2024
424c2a2
improve test context description
ancorcruz Dec 9, 2024
0b682c0
Apply consistent ordering to IntegrationItemsQuery
ancorcruz Dec 9, 2024
871d238
Apply consistent ordering for IntegrationMappingsQuery
ancorcruz Dec 9, 2024
2612c24
Apply consistent ordering to InvoicesQuery
ancorcruz Dec 9, 2024
1748f99
Apply consistent ordering to PastUsageQuery
ancorcruz Dec 9, 2024
18ef556
Apply consitent ordering to payment requests
ancorcruz Dec 9, 2024
90bb418
Apply consistent ordering to plans query
ancorcruz Dec 9, 2024
667434a
re-style subscriptions query specs
ancorcruz Dec 10, 2024
066234b
Apply consistent ordering to subscriptions query
ancorcruz Dec 10, 2024
ae8920e
Apply consistent ordering to TaxesQuery
ancorcruz Dec 10, 2024
2d714ef
Apply consistent ordering to WalletTransactionsQuery
ancorcruz Dec 10, 2024
5515196
re-style webhook endpoints query specs
ancorcruz Dec 10, 2024
851c18a
Apply consistent ordering to webhook endpoints
ancorcruz Dec 10, 2024
9965e6f
re-style specs
ancorcruz Dec 10, 2024
a34c422
Apply consistent ordering to webhooks query
ancorcruz Dec 10, 2024
338f3ca
Re-style query specs
ancorcruz Dec 10, 2024
7ecab7e
Add test to ensure public API does not change
ancorcruz Dec 10, 2024
ed038bf
Use query objects for api controllers
ancorcruz Dec 10, 2024
8815436
GET /api/v1/plans returns plans in consistent order
ancorcruz Dec 10, 2024
90d2f95
Ensure consistent order for Wallets API endpoing response
ancorcruz Dec 11, 2024
287cec2
apply rubocop fixes
ancorcruz Dec 11, 2024
4892cec
Fix
ancorcruz Dec 11, 2024
7e50e26
Revert "Apply consistent ordering to EventsQuery"
ancorcruz Dec 13, 2024
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
31 changes: 19 additions & 12 deletions app/controllers/api/v1/add_ons_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -51,20 +51,27 @@ def show
end

def index
add_ons = current_organization.add_ons
.order(created_at: :desc)
.page(params[:page])
.per(params[:per_page] || PER_PAGE)
result = AddOnsQuery.call(
organization: current_organization,
pagination: {
page: params[:page],
limit: params[:per_page] || PER_PAGE
}
)

render(
json: ::CollectionSerializer.new(
add_ons.includes(:taxes),
::V1::AddOnSerializer,
collection_name: "add_ons",
meta: pagination_metadata(add_ons),
includes: %i[taxes]
if result.success?
render(
json: ::CollectionSerializer.new(
result.add_ons.includes(:taxes),
::V1::AddOnSerializer,
collection_name: "add_ons",
meta: pagination_metadata(result.add_ons),
includes: %i[taxes]
)
)
)
else
render_error_response(result)
end
end

private
Expand Down
32 changes: 19 additions & 13 deletions app/controllers/api/v1/billable_metrics_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -79,21 +79,27 @@ def show
end

def index
metrics = current_organization.billable_metrics
.includes(:filters)
.order(created_at: :desc)
.page(params[:page])
.per(params[:per_page] || PER_PAGE)
result = BillableMetricsQuery.call(
organization: current_organization,
pagination: {
page: params[:page],
limit: params[:per_page] || PER_PAGE
}
)

render(
json: ::CollectionSerializer.new(
metrics,
::V1::BillableMetricSerializer,
collection_name: "billable_metrics",
meta: pagination_metadata(metrics),
includes: %i[counters] # DEPRECATED since 2024-11-22
if result.success?
render(
json: ::CollectionSerializer.new(
result.billable_metrics.includes(:filters),
::V1::BillableMetricSerializer,
collection_name: "billable_metrics",
meta: pagination_metadata(result.billable_metrics),
includes: %i[counters] # DEPRECATED since 2024-11-22
)
)
)
else
render_error_response(result)
end
end

def evaluate_expression
Expand Down
29 changes: 18 additions & 11 deletions app/controllers/api/v1/coupons_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -52,19 +52,26 @@ def show
end

def index
coupons = current_organization.coupons
.order(created_at: :desc)
.page(params[:page])
.per(params[:per_page] || PER_PAGE)
result = CouponsQuery.call(
organization: current_organization,
pagination: {
page: params[:page],
limit: params[:per_page] || PER_PAGE
}
)

render(
json: ::CollectionSerializer.new(
coupons,
::V1::CouponSerializer,
collection_name: "coupons",
meta: pagination_metadata(coupons)
if result.success?
render(
json: ::CollectionSerializer.new(
result.coupons,
::V1::CouponSerializer,
collection_name: "coupons",
meta: pagination_metadata(result.coupons)
)
)
)
else
render_error_response(result)
end
end

private
Expand Down
41 changes: 24 additions & 17 deletions app/controllers/api/v1/credit_notes_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -93,25 +93,28 @@ def void
end

def index
credit_notes = current_organization.credit_notes.finalized

if params[:external_customer_id]
credit_notes = credit_notes.joins(:customer).where(customers: {external_id: params[:external_customer_id]})
end

credit_notes = credit_notes.order(created_at: :desc)
.page(params[:page])
.per(params[:per_page] || PER_PAGE)
result = CreditNotesQuery.call(
organization: current_organization,
pagination: {
page: params[:page],
limit: params[:per_page] || PER_PAGE
},
filters: index_filters
)

render(
json: ::CollectionSerializer.new(
credit_notes.includes(:items, :applied_taxes),
::V1::CreditNoteSerializer,
collection_name: 'credit_notes',
meta: pagination_metadata(credit_notes),
includes: %i[items applied_taxes error_details]
if result.success?
render(
json: ::CollectionSerializer.new(
result.credit_notes.includes(:items, :applied_taxes),
::V1::CreditNoteSerializer,
collection_name: "credit_notes",
meta: pagination_metadata(result.credit_notes),
includes: %i[items applied_taxes error_details]
)
)
)
else
render_error_response(result)
end
end

def estimate
Expand Down Expand Up @@ -164,6 +167,10 @@ def estimate_params
)
end

def index_filters
params.permit(:external_customer_id)
end

def resource_name
'credit_note'
end
Expand Down
30 changes: 19 additions & 11 deletions app/controllers/api/v1/customers_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -36,19 +36,27 @@ def portal_url
end

def index
customers = current_organization.customers
.page(params[:page])
.per(params[:per_page] || PER_PAGE)
result = CustomersQuery.call(
organization: current_organization,
pagination: {
page: params[:page],
limit: params[:per_page] || PER_PAGE
}
)

render(
json: ::CollectionSerializer.new(
customers.includes(:taxes, :integration_customers),
::V1::CustomerSerializer,
collection_name: 'customers',
meta: pagination_metadata(customers),
includes: %i[taxes integration_customers]
if result.success?
render(
json: ::CollectionSerializer.new(
result.customers.includes(:taxes, :integration_customers),
::V1::CustomerSerializer,
collection_name: "customers",
meta: pagination_metadata(result.customers),
includes: %i[taxes integration_customers]
)
)
)
else
render_error_response(result)
end
end

def show
Expand Down
37 changes: 25 additions & 12 deletions app/controllers/api/v1/plans_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -47,20 +47,33 @@ def show
end

def index
plans = current_organization.plans.parents
.order(created_at: :desc)
.page(params[:page])
.per(params[:per_page] || PER_PAGE)
result = PlansQuery.call(
organization: current_organization,
pagination: {
page: params[:page],
limit: params[:per_page] || PER_PAGE
},
filters: {include_pending_deletion: true}
)

render(
json: ::CollectionSerializer.new(
plans.includes(:usage_thresholds, :taxes, :minimum_commitment, charges: {filters: {values: :billable_metric_filter}}),
::V1::PlanSerializer,
collection_name: 'plans',
meta: pagination_metadata(plans),
includes: %i[charges usage_thresholds taxes minimum_commitment]
if result.success?
render(
json: ::CollectionSerializer.new(
result.plans.includes(
:usage_thresholds,
:taxes,
:minimum_commitment,
charges: {filters: {values: :billable_metric_filter}}
),
::V1::PlanSerializer,
collection_name: "plans",
meta: pagination_metadata(result.plans),
includes: %i[charges usage_thresholds taxes minimum_commitment]
)
)
)
else
render_error_response(result)
end
end

private
Expand Down
29 changes: 18 additions & 11 deletions app/controllers/api/v1/taxes_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -43,19 +43,26 @@ def show
end

def index
taxes = current_organization.taxes
.order(created_at: :desc)
.page(params[:page])
.per(params[:per_page] || PER_PAGE)
result = TaxesQuery.call(
organization: current_organization,
pagination: {
page: params[:page],
limit: params[:per_page] || PER_PAGE
}
)

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

private
Expand Down
34 changes: 20 additions & 14 deletions app/controllers/api/v1/wallets_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -52,22 +52,28 @@ def show
end

def index
customer = current_organization.customers.find_by(external_id: params[:external_customer_id])
return not_found_error(resource: 'customer') unless customer

wallets = customer.wallets
.page(params[:page])
.per(params[:per_page] || PER_PAGE)
result = WalletsQuery.call(
organization: current_organization,
pagination: {
page: params[:page],
limit: params[:per_page] || PER_PAGE
},
filters: {external_customer_id: params[:external_customer_id]}
)

render(
json: ::CollectionSerializer.new(
wallets,
::V1::WalletSerializer,
collection_name: 'wallets',
meta: pagination_metadata(wallets),
includes: %i[recurring_transaction_rules]
if result.success?
render(
json: ::CollectionSerializer.new(
result.wallets.includes(:recurring_transaction_rules),
::V1::WalletSerializer,
collection_name: "wallets",
meta: pagination_metadata(result.wallets),
includes: %i[recurring_transaction_rules]
)
)
)
else
render_error_response(result)
end
end

private
Expand Down
28 changes: 18 additions & 10 deletions app/controllers/api/v1/webhook_endpoints_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -31,18 +31,26 @@ def update
end

def index
webhook_endpoints = current_organization.webhook_endpoints
.page(params[:page])
.per(params[:per_page] || PER_PAGE)
result = WebhookEndpointsQuery.call(
organization: current_organization,
pagination: {
page: params[:page],
limit: params[:per_page] || PER_PAGE
}
)

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

def show
Expand Down
2 changes: 1 addition & 1 deletion app/queries/add_ons_query.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ class AddOnsQuery < BaseQuery
def call
add_ons = base_scope.result
add_ons = paginate(add_ons)
add_ons = add_ons.order(created_at: :desc)
add_ons = apply_consistent_ordering(add_ons)

result.add_ons = add_ons
result
Expand Down
2 changes: 1 addition & 1 deletion app/queries/applied_coupons_query.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
class AppliedCouponsQuery < BaseQuery
def call
applied_coupons = paginate(base_scope)
applied_coupons = applied_coupons.order(created_at: :desc)
applied_coupons = apply_consistent_ordering(applied_coupons)

applied_coupons = with_external_customer(applied_coupons) if filters.external_customer_id
applied_coupons = with_status(applied_coupons) if valid_status?
Expand Down
Loading
Loading