Merge branch 'master' of github.com:domify/registry

This commit is contained in:
Priit Tark 2015-07-07 13:23:11 +03:00
commit f5c7850d2c
15 changed files with 255 additions and 74 deletions

View file

@ -30,7 +30,7 @@ class Epp::DomainsController < EppController
ActiveRecord::Base.transaction do ActiveRecord::Base.transaction do
if @domain.save # TODO: Maybe use validate: false here because we have already validated the domain? if @domain.save # TODO: Maybe use validate: false here because we have already validated the domain?
current_user.registrar.debit!(@domain_price, "#{I18n.t('create')} #{@domain.name}") current_user.registrar.debit!(@domain_price, "#{I18n.t('create')} #{@domain.name}", AccountActivity::CREATE)
render_epp_response '/epp/domains/create' render_epp_response '/epp/domains/create'
else else
handle_errors(@domain) handle_errors(@domain)
@ -102,7 +102,7 @@ class Epp::DomainsController < EppController
fail ActiveRecord::Rollback fail ActiveRecord::Rollback
end end
current_user.registrar.debit!(@domain_price, "#{I18n.t('renew')} #{@domain.name}") current_user.registrar.debit!(@domain_price, "#{I18n.t('renew')} #{@domain.name}", AccountActivity::RENEW)
render_epp_response '/epp/domains/renew' render_epp_response '/epp/domains/renew'
else else
handle_errors(@domain) handle_errors(@domain)

View file

@ -1,10 +1,28 @@
class Registrar::AccountActivitiesController < RegistrarController class Registrar::AccountActivitiesController < RegistrarController
load_and_authorize_resource load_and_authorize_resource
def index def index # rubocop: disable Metrics/AbcSize
params[:q] ||= {}
account = current_user.registrar.cash_account account = current_user.registrar.cash_account
ca_cache = params[:q][:created_at_lteq]
begin
end_time = params[:q][:created_at_lteq].try(:to_date)
params[:q][:created_at_lteq] = end_time.try(:end_of_day)
rescue
logger.warn('Invalid date')
end
@q = account.activities.includes(:invoice).search(params[:q]) @q = account.activities.includes(:invoice).search(params[:q])
@q.sorts = 'id desc' if @q.sorts.empty? @q.sorts = 'id desc' if @q.sorts.empty?
@account_activities = @q.result.page(params[:page])
respond_to do |format|
format.html { @account_activities = @q.result.page(params[:page]) }
format.csv do
send_data @q.result.to_csv, filename: "account_activities_#{Time.zone.now.to_formatted_s(:number)}.csv"
end
end
params[:q][:created_at_lteq] = ca_cache
end end
end end

View file

@ -1,13 +1,37 @@
require 'csv'
class AccountActivity < ActiveRecord::Base class AccountActivity < ActiveRecord::Base
include Versions include Versions
belongs_to :account belongs_to :account
belongs_to :bank_transaction belongs_to :bank_transaction
belongs_to :invoice belongs_to :invoice
CREATE = 'create'
RENEW = 'renew'
ADD_CREDIT = 'add_credit'
after_create :update_balance after_create :update_balance
def update_balance def update_balance
account.balance += sum account.balance += sum
account.save account.save
end end
class << self
def types_for_select
[CREATE, RENEW, ADD_CREDIT].map { |x| [I18n.t(x), x] }
end
def to_csv
attributes = %w(description activity_type created_at sum)
CSV.generate(headers: true) do |csv|
csv << %w(description activity_type receipt_date sum)
all.find_each do |x|
csv << attributes.map { |attr| x.send(attr) }
end
end
end
end
end end

View file

@ -79,7 +79,8 @@ class BankTransaction < ActiveRecord::Base
invoice: invoice, invoice: invoice,
sum: invoice.sum_without_vat, sum: invoice.sum_without_vat,
currency: currency, currency: currency,
description: description description: description,
activity_type: AccountActivity::ADD_CREDIT
) )
end end
end end

View file

@ -123,19 +123,21 @@ class Registrar < ActiveRecord::Base
accounts.find_by(account_type: Account::CASH) accounts.find_by(account_type: Account::CASH)
end end
def debit!(sum, description) def debit!(sum, description, type = nil)
cash_account.account_activities.create!( cash_account.account_activities.create!(
sum: -sum, sum: -sum,
currency: 'EUR', currency: 'EUR',
description: description description: description,
activity_type: type
) )
end end
def credit!(sum, description) def credit!(sum, description, type = nil)
cash_account.account_activities.create!( cash_account.account_activities.create!(
sum: sum, sum: sum,
currency: 'EUR', currency: 'EUR',
description: description description: description,
activity_type: type
) )
end end

View file

@ -1,29 +1,67 @@
- content_for :actions do - content_for :actions do
= link_to(t(:back_to_billing), registrar_invoices_path, class: 'btn btn-default') = link_to(t(:back_to_billing), registrar_invoices_path, class: 'btn btn-default')
= link_to(t(:export_csv), url_for(params.merge(format: 'csv')), class: 'btn btn-default')
= render 'shared/title', name: t(:account_activity) = render 'shared/title', name: t(:account_activity)
.row
.col-md-12
= search_form_for @q, url: [:registrar, :account_activities], html: { style: 'margin-bottom: 0;' } do |f|
.row
.col-md-6
.form-group
= f.label t(:activity_type)
= f.select :activity_type_in, AccountActivity.types_for_select, {}, class: 'form-control js-combobox', placeholder: t(:choose), multiple: true
.col-md-6
.form-group
= f.label t(:description)
= f.search_field :description_cont, class: 'form-control', placeholder: t(:description), autocomplete: 'off'
.row
.col-md-3
.form-group
= f.label t(:receipt_date_from)
= f.search_field :created_at_gteq, value: params[:q][:created_at_gteq], class: 'form-control datepicker', placeholder: t(:receipt_date_from), autocomplete: 'off'
.col-md-3
.form-group
= f.label t(:receipt_date_until)
= f.search_field :created_at_lteq, value: params[:q][:created_at_lteq], class: 'form-control datepicker', placeholder: t(:receipt_date_until), autocomplete: 'off'
.col-md-6{style: 'padding-top: 25px;'}
%button.btn.btn-default
&nbsp;
%span.glyphicon.glyphicon-search
&nbsp;
%button.btn.btn-default.js-reset-form
= t(:clear_fields)
%hr
.row .row
.col-md-12 .col-md-12
.table-responsive .table-responsive
%table.table.table-hover.table-condensed %table.table.table-hover.table-condensed
%thead %thead
%tr %tr
%th{class: 'col-xs-5'}= t(:description) %th{class: 'col-xs-5'}
%th{class: 'col-xs-3'}= t(:receipt_date) = sort_link(@q, 'description')
%th{class: 'col-xs-2'}= t(:invoice) %th{class: 'col-xs-2'}
%th{class: 'col-xs-2'}= t(:sum) = sort_link(@q, 'activity_type')
%th{class: 'col-xs-3'}
= sort_link(@q, 'created_at', t(:receipt_date))
%th{class: 'col-xs-2'}
= sort_link(@q, 'sum')
%tbody %tbody
- @account_activities.each do |x| - @account_activities.each do |x|
%tr %tr
%td= x.description.present? ? x.description : '-' %td= x.description.present? ? x.description : '-'
%td= x.activity_type ? t(x.activity_type) : ''
%td= l(x.created_at) %td= l(x.created_at)
- if x.invoice
%td= link_to(x.invoice, [:registrar, x.invoice])
- else
%td -
- c = x.sum > 0.0 ? 'text-success' : 'text-danger' - c = x.sum > 0.0 ? 'text-success' : 'text-danger'
- s = x.sum > 0.0 ? "+#{x.sum} #{x.currency}" : "#{x.sum} #{x.currency}" - s = x.sum > 0.0 ? "+#{x.sum} #{x.currency}" : "#{x.sum} #{x.currency}"
%td{class: c}= s %td{class: c}= s
.row .row
.col-md-12 .col-md-12
= paginate @account_activities = paginate @account_activities
:coffee
$(".js-reset-form").on "click", (e) ->
e.preventDefault();
window.location = "#{registrar_account_activities_path}"

View file

@ -856,3 +856,8 @@ en:
blocked_domains: 'Blocked domains' blocked_domains: 'Blocked domains'
billing_failure_credit_balance_low: 'Billing failure - credit balance low' billing_failure_credit_balance_low: 'Billing failure - credit balance low'
create: 'Create' create: 'Create'
activity_type: 'Activity type'
receipt_date_from: 'Receipt date from'
receipt_date_until: 'Receipt date until'
add_credit: 'Add credit'
export_csv: 'Export CSV'

View file

@ -0,0 +1,5 @@
class AddActivityTypeToAccountActivities < ActiveRecord::Migration
def change
add_column :account_activities, :activity_type, :string
end
end

View file

@ -11,7 +11,7 @@
# #
# It's strongly recommended that you check this file into your version control system. # It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema.define(version: 20150703084632) do ActiveRecord::Schema.define(version: 20150706091724) do
# These are extensions that must be enabled in order to support this database # These are extensions that must be enabled in order to support this database
enable_extension "plpgsql" enable_extension "plpgsql"
@ -27,6 +27,7 @@ ActiveRecord::Schema.define(version: 20150703084632) do
t.string "description" t.string "description"
t.string "creator_str" t.string "creator_str"
t.string "updator_str" t.string "updator_str"
t.string "activity_type"
end end
add_index "account_activities", ["account_id"], name: "index_account_activities_on_account_id", using: :btree add_index "account_activities", ["account_id"], name: "index_account_activities_on_account_id", using: :btree
@ -927,8 +928,8 @@ ActiveRecord::Schema.define(version: 20150703084632) do
create_table "que_jobs", id: false, force: :cascade do |t| create_table "que_jobs", id: false, force: :cascade do |t|
t.integer "priority", limit: 2, default: 100, null: false t.integer "priority", limit: 2, default: 100, null: false
t.datetime "run_at", default: "now()", null: false t.datetime "run_at", default: '2015-06-30 14:16:50', null: false
t.integer "job_id", limit: 8, default: "nextval('que_jobs_job_id_seq'::regclass)", null: false t.integer "job_id", limit: 8, default: 0, null: false
t.text "job_class", null: false t.text "job_class", null: false
t.json "args", default: [], null: false t.json "args", default: [], null: false
t.integer "error_count", default: 0, null: false t.integer "error_count", default: 0, null: false

View file

@ -205,7 +205,8 @@ CREATE TABLE account_activities (
updated_at timestamp without time zone, updated_at timestamp without time zone,
description character varying, description character varying,
creator_str character varying, creator_str character varying,
updator_str character varying updator_str character varying,
activity_type character varying
); );
@ -2395,8 +2396,8 @@ ALTER SEQUENCE pricelists_id_seq OWNED BY pricelists.id;
CREATE TABLE que_jobs ( CREATE TABLE que_jobs (
priority smallint DEFAULT 100 NOT NULL, priority smallint DEFAULT 100 NOT NULL,
run_at timestamp with time zone DEFAULT now() NOT NULL, run_at timestamp without time zone DEFAULT '2015-06-30 14:16:50.905537'::timestamp without time zone NOT NULL,
job_id bigint NOT NULL, job_id bigint DEFAULT 0 NOT NULL,
job_class text NOT NULL, job_class text NOT NULL,
args json DEFAULT '[]'::json NOT NULL, args json DEFAULT '[]'::json NOT NULL,
error_count integer DEFAULT 0 NOT NULL, error_count integer DEFAULT 0 NOT NULL,
@ -2405,32 +2406,6 @@ CREATE TABLE que_jobs (
); );
--
-- Name: TABLE que_jobs; Type: COMMENT; Schema: public; Owner: -
--
COMMENT ON TABLE que_jobs IS '3';
--
-- Name: que_jobs_job_id_seq; Type: SEQUENCE; Schema: public; Owner: -
--
CREATE SEQUENCE que_jobs_job_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
--
-- Name: que_jobs_job_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: -
--
ALTER SEQUENCE que_jobs_job_id_seq OWNED BY que_jobs.job_id;
-- --
-- Name: registrant_verifications; Type: TABLE; Schema: public; Owner: -; Tablespace: -- Name: registrant_verifications; Type: TABLE; Schema: public; Owner: -; Tablespace:
-- --
@ -3186,13 +3161,6 @@ ALTER TABLE ONLY people ALTER COLUMN id SET DEFAULT nextval('people_id_seq'::reg
ALTER TABLE ONLY pricelists ALTER COLUMN id SET DEFAULT nextval('pricelists_id_seq'::regclass); ALTER TABLE ONLY pricelists ALTER COLUMN id SET DEFAULT nextval('pricelists_id_seq'::regclass);
--
-- Name: job_id; Type: DEFAULT; Schema: public; Owner: -
--
ALTER TABLE ONLY que_jobs ALTER COLUMN job_id SET DEFAULT nextval('que_jobs_job_id_seq'::regclass);
-- --
-- Name: id; Type: DEFAULT; Schema: public; Owner: - -- Name: id; Type: DEFAULT; Schema: public; Owner: -
-- --
@ -3712,14 +3680,6 @@ ALTER TABLE ONLY pricelists
ADD CONSTRAINT pricelists_pkey PRIMARY KEY (id); ADD CONSTRAINT pricelists_pkey PRIMARY KEY (id);
--
-- Name: que_jobs_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace:
--
ALTER TABLE ONLY que_jobs
ADD CONSTRAINT que_jobs_pkey PRIMARY KEY (queue, priority, run_at, job_id);
-- --
-- Name: registrant_verifications_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: -- Name: registrant_verifications_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace:
-- --
@ -4849,3 +4809,4 @@ INSERT INTO schema_migrations (version) VALUES ('20150701074344');
INSERT INTO schema_migrations (version) VALUES ('20150703084632'); INSERT INTO schema_migrations (version) VALUES ('20150703084632');
INSERT INTO schema_migrations (version) VALUES ('20150706091724');

View file

@ -356,6 +356,7 @@ describe 'EPP Domain', epp: true do
a = @registrar1.cash_account.account_activities.last a = @registrar1.cash_account.account_activities.last
a.description.should == "Create #{Domain.last.name}" a.description.should == "Create #{Domain.last.name}"
a.sum.should == -BigDecimal.new('10.0') a.sum.should == -BigDecimal.new('10.0')
a.activity_type = AccountActivity::CREATE
end end
it 'creates a domain with longer periods' do it 'creates a domain with longer periods' do
@ -372,6 +373,7 @@ describe 'EPP Domain', epp: true do
a = @registrar1.cash_account.account_activities.last a = @registrar1.cash_account.account_activities.last
a.description.should == "Create #{Domain.last.name}" a.description.should == "Create #{Domain.last.name}"
a.sum.should == -BigDecimal.new('20.0') a.sum.should == -BigDecimal.new('20.0')
a.activity_type = AccountActivity::CREATE
end end
it 'creates a domain with longer periods' do it 'creates a domain with longer periods' do
@ -388,6 +390,7 @@ describe 'EPP Domain', epp: true do
a = @registrar1.cash_account.account_activities.last a = @registrar1.cash_account.account_activities.last
a.description.should == "Create #{Domain.last.name}" a.description.should == "Create #{Domain.last.name}"
a.sum.should == -BigDecimal.new('30.0') a.sum.should == -BigDecimal.new('30.0')
a.activity_type = AccountActivity::CREATE
end end
it 'does not create a domain with invalid period' do it 'does not create a domain with invalid period' do
@ -2059,6 +2062,7 @@ describe 'EPP Domain', epp: true do
a = @registrar1.cash_account.account_activities.last a = @registrar1.cash_account.account_activities.last
a.description.should == "Renew #{Domain.last.name}" a.description.should == "Renew #{Domain.last.name}"
a.sum.should == -BigDecimal.new('15.0') a.sum.should == -BigDecimal.new('15.0')
a.activity_type = AccountActivity::RENEW
end end
it 'renews a domain with 2 year period' do it 'renews a domain with 2 year period' do
@ -2089,6 +2093,7 @@ describe 'EPP Domain', epp: true do
a = @registrar1.cash_account.account_activities.last a = @registrar1.cash_account.account_activities.last
a.description.should == "Renew #{Domain.last.name}" a.description.should == "Renew #{Domain.last.name}"
a.sum.should == -BigDecimal.new('35.0') a.sum.should == -BigDecimal.new('35.0')
a.activity_type = AccountActivity::CREATE
end end
it 'renews a domain with 3 year period' do it 'renews a domain with 3 year period' do
@ -2119,11 +2124,17 @@ describe 'EPP Domain', epp: true do
a = @registrar1.cash_account.account_activities.last a = @registrar1.cash_account.account_activities.last
a.description.should == "Renew #{Domain.last.name}" a.description.should == "Renew #{Domain.last.name}"
a.sum.should == -BigDecimal.new('62.0') a.sum.should == -BigDecimal.new('62.0')
a.activity_type = AccountActivity::CREATE
end end
it 'does not renew a domain if credit balance low' do it 'does not renew a domain if credit balance low' do
f = Fabricate(:pricelist, valid_to: Time.zone.now + 1.day, f = Fabricate(:pricelist, {
operation_category: 'renew', duration: '1year', price: 100000) valid_to: Time.zone.now + 1.day,
operation_category: 'renew',
duration: '1year',
price: 100000
})
old_balance = @registrar1.balance old_balance = @registrar1.balance
old_activities = @registrar1.cash_account.account_activities.count old_activities = @registrar1.cash_account.account_activities.count

View file

@ -27,5 +27,12 @@ feature 'Account activity', type: :feature do
current_path.should == '/registrar/account_activities' current_path.should == '/registrar/account_activities'
page.should have_text('+110.0 EUR') page.should have_text('+110.0 EUR')
end end
it 'should download csv' do
visit '/registrar/account_activities'
click_link 'Export CSV'
response_headers['Content-Type'].should == 'text/csv'
response_headers['Content-Disposition'].should match(/attachment; filename="account_activities_\d+\.csv"/)
end
end end
end end

View file

@ -62,6 +62,11 @@ describe BankStatement do
AccountActivity.count.should == 1 AccountActivity.count.should == 1
a = AccountActivity.last
a.description.should == "Invoice no. #{invoice.number}"
a.sum.should == BigDecimal.new('200.0')
a.activity_type = AccountActivity::ADD_CREDIT
r.cash_account.balance.should == 200.0 r.cash_account.balance.should == 200.0
bs.bank_transactions.unbinded.count.should == 1 bs.bank_transactions.unbinded.count.should == 1

View file

@ -182,7 +182,7 @@ describe Domain do
@domain.force_delete_at.should be_nil @domain.force_delete_at.should be_nil
end end
it 'should know its price' do it 'should know its create price' do
Fabricate(:pricelist, { Fabricate(:pricelist, {
category: 'ee', category: 'ee',
operation_category: 'create', operation_category: 'create',
@ -200,6 +200,98 @@ describe Domain do
domain = Fabricate(:domain, period: 365, period_unit: 'd') domain = Fabricate(:domain, period: 365, period_unit: 'd')
domain.price('create').should == 1.50 domain.price('create').should == 1.50
Fabricate(:pricelist, {
category: 'ee',
operation_category: 'create',
duration: '2years',
price: 3,
valid_from: Time.zone.parse('2015-01-01'),
valid_to: nil
})
domain = Fabricate(:domain, period: 2)
domain.price('create').should == 3.0
domain = Fabricate(:domain, period: 24, period_unit: 'm')
domain.price('create').should == 3.0
domain = Fabricate(:domain, period: 730, period_unit: 'd')
domain.price('create').should == 3.0
Fabricate(:pricelist, {
category: 'ee',
operation_category: 'create',
duration: '3years',
price: 6,
valid_from: Time.zone.parse('2015-01-01'),
valid_to: nil
})
domain = Fabricate(:domain, period: 3)
domain.price('create').should == 6.0
domain = Fabricate(:domain, period: 36, period_unit: 'm')
domain.price('create').should == 6.0
domain = Fabricate(:domain, period: 1095, period_unit: 'd')
domain.price('create').should == 6.0
end
it 'should know its renew price' do
Fabricate(:pricelist, {
category: 'ee',
operation_category: 'renew',
duration: '1year',
price: 1.30,
valid_from: Time.zone.parse('2015-01-01'),
valid_to: nil
})
domain = Fabricate(:domain)
domain.price('renew').should == 1.30
domain = Fabricate(:domain, period: 12, period_unit: 'm')
domain.price('renew').should == 1.30
domain = Fabricate(:domain, period: 365, period_unit: 'd')
domain.price('renew').should == 1.30
Fabricate(:pricelist, {
category: 'ee',
operation_category: 'renew',
duration: '2years',
price: 3.1,
valid_from: Time.zone.parse('2015-01-01'),
valid_to: nil
})
domain = Fabricate(:domain, period: 2)
domain.price('renew').should == 3.1
domain = Fabricate(:domain, period: 24, period_unit: 'm')
domain.price('renew').should == 3.1
domain = Fabricate(:domain, period: 730, period_unit: 'd')
domain.price('renew').should == 3.1
Fabricate(:pricelist, {
category: 'ee',
operation_category: 'renew',
duration: '3years',
price: 6.1,
valid_from: Time.zone.parse('2015-01-01'),
valid_to: nil
})
domain = Fabricate(:domain, period: 3)
domain.price('renew').should == 6.1
domain = Fabricate(:domain, period: 36, period_unit: 'm')
domain.price('renew').should == 6.1
domain = Fabricate(:domain, period: 1095, period_unit: 'd')
domain.price('renew').should == 6.1
end end
context 'about registrant update confirm' do context 'about registrant update confirm' do

View file

@ -159,5 +159,16 @@ describe Pricelist do
}) })
Pricelist.price_for('ee', 'create', '1year').should == 1.10 Pricelist.price_for('ee', 'create', '1year').should == 1.10
Fabricate.create(:pricelist, {
category: 'ee',
operation_category: 'create',
duration: '2years',
price: 1.20,
valid_from: Time.zone.parse('2015-07-01'),
valid_to: Time.zone.parse('2999-01-01')
})
Pricelist.price_for('ee', 'create', '2years').should == 1.20
end end
end end