Considering timezone when querying payments

This commit is contained in:
Clarissa Borges 2021-05-21 17:41:44 -03:00 committed by Eric Schultz
parent f56ba93e71
commit eaa2b40499
2 changed files with 74 additions and 5 deletions

View file

@ -83,7 +83,10 @@ module QueryPayments
'supporters.name', 'supporters.name',
'supporters.email', 'supporters.email',
'payments.gross_amount', 'payments.gross_amount',
'payments.date' 'timezone(
COALESCE(nonprofits.timezone, \'UTC\'),
timezone(\'UTC\', payments.date)
) as date'
) )
payments = Psql.execute(expr.limit(limit).offset(offset).parse) payments = Psql.execute(expr.limit(limit).offset(offset).parse)
@ -110,6 +113,7 @@ module QueryPayments
def self.full_search_expr(npo_id, query) def self.full_search_expr(npo_id, query)
expr = Qexpr.new.from('payments') expr = Qexpr.new.from('payments')
.left_outer_join('supporters', 'supporters.id=payments.supporter_id') .left_outer_join('supporters', 'supporters.id=payments.supporter_id')
.inner_join('nonprofits', 'nonprofits.id=payments.nonprofit_id')
.left_outer_join('donations', 'donations.id=payments.donation_id') .left_outer_join('donations', 'donations.id=payments.donation_id')
.join("(#{select_to_filter_search(npo_id, query)}) AS \"filtered_payments\"", 'payments.id = filtered_payments.id') .join("(#{select_to_filter_search(npo_id, query)}) AS \"filtered_payments\"", 'payments.id = filtered_payments.id')
.order_by('payments.date DESC') .order_by('payments.date DESC')
@ -145,6 +149,7 @@ module QueryPayments
end end
expr = Qexpr.new.select('payments.id').from('payments') expr = Qexpr.new.select('payments.id').from('payments')
.left_outer_join('supporters', 'supporters.id=payments.supporter_id') .left_outer_join('supporters', 'supporters.id=payments.supporter_id')
.inner_join('nonprofits', 'nonprofits.id=payments.nonprofit_id')
.left_outer_join(inner_donation_search.as('donations'), 'donations.id=payments.donation_id') .left_outer_join(inner_donation_search.as('donations'), 'donations.id=payments.donation_id')
.where('payments.nonprofit_id=$id', id: npo_id.to_i) .where('payments.nonprofit_id=$id', id: npo_id.to_i)
@ -165,10 +170,10 @@ module QueryPayments
expr = expr.order_by("NULLIF(payments.towards, '') #{query[:sort_towards]}") expr = expr.order_by("NULLIF(payments.towards, '') #{query[:sort_towards]}")
end end
if query[:after_date].present? if query[:after_date].present?
expr = expr.where('payments.date >= $date', date: query[:after_date]) expr = expr.where('payments.date >= timezone(COALESCE(nonprofits.timezone, \'UTC\'), timezone(\'UTC\', $date))', date: query[:after_date])
end end
if query[:before_date].present? if query[:before_date].present?
expr = expr.where('payments.date <= $date', date: query[:before_date]) expr = expr.where('payments.date <= timezone(COALESCE(nonprofits.timezone, \'UTC\'), timezone(\'UTC\', $date))', date: query[:before_date])
end end
if query[:amount_greater_than].present? if query[:amount_greater_than].present?
expr = expr.where('payments.gross_amount >= $amt', amt: query[:amount_greater_than].to_i * 100) expr = expr.where('payments.gross_amount >= $amt', amt: query[:amount_greater_than].to_i * 100)
@ -177,7 +182,14 @@ module QueryPayments
expr = expr.where('payments.gross_amount <= $amt', amt: query[:amount_less_than].to_i * 100) expr = expr.where('payments.gross_amount <= $amt', amt: query[:amount_less_than].to_i * 100)
end end
if query[:year].present? if query[:year].present?
expr = expr.where("to_char(payments.date, 'YYYY')=$year", year: query[:year]) expr = expr
.where(
"to_char(timezone(
COALESCE(nonprofits.timezone, \'UTC\'),
timezone(\'UTC\', payments.date)
), 'YYYY')=$year",
year: (query[:year]).to_s
)
end end
if query[:designation].present? if query[:designation].present?
expr = expr.where('donations.designation @@ $s', s: (query[:designation]).to_s) expr = expr.where('donations.designation @@ $s', s: (query[:designation]).to_s)
@ -332,7 +344,7 @@ module QueryPayments
end end
def self.export_selects def self.export_selects
["to_char(payments.date::timestamptz, 'YYYY-MM-DD HH24:MI:SS TZ') AS date", ["to_char(payments.date::timestamptz at time zone COALESCE(nonprofits.timezone, \'UTC\'), 'YYYY-MM-DD HH24:MI:SS TZ') AS date",
'(payments.gross_amount / 100.0)::money::text AS gross_amount', '(payments.gross_amount / 100.0)::money::text AS gross_amount',
'(payments.fee_total / 100.0)::money::text AS fee_total', '(payments.fee_total / 100.0)::money::text AS fee_total',
'(payments.net_amount / 100.0)::money::text AS net_amount', '(payments.net_amount / 100.0)::money::text AS net_amount',

View file

@ -241,6 +241,63 @@ describe QueryPayments do
expect(result[:data].count).to eq 5 expect(result[:data].count).to eq 5
end end
context 'considering the nonprofit timezone on the query result' do
before do
donation_result_today
first_refund_of_yesterday
second_refund_of_yesterday
end
it 'when the nonprofit does not have a timezone it considers UTC as default' do
donation_result_tomorrow
result = QueryPayments::full_search(nonprofit.id, {})
expect(result[:data].first['date']).to eq (Time.now).to_s
end
context 'when the nonprofit has a timezone' do
before do
nonprofit.update(timezone: 'America/New_York')
allow(QuerySourceToken)
.to receive(:get_and_increment_source_token)
.and_return(source_tokens[0])
end
it 'shows the corresponding time' do
donation_result_tomorrow
result = QueryPayments::full_search(nonprofit.id, {})
expect(result[:data].first['date']).to eq ((Time.now) - 4.hours).to_s
end
it 'finds the payments on dates after the specified dates' do
donation_result_tomorrow
result = QueryPayments::full_search(nonprofit.id, { after_date: Time.now - 4.hours })
expect(result[:data].count).to eq 5
end
it 'finds the payments on dates before the specified dates' do
donation_result_tomorrow
result = QueryPayments::full_search(nonprofit.id, { before_date: Time.now })
expect(result[:data].count).to eq 5
end
it 'finds the payments of an specific year' do
# creating a payment at 1 AM UTC from january 2020
# should not be included in the 2020 query if we are at America/New_York
Timecop.freeze(2020,1,1,1,0,0, "+00:00")
donation =
generate_donation(
amount: charge_amount_large,
token: source_tokens[2].token,
date: Time.now.to_s
)
result_for_2020 = QueryPayments::full_search(nonprofit.id, { year: '2020' })
result_for_2019 = QueryPayments::full_search(nonprofit.id, { year: '2019' })
expect(result_for_2019[:data].count).to eq 1
expect(result_for_2020[:data].count).to eq 4
end
end
end
end end
describe 'event donations' do describe 'event donations' do