Consider nil in price expire time as effective

#522
This commit is contained in:
Artur Beljajev 2017-06-03 23:12:16 +03:00
parent 8916eee169
commit f76e1259fc
11 changed files with 106 additions and 65 deletions

View file

@ -6,18 +6,19 @@ module Admin
helper_method :zones
helper_method :operation_categories
helper_method :durations
helper_method :statuses
def index
@search = OpenStruct.new(search_params)
unless @search.validity
@search.validity = 'unexpired'
unless @search.status
@search.status = default_status
end
prices = ::Billing::Price.all
if @search.validity.present?
prices = ::Billing::Price.send(@search.validity)
if @search.status.present?
prices = ::Billing::Price.send(@search.status)
end
@q = prices.search(params[:q])
@ -81,7 +82,7 @@ module Admin
def search_params
allowed_params = %i[
validity
status
]
params.fetch(:search, {}).permit(*allowed_params)
end
@ -102,6 +103,14 @@ module Admin
durations = ::Billing::Price::durations
durations.collect { |duration| [duration.sub('mon', 'month'), duration] }
end
def statuses
::Billing::Price.statuses
end
def default_status
'effective'
end
end
end
end

View file

@ -12,6 +12,7 @@ module Billing
validates :operation_category, inclusion: { in: Proc.new { |price| price.class.operation_categories } }
validates :duration, inclusion: { in: Proc.new { |price| price.class.durations } }
alias_attribute :effect_time, :valid_from
alias_attribute :expire_time, :valid_to
monetize :price_cents, allow_nil: true, numericality: { greater_than_or_equal_to: 0 }
after_initialize :init_values
@ -38,6 +39,21 @@ module Billing
]
end
def self.statuses
%w[pending effective expired]
end
def self.pending
where("#{attribute_alias(:effect_time)} > ?", Time.zone.now)
end
def self.effective
condition = "#{attribute_alias(:effect_time)} <= :now " \
" AND (#{attribute_alias(:expire_time)} >= :now" \
" OR #{attribute_alias(:expire_time)} IS NULL)"
where(condition, now: Time.zone.now)
end
def self.valid
where('valid_from <= ? AND (valid_to >= ? OR valid_to IS NULL)', Time.zone.now.end_of_day,
Time.zone.now.beginning_of_day)

View file

@ -2,10 +2,6 @@ module Concerns::Billing::Price::Expirable
extend ActiveSupport::Concern
class_methods do
def unexpired
where("#{attribute_alias(:expire_time)} >= ?", Time.zone.now)
end
def expired
where("#{attribute_alias(:expire_time)} < ?", Time.zone.now)
end

View file

@ -1,10 +1,9 @@
<%= form_for :search, url: admin_prices_path, method: :get, html: { class: 'form-horizontal' } do |f| %>
<div class="form-group">
<%= f.label :validity, class: 'col-sm-2 control-label' %>
<%= f.label :status, class: 'col-sm-2 control-label' %>
<div class="col-sm-3">
<%= f.select :validity, options_for_select(%w[unexpired expired], search.validity),
{ include_blank: true },
<%= f.select :status, options_for_select(statuses, search.status), { include_blank: true },
class: 'form-control' %>
</div>
</div>

View file

@ -7,7 +7,7 @@ FactoryGirl.define do
operation_category Billing::Price.operation_categories.first
zone
factory :unexpired_price do
factory :effective_price do
expire_time { Time.zone.now + 1.day }
end

View file

@ -1,7 +1,7 @@
require 'rails_helper'
RSpec.feature 'Editing price in admin area', settings: false do
given!(:price) { create(:unexpired_price) }
given!(:price) { create(:effective_price) }
background do
sign_in_to_admin_area

View file

@ -1,7 +1,7 @@
require 'rails_helper'
RSpec.feature 'Expiring price in admin area', settings: false do
given!(:price) { create(:unexpired_price) }
given!(:price) { create(:effective_price) }
background do
sign_in_to_admin_area

View file

@ -1,7 +1,7 @@
require 'rails_helper'
RSpec.feature 'Viewing prices in admin area', settings: false do
given!(:unexpired_price) { create(:unexpired_price) }
given!(:effective_price) { create(:effective_price) }
given!(:expired_price) { create(:expired_price) }
background do
@ -9,17 +9,17 @@ RSpec.feature 'Viewing prices in admin area', settings: false do
end
describe 'search' do
context 'when validity is not selected' do
scenario 'shows unexpired prices' do
context 'when status is not selected' do
scenario 'shows effective prices' do
visit admin_prices_path
expect(page).to have_css('.price', count: 1)
end
end
context 'when validity is given' do
scenario 'filters by given validity' do
context 'when status is given' do
scenario 'filters by given status' do
visit admin_prices_path
select 'unexpired', from: 'search_validity'
select 'effective', from: 'search_status'
submit_search_form
expect(page).to have_css('.price', count: 1)

View file

@ -3,6 +3,7 @@ require 'rails_helper'
RSpec.describe Billing::Price do
it { is_expected.to monetize(:price) }
it { is_expected.to be_versioned }
it { is_expected.to alias_attribute(:effect_time, :valid_from) }
it { is_expected.to alias_attribute(:expire_time, :valid_to) }
it 'should have one version' do
@ -14,14 +15,14 @@ RSpec.describe Billing::Price do
end
describe '::operation_categories', db: false do
it 'returns available operation categories' do
it 'returns operation categories' do
categories = %w[create renew]
expect(described_class.operation_categories).to eq(categories)
end
end
describe '::durations', db: false do
it 'returns available durations' do
it 'returns durations' do
durations = [
'3 mons',
'6 mons',
@ -42,6 +43,40 @@ RSpec.describe Billing::Price do
end
end
describe '::statuses', db: false do
it 'returns statuses' do
expect(described_class.statuses).to eq(%w[pending effective expired])
end
end
describe '::pending' do
before :example do
travel_to Time.zone.parse('05.07.2010 00:00')
create(:price, id: 1, effect_time: Time.zone.parse('05.07.2010 00:00'))
create(:price, id: 2, effect_time: Time.zone.parse('05.07.2010 00:01'))
end
it 'returns pending' do
expect(described_class.pending.ids).to eq([2])
end
end
describe '::effective' do
before :example do
travel_to Time.zone.parse('05.07.2010 00:00')
create(:price, id: 1, effect_time: '05.07.2010 00:01', expire_time: '05.07.2010 00:02')
create(:price, id: 2, effect_time: '05.07.2010 00:00', expire_time: '05.07.2010 00:01')
create(:price, id: 3, effect_time: '05.07.2010 00:00', expire_time: nil)
create(:price, id: 4, effect_time: '04.07.2010', expire_time: '04.07.2010 23:59')
end
it 'returns effective' do
expect(described_class.effective.ids).to eq([2, 3])
end
end
describe 'zone validation', db: false do
subject(:price) { described_class.new }

View file

@ -1,20 +1,6 @@
require 'rails_helper'
RSpec.describe Billing::Price do
describe '::unexpired' do
before :example do
travel_to Time.zone.parse('05.07.2010 00:00')
create(:price, id: 1, expire_time: Time.zone.parse('04.07.2010 23:59'))
create(:price, id: 2, expire_time: Time.zone.parse('05.07.2010 00:00'))
create(:price, id: 3, expire_time: Time.zone.parse('05.07.2010 00:01'))
end
it 'returns prices with expire time in the future ' do
expect(described_class.unexpired.ids).to eq([2, 3])
end
end
describe '::expired' do
before :example do
travel_to Time.zone.parse('05.07.2010 00:00')

View file

@ -6,14 +6,14 @@ RSpec.describe 'admin price expire', settings: false do
end
it 'expires price' do
price = create(:unexpired_price)
price = create(:effective_price)
expect { patch expire_admin_price_path(price); price.reload }
.to change { price.expired? }.from(false).to(true)
end
it 'redirects to :index' do
price = create(:unexpired_price)
price = create(:effective_price)
patch expire_admin_price_path(price)