Refactor prices

#475
This commit is contained in:
Artur Beljajev 2017-04-26 00:51:06 +03:00
parent 5fdc1938af
commit 5a533e09bf
44 changed files with 1027 additions and 375 deletions

View file

@ -0,0 +1,86 @@
module Admin
module Billing
class PricesController < AdminController
authorize_resource(class: 'Billing::Price')
before_action :load_price, only: %i[edit update destroy]
helper_method :zones
helper_method :operation_categories
helper_method :durations
def index
@q = ::Billing::Price.search(params[:q])
@q.sorts = ['zone_id asc', 'duration asc', 'operation_category asc',
'valid_from desc', 'valid_to asc'] if @q.sorts.empty?
@prices = @q.result.page(params[:page])
end
def new
@price = ::Billing::Price.new
end
def edit
end
def create
@price = ::Billing::Price.new(price_params)
if @price.save
flash[:notice] = t('.created')
redirect_to_index
else
render :new
end
end
def update
if @price.update_attributes(price_params)
flash[:notice] = t('.updated')
redirect_to_index
else
render :edit
end
end
def destroy
@price.destroy!
flash[:notice] = t('.destroyed')
redirect_to_index
end
private
def load_price
@price = ::Billing::Price.find(params[:id])
end
def price_params
allowed_params = %i[
zone_id
operation_category
duration
price
valid_from
valid_to
]
params.require(:price).permit(*allowed_params)
end
def redirect_to_index
redirect_to admin_prices_url
end
def zones
::DNS::Zone.all
end
def operation_categories
::Billing::Price::operation_categories
end
def durations
::Billing::Price::durations
end
end
end
end

View file

@ -1,54 +0,0 @@
class Admin::PricelistsController < AdminController
load_and_authorize_resource
before_action :set_pricelist, only: [:show, :edit, :update]
def index
@q = Pricelist.search(params[:q])
@q.sorts = ['category asc', 'duration asc', 'operation_category asc',
'valid_from desc', 'valid_to asc'] if @q.sorts.empty?
@pricelists = @q.result.page(params[:page])
end
def new
@pricelist = Pricelist.new
end
def edit
end
def create
comma_support_for(:pricelist, :price)
@pricelist = Pricelist.new(pricelist_params)
if @pricelist.save
redirect_to admin_pricelists_url
else
render 'new'
end
end
def update
comma_support_for(:pricelist, :price)
if @pricelist.update_attributes(pricelist_params)
redirect_to admin_pricelists_url
else
render 'edit'
end
end
def destroy
@pricelist.destroy
redirect_to admin_pricelists_url
end
private
def set_pricelist
@pricelist = Pricelist.find(params[:id])
end
def pricelist_params
params.require(:pricelist).permit(:operation_category, :category, :price_category,
:duration, :price, :valid_from, :valid_to)
end
end

View file

@ -96,7 +96,7 @@ class Ability
can :manage, DNS::Zone
can :manage, DomainVersion
can :manage, ContactVersion
can :manage, Pricelist
can :manage, Billing::Price
can :manage, User
can :manage, ApiUser
can :manage, AdminUser

5
app/models/billing.rb Normal file
View file

@ -0,0 +1,5 @@
module Billing
def self.use_relative_model_naming?
true
end
end

View file

@ -0,0 +1,74 @@
module Billing
class Price < ActiveRecord::Base
self.auto_html5_validation = false
belongs_to :zone, class_name: 'DNS::Zone', required: true
validates :price, :valid_from, :operation_category, :duration, presence: true
validates :operation_category, inclusion: { in: Proc.new { |price| price.class.operation_categories } }
validates :duration, inclusion: { in: Proc.new { |price| price.class.durations } }
monetize :price_cents, allow_nil: true, numericality: { greater_than_or_equal_to: 0 }
after_initialize :init_values
def self.operation_categories
%w[create renew]
end
def self.durations
[
'3 months',
'6 months',
'9 months',
'1 year',
'2 years',
'3 years',
'4 years',
'5 years',
'6 years',
'7 years',
'8 years',
'9 years',
'10 years',
]
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)
end
def self.price_for(zone, operation_category, duration)
lists = valid.where(zone: zone, operation_category: operation_category, duration: duration)
return lists.first if lists.count == 1
lists.order(valid_from: :desc).first
end
def name
"#{operation_category} #{zone_name}"
end
def years_amount
duration.to_i
end
def price_decimal
price_cents / BigDecimal.new('100')
end
def zone_name
zone.origin
end
private
def to_partial_path
'price'
end
def init_values
return unless new_record?
self.valid_from = Time.zone.now.beginning_of_year unless valid_from
end
end
end

View file

@ -1,47 +0,0 @@
class Pricelist < ActiveRecord::Base
include Versions # version/pricelist_version.rb
scope :valid, lambda {
where(
"valid_from <= ? AND (valid_to >= ? OR valid_to IS NULL)",
Time.zone.now.end_of_day, Time.zone.now.beginning_of_day
)
}
scope :valid_at, ->(time){ where("valid_from IS NULL OR valid_from <= ?", time).where("valid_to IS NULL OR valid_to >= ?", time) }
monetize :price_cents
validates :price_cents, :price_currency, :price,
:valid_from, :category, :operation_category, :duration, presence: true
CATEGORIES = %w(ee pri.ee fie.ee med.ee com.ee)
OPERATION_CATEGORIES = %w(create renew)
DURATIONS = %w(1year 2years 3years)
after_initialize :init_values
def init_values
return unless new_record?
self.valid_from = Time.zone.now.beginning_of_year unless valid_from
end
def name
"#{operation_category} #{category}"
end
def years_amount
duration.to_i
end
def price_decimal
price_cents / BigDecimal.new('100')
end
class << self
def pricelist_for(zone, operation, period)
lists = valid.where(category: zone, operation_category: operation, duration: period)
return lists.first if lists.count == 1
lists.order(valid_from: :desc).first
end
end
end

View file

@ -19,8 +19,8 @@
%li= link_to t('.admin_users'), admin_admin_users_path
%li.divider
%li.dropdown-header= t(:billing)
- if can? :view, Pricelist
%li= link_to t(:pricelists), admin_pricelists_path
- if can? :view, Billing::Price
%li= link_to t('.prices'), admin_prices_path
%li= link_to t(:bank_statements), admin_bank_statements_path
%li= link_to t(:invoices), admin_invoices_path
%li= link_to t(:account_activities), admin_account_activities_path(created_after: 'today')

View file

@ -0,0 +1,60 @@
<%= form_for [:admin, price], html: { class: 'form-horizontal' } do |f| %>
<%= render 'form_errors', target: price %>
<div class="form-group">
<%= f.label :zone_id, class: 'col-sm-2 control-label' %>
<div class="col-sm-3">
<%= f.collection_select :zone_id, zones, :id, :origin, {}, class: 'form-control', required: true %>
</div>
</div>
<div class="form-group">
<%= f.label :operation_category, class: 'col-sm-2 control-label' %>
<div class="col-sm-3">
<%= f.select :operation_category, operation_categories, {}, class: 'form-control', required: true %>
</div>
</div>
<div class="form-group">
<%= f.label :duration, class: 'col-sm-2 control-label' %>
<div class="col-sm-3">
<%= f.select :duration, durations, {}, class: 'form-control', required: true %>
</div>
</div>
<div class="form-group">
<%= f.label :price, class: 'col-sm-2 control-label' %>
<div class="col-sm-3">
<div class="input-group">
<%= f.money_field :price, class: 'form-control', required: true %>
<div class="input-group-addon"><%= Money::default_currency.symbol %></div>
</div>
</div>
</div>
<div class="form-group">
<%= f.label :valid_from, class: 'col-sm-2 control-label' %>
<div class="col-sm-6">
<div class="input-group">
<%= f.text_field :valid_from, value: f.object.valid_from.try(:to_s, :dshort),
class: 'form-control datepicker' %>
<span class="input-group-addon">-</span>
<%= f.text_field :valid_to, value: f.object.valid_to.try(:to_s, :dshort),
class: 'form-control datepicker' %>
</div>
</div>
</div>
<hr>
<div class="row">
<div class="col-md-8 text-right">
<%= f.submit t(".#{f.object.new_record? ? 'create' : 'update'}_btn"), class: 'btn btn-success', name: nil %>
</div>
</div>
<% end %>

View file

@ -0,0 +1,15 @@
<tr>
<td><%= price.zone_name %></td>
<td><%= price.duration %></td>
<td><%= price.operation_category %></td>
<td><%= currency(price.price) %></td>
<td><%= l(price.valid_from, format: :ydate) %></td>
<td><%= l(price.valid_to, format: :ydate) %></td>
<td>
<%= link_to t('.edit_btn'), edit_admin_price_path(price), class: 'btn btn-xs btn-primary' %>
<%= link_to(t('.delete_btn'), admin_price_path(price),
method: :delete,
data: { confirm: t('.delete_btn_confirm') },
class: 'btn btn-xs btn-danger') %>
</td>
</tr>

View file

@ -0,0 +1,20 @@
<ol class="breadcrumb">
<li><%= link_to t('admin.billing.prices.index.title'), admin_prices_path %></li>
</ol>
<div class="page-header">
<h1><%= t '.title' %></h1>
</div>
<% if @price.persisted? && @price.errors.none? %>
<div class="alert alert-info">
<% active_price = ::Billing::Price.price_for(@price.zone, @price.operation_category, @price.duration) %>
<% if active_price %>
<%= t('active_price_for_this_operation_is', price: "#{active_price.price.amount.to_s} EUR") %>
<% else %>
<%= t('active_price_missing_for_this_operation') %>
<% end %>
</div>
<% end %>
<%= render 'form', price: @price %>

View file

@ -0,0 +1,41 @@
<div class="page-header">
<div class="row">
<div class="col-sm-10">
<h1><%= t '.title' %></h1>
</div>
<div class="col-sm-2 text-right">
<%= link_to t('.new_btn'), new_admin_price_path, class: 'btn btn-primary' %>
</div>
</div>
</div>
<% if @prices.present? %>
<table class="table table-hover table-bordered table-wrapped">
<thead>
<tr>
<th><%= sort_link(@q, 'zone_id', DNS::Zone.model_name.human) %></th>
<th><%= sort_link(@q, 'duration', ::Billing::Price.human_attribute_name(:duration)) %></th>
<th><%= sort_link(@q, 'operation_category', ::Billing::Price.human_attribute_name(:operation)) %></th>
<th><%= sort_link(@q, 'price', t(:price)) %></th>
<th><%= sort_link(@q, 'valid_from', t(:valid_from)) %></th>
<th><%= sort_link(@q, 'valid_to', t(:valid_to)) %></th>
<th></th>
</tr>
</thead>
<tbody>
<% @prices.each do |price| %>
<%= render 'price', price: price %>
<% end %>
</tbody>
</table>
<div class="row">
<div class="col-md-12">
<%= paginate @prices %>
</div>
</div>
<% else %>
<div class="alert alert-info"><%= t '.not_found' %></div>
<% end %>

View file

@ -0,0 +1,9 @@
<ol class="breadcrumb">
<li><%= link_to t('admin.billing.prices.index.title'), admin_prices_path %></li>
</ol>
<div class="page-header">
<h1><%= t '.title' %></h1>
</div>
<%= render 'form', price: @price %>

View file

@ -1,35 +0,0 @@
= form_for([:admin, @pricelist], multipart: true) do |f|
= render 'shared/errors', object: f.object
.row
.col-md-6
.form-group
= f.label :operation_category
= f.select(:operation_category, Pricelist::OPERATION_CATEGORIES, {}, { class: 'form-control' })
.form-group
= f.label :category, t(:category)
= f.select(:category, Pricelist::CATEGORIES, {}, { class: 'form-control' })
.form-group
= f.label :duration
= f.select(:duration, Pricelist::DURATIONS, {}, { class: 'form-control' })
.form-group
= f.label :price
.input-group
= f.text_field(:price, value: currency(f.object.price), class: 'form-control')
%span.input-group-addon= Money.default_currency
.form-group.input-daterange
= f.label :valid_from, t(:valid)
.input-group
= f.text_field(:valid_from, value: f.object.valid_from.try(:to_s, :dshort),
class: 'form-control datepicker')
%span.input-group-addon -
= f.text_field(:valid_to, value: f.object.valid_to.try(:to_s, :dshort),
class: 'form-control datepicker')
%hr
.row
.col-md-12.text-right
= button_tag(t(:save), class: 'btn btn-warning')
- if !f.object.new_record? && can?(:delete, f.object)
= link_to t(:delete), admin_pricelist_path(f.object),
method: :delete, data: { confirm: t(:are_you_sure_destroy) }, class: 'btn btn-danger'

View file

@ -1,14 +0,0 @@
.row
.col-sm-6
%h2.text-center-xs= "#{t(:edit)}: #{@pricelist.name}"
- if @pricelist.persisted? && @pricelist.errors.none?
%hr
- active_pricelist = Pricelist.pricelist_for(@pricelist.category, @pricelist.operation_category, @pricelist.duration)
- if active_pricelist
= t('active_price_for_this_operation_is', price: "#{active_pricelist.price.amount.to_s} #{active_pricelist.price_currency}")
- else
= t('active_price_missing_for_this_operation')
%hr
= render 'form'

View file

@ -1,43 +0,0 @@
.row
.col-sm-6
%h2.text-center-xs= t(:pricelists)
.col-sm-6
%h2.text-right.text-center-xs
= link_to(t(:new), new_admin_pricelist_path, class: 'btn btn-primary')
%hr
.row
.col-md-12
.table-responsive
%table.table.table-hover.table-bordered.table-condensed
%thead
%tr
%th{class: 'col-xs-2'}
= sort_link(@q, 'category', t(:category))
%th{class: 'col-xs-2'}
= sort_link(@q, 'duration', t(:duration))
%th{class: 'col-xs-2'}
= sort_link(@q, 'operation_category', t(:operation))
%th{class: 'col-xs-2'}
= sort_link(@q, 'price', t(:price))
%th{class: 'col-xs-2'}
= sort_link(@q, 'valid_from', t(:valid_from))
%th{class: 'col-xs-2'}
= sort_link(@q, 'valid_to', t(:valid_to))
%th{class: 'col-xs-2'}
= t(:action)
%tbody
- @pricelists.each do |pricelist|
%tr
%td= pricelist.category
%td= pricelist.duration
%td= pricelist.operation_category
%td= currency(pricelist.price)
%td= l(pricelist.valid_from, format: :ydate)
%td= l(pricelist.valid_to, format: :ydate)
%td= link_to(t(:edit), edit_admin_pricelist_path(pricelist), class: 'btn btn-xs btn-primary')
.row
.col-md-12
= paginate @pricelists

View file

@ -1,3 +0,0 @@
%h2= t(:new_price)
%hr
= render 'form'

View file

@ -0,0 +1,32 @@
en:
admin:
billing:
prices:
index:
title: Prices
new_btn: New price
not_found: No price found
new:
title: New price
create:
created: Price has been created
edit:
title: Edit price
update:
updated: Price has been updated
destroy:
destroyed: Price has been deleted
form:
create_btn: Create price
update_btn: Update price
price:
edit_btn: Edit
delete_btn: Delete
delete_btn_confirm: Are you sure you want to delete price?

View file

@ -4,6 +4,7 @@ en:
users: Users
api_users: API users
admin_users: Admin users
prices: Prices
archive: Archive
domain_history: Domain history
contact_history: Contact history

View file

@ -297,7 +297,6 @@ en:
description: 'Description'
delete: 'Delete'
are_you_sure: 'Are you sure?'
are_you_sure_destroy: 'You are going to delete, are you sure?'
back: 'Back'
new_domain: 'New domain'
registrar_name: 'Registrar name'
@ -826,10 +825,7 @@ en:
webserver_missing_client_cert_directive: 'Webserver missing client cert directive'
webserver_client_cert_directive_should_be_required: 'Webserver client cert directive should be required'
tech: Tech contact
pricelists: Pricelists
new_pricelist: New Pricelist
valid: Valid
category: Zone
object_is_not_eligible_for_renewal: 'Object is not eligible for renewal'
domain_expiring: 'Domain expiring'
domain_validation_rules: 'Domain validation rules'

View file

@ -173,7 +173,7 @@ Rails.application.routes.draw do
resources :zones, controller: 'dns/zones', except: %i[show]
resources :legal_documents
resources :keyrelays
resources :pricelists
resources :prices, controller: 'billing/prices', except: %i[show]
resources :mail_templates
resources :account_activities

View file

@ -0,0 +1,23 @@
class AddZoneToPrices < ActiveRecord::Migration
def up
add_reference :prices, :zone, index: true
add_foreign_key :prices, :zones
assign_zone_to_current_prices
change_column :prices, :zone_id, :integer, null: false
remove_column :prices, :category, :string
end
def down
raise ActiveRecord::IrreversibleMigration
end
private
def assign_zone_to_current_prices
Billing::Price.all.each do |price|
zone = DNS::Zone.find_by!(origin: price.category)
price.zone = zone
price.save!
end
end
end

View file

@ -963,7 +963,6 @@ ActiveRecord::Schema.define(version: 20170424115801) do
create_table "prices", force: :cascade do |t|
t.string "desc"
t.string "category"
t.integer "price_cents", null: false
t.datetime "valid_from"
t.datetime "valid_to"
@ -973,8 +972,11 @@ ActiveRecord::Schema.define(version: 20170424115801) do
t.datetime "updated_at", null: false
t.string "duration"
t.string "operation_category"
t.integer "zone_id", null: false
end
add_index "prices", ["zone_id"], name: "index_prices_on_zone_id", using: :btree
create_table "que_jobs", id: false, force: :cascade do |t|
t.integer "priority", limit: 2, default: 100, null: false
t.datetime "run_at", default: "now()", null: false
@ -1132,4 +1134,5 @@ ActiveRecord::Schema.define(version: 20170424115801) do
add_index "zones", ["origin"], name: "unique_zone_origin", unique: true, using: :btree
add_foreign_key "prices", "zones"
end

View file

@ -2496,7 +2496,6 @@ ALTER SEQUENCE people_id_seq OWNED BY people.id;
CREATE TABLE prices (
id integer NOT NULL,
"desc" character varying,
category character varying,
price_cents integer NOT NULL,
valid_from timestamp without time zone,
valid_to timestamp without time zone,
@ -2505,7 +2504,8 @@ CREATE TABLE prices (
created_at timestamp without time zone NOT NULL,
updated_at timestamp without time zone NOT NULL,
duration interval,
operation_category character varying
operation_category character varying,
zone_id integer NOT NULL
);
@ -4605,6 +4605,13 @@ CREATE UNIQUE INDEX index_people_on_email ON people USING btree (email);
CREATE UNIQUE INDEX index_people_on_reset_password_token ON people USING btree (reset_password_token);
--
-- Name: index_prices_on_zone_id; Type: INDEX; Schema: public; Owner: -; Tablespace:
--
CREATE INDEX index_prices_on_zone_id ON prices USING btree (zone_id);
--
-- Name: index_registrant_verifications_on_created_at; Type: INDEX; Schema: public; Owner: -; Tablespace:
--
@ -4710,6 +4717,14 @@ CREATE UNIQUE INDEX unique_data_migrations ON data_migrations USING btree (versi
CREATE UNIQUE INDEX unique_schema_migrations ON schema_migrations USING btree (version);
--
-- Name: fk_rails_78c376257f; Type: FK CONSTRAINT; Schema: public; Owner: -
--
ALTER TABLE ONLY prices
ADD CONSTRAINT fk_rails_78c376257f FOREIGN KEY (zone_id) REFERENCES zones(id);
--
-- PostgreSQL database dump complete
--
@ -5188,5 +5203,7 @@ INSERT INTO schema_migrations (version) VALUES ('20170423214500');
INSERT INTO schema_migrations (version) VALUES ('20170423222302');
INSERT INTO schema_migrations (version) VALUES ('20170423225333');
INSERT INTO schema_migrations (version) VALUES ('20170424115801');

View file

@ -77,11 +77,6 @@
<ellipse fill="none" stroke="black" cx="-215" cy="306" rx="109.381" ry="18"/>
<text text-anchor="middle" x="-215" y="309.7" font-family="Times,serif" font-size="14.00">Admin::WhiteIpsController</text>
</g>
<!-- Admin::PricelistsController -->
<g id="node14" class="node"><title>Admin::PricelistsController</title>
<ellipse fill="none" stroke="black" cx="193" cy="-354" rx="108.581" ry="18"/>
<text text-anchor="middle" x="193" y="-350.3" font-family="Times,serif" font-size="14.00">Admin::PricelistsController</text>
</g>
<!-- Admin::ZonefilesController -->
<g id="node15" class="node"><title>Admin::ZonefilesController</title>
<ellipse fill="none" stroke="black" cx="-46" cy="-390" rx="109.681" ry="18"/>

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 16 KiB

Before After
Before After

View file

@ -199,22 +199,6 @@
<text text-anchor="start" x="-492" y="216.2" font-family="Times,serif" font-size="14.00">set_registrar</text>
<text text-anchor="start" x="-492" y="231.2" font-family="Times,serif" font-size="14.00">white_ip_params</text>
</g>
<!-- Admin::PricelistsController -->
<g id="node14" class="node"><title>Admin::PricelistsController</title>
<path fill="none" stroke="black" d="M-488.5,-260.5C-488.5,-260.5 -345.5,-260.5 -345.5,-260.5 -339.5,-260.5 -333.5,-266.5 -333.5,-272.5 -333.5,-272.5 -333.5,-431.5 -333.5,-431.5 -333.5,-437.5 -339.5,-443.5 -345.5,-443.5 -345.5,-443.5 -488.5,-443.5 -488.5,-443.5 -494.5,-443.5 -500.5,-437.5 -500.5,-431.5 -500.5,-431.5 -500.5,-272.5 -500.5,-272.5 -500.5,-266.5 -494.5,-260.5 -488.5,-260.5"/>
<text text-anchor="middle" x="-417" y="-428.3" font-family="Times,serif" font-size="14.00">Admin::PricelistsController</text>
<polyline fill="none" stroke="black" points="-500.5,-420.5 -333.5,-420.5 "/>
<text text-anchor="start" x="-492.5" y="-405.3" font-family="Times,serif" font-size="14.00">create</text>
<text text-anchor="start" x="-492.5" y="-390.3" font-family="Times,serif" font-size="14.00">edit</text>
<text text-anchor="start" x="-492.5" y="-375.3" font-family="Times,serif" font-size="14.00">index</text>
<text text-anchor="start" x="-492.5" y="-360.3" font-family="Times,serif" font-size="14.00">new</text>
<text text-anchor="start" x="-492.5" y="-345.3" font-family="Times,serif" font-size="14.00">update</text>
<polyline fill="none" stroke="black" points="-500.5,-337.5 -333.5,-337.5 "/>
<polyline fill="none" stroke="black" points="-500.5,-313.5 -333.5,-313.5 "/>
<text text-anchor="start" x="-492.5" y="-298.3" font-family="Times,serif" font-size="14.00">_layout</text>
<text text-anchor="start" x="-492.5" y="-283.3" font-family="Times,serif" font-size="14.00">pricelist_params</text>
<text text-anchor="start" x="-492.5" y="-268.3" font-family="Times,serif" font-size="14.00">set_pricelist</text>
</g>
<!-- Admin::ZonefilesController -->
<g id="node15" class="node"><title>Admin::ZonefilesController</title>
<path fill="none" stroke="black" d="M-688.5,-240.5C-688.5,-240.5 -543.5,-240.5 -543.5,-240.5 -537.5,-240.5 -531.5,-246.5 -531.5,-252.5 -531.5,-252.5 -531.5,-321.5 -531.5,-321.5 -531.5,-327.5 -537.5,-333.5 -543.5,-333.5 -543.5,-333.5 -688.5,-333.5 -688.5,-333.5 -694.5,-333.5 -700.5,-327.5 -700.5,-321.5 -700.5,-321.5 -700.5,-252.5 -700.5,-252.5 -700.5,-246.5 -694.5,-240.5 -688.5,-240.5"/>

Before

Width:  |  Height:  |  Size: 70 KiB

After

Width:  |  Height:  |  Size: 69 KiB

Before After
Before After

View file

@ -1240,11 +1240,6 @@
<ellipse fill="none" stroke="black" cx="4191.99" cy="-523" rx="51.9908" ry="18"/>
<text text-anchor="middle" x="4191.99" y="-519.3" font-family="Times,serif" font-size="14.00">EppSession</text>
</g>
<!-- Pricelist -->
<g id="node54" class="node"><title>Pricelist</title>
<ellipse fill="none" stroke="black" cx="3258.99" cy="-199" rx="39.7935" ry="18"/>
<text text-anchor="middle" x="3258.99" y="-195.3" font-family="Times,serif" font-size="14.00">Pricelist</text>
</g>
<!-- Pricelist&#45;&gt;PricelistVersion -->
<g id="edge79" class="edge"><title>Pricelist&#45;&gt;PricelistVersion</title>
<path fill="none" stroke="#499b9a" d="M3250.87,-173.392C3244.19,-157.303 3233,-137.406 3215.99,-127 3168.48,-97.9313 3021.11,-117.025 2965.99,-109 2959.86,-108.107 2953.49,-106.998 2947.15,-105.777"/>

Before

Width:  |  Height:  |  Size: 134 KiB

After

Width:  |  Height:  |  Size: 133 KiB

Before After
Before After

View file

@ -1998,24 +1998,6 @@
<text text-anchor="start" x="4306.5" y="-2451.8" font-family="Times,serif" font-size="14.00">updated_at :datetime</text>
<text text-anchor="start" x="4306.5" y="-2436.8" font-family="Times,serif" font-size="14.00">registrar_id :integer</text>
</g>
<!-- Pricelist -->
<g id="node54" class="node"><title>Pricelist</title>
<path fill="none" stroke="black" d="M3610.5,-481C3610.5,-481 3745.5,-481 3745.5,-481 3751.5,-481 3757.5,-487 3757.5,-493 3757.5,-493 3757.5,-695 3757.5,-695 3757.5,-701 3751.5,-707 3745.5,-707 3745.5,-707 3610.5,-707 3610.5,-707 3604.5,-707 3598.5,-701 3598.5,-695 3598.5,-695 3598.5,-493 3598.5,-493 3598.5,-487 3604.5,-481 3610.5,-481"/>
<text text-anchor="middle" x="3678" y="-691.8" font-family="Times,serif" font-size="14.00">Pricelist</text>
<polyline fill="none" stroke="black" points="3598.5,-684 3757.5,-684 "/>
<text text-anchor="start" x="3606.5" y="-668.8" font-family="Times,serif" font-size="14.00">id :integer</text>
<text text-anchor="start" x="3606.5" y="-653.8" font-family="Times,serif" font-size="14.00">desc :string</text>
<text text-anchor="start" x="3606.5" y="-638.8" font-family="Times,serif" font-size="14.00">category :string</text>
<text text-anchor="start" x="3606.5" y="-623.8" font-family="Times,serif" font-size="14.00">price_cents :integer</text>
<text text-anchor="start" x="3606.5" y="-593.8" font-family="Times,serif" font-size="14.00">valid_from :datetime</text>
<text text-anchor="start" x="3606.5" y="-578.8" font-family="Times,serif" font-size="14.00">valid_to :datetime</text>
<text text-anchor="start" x="3606.5" y="-563.8" font-family="Times,serif" font-size="14.00">creator_str :string</text>
<text text-anchor="start" x="3606.5" y="-548.8" font-family="Times,serif" font-size="14.00">updator_str :string</text>
<text text-anchor="start" x="3606.5" y="-533.8" font-family="Times,serif" font-size="14.00">created_at :datetime</text>
<text text-anchor="start" x="3606.5" y="-518.8" font-family="Times,serif" font-size="14.00">updated_at :datetime</text>
<text text-anchor="start" x="3606.5" y="-503.8" font-family="Times,serif" font-size="14.00">duration :string</text>
<text text-anchor="start" x="3606.5" y="-488.8" font-family="Times,serif" font-size="14.00">operation_category :string</text>
</g>
<!-- Pricelist&#45;&gt;PricelistVersion -->
<g id="edge79" class="edge"><title>Pricelist&#45;&gt;PricelistVersion</title>
<path fill="none" stroke="#7416af" d="M3665.06,-472.647C3650.73,-402.404 3620.54,-318.837 3557,-273 3516.96,-244.115 3157.21,-276.99 3113,-255 3111.44,-254.226 3109.91,-253.402 3108.39,-252.533"/>

Before

Width:  |  Height:  |  Size: 246 KiB

After

Width:  |  Height:  |  Size: 244 KiB

Before After
Before After

View file

@ -1,8 +0,0 @@
Fabricator(:pricelist) do
valid_from 1.year.ago
valid_to 1.year.since
category 'ee'
duration '1year'
operation_category 'create'
price 10
end

View file

@ -0,0 +1,10 @@
FactoryGirl.define do
factory :price, class: Billing::Price do
price Money.from_amount(1)
valid_from Time.zone.parse('05.07.2010')
valid_to Time.zone.parse('05.07.2010')
duration '1 year'
operation_category Billing::Price.operation_categories.first
zone
end
end

View file

@ -1,10 +0,0 @@
FactoryGirl.define do
factory :pricelist do
valid_from Time.zone.parse('05.07.2010')
valid_to Time.zone.parse('05.07.2010')
category 'com'
duration '1year'
operation_category 'create'
price 1.to_money
end
end

View file

@ -0,0 +1,16 @@
require 'rails_helper'
RSpec.feature 'Deleting price in admin area', settings: false do
given!(:price) { create(:price) }
background do
sign_in_to_admin_area
end
scenario 'deletes price' do
visit admin_prices_url
click_link_or_button t('admin.billing.prices.price.delete_btn')
expect(page).to have_text(t('admin.billing.prices.destroy.destroyed'))
end
end

View file

@ -0,0 +1,25 @@
require 'rails_helper'
RSpec.feature 'Editing price in admin area', settings: false do
given!(:price) { create(:price) }
background do
sign_in_to_admin_area
end
scenario 'updates price' do
visit admin_prices_url
open_form
submit_form
expect(page).to have_text(t('admin.billing.prices.update.updated'))
end
def open_form
click_link_or_button t('admin.billing.prices.price.edit_btn')
end
def submit_form
click_link_or_button t('admin.billing.prices.form.update_btn')
end
end

View file

@ -0,0 +1,37 @@
require 'rails_helper'
RSpec.feature 'New price in admin area', settings: false do
given!(:zone) { create(:zone, origin: 'test') }
background do
sign_in_to_admin_area
end
scenario 'it creates new price' do
open_list
open_form
fill_form
submit_form
expect(page).to have_text(t('admin.billing.prices.create.created'))
end
def open_list
click_link_or_button t('admin.menu.prices')
end
def open_form
click_link_or_button t('admin.billing.prices.index.new_btn')
end
def fill_form
select 'test', from: 'price_zone_id'
select Billing::Price.operation_categories.first, from: 'price_operation_category'
select Billing::Price.durations.first, from: 'price_duration'
fill_in 'price_price', with: '1'
end
def submit_form
click_link_or_button t('admin.billing.prices.form.create_btn')
end
end

View file

@ -0,0 +1,138 @@
require 'rails_helper'
RSpec.describe Billing::Price do
it { is_expected.to monetize(:price) }
describe '::operation_categories', db: false do
it 'returns available 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
durations = [
'3 months',
'6 months',
'9 months',
'1 year',
'2 years',
'3 years',
'4 years',
'5 years',
'6 years',
'7 years',
'8 years',
'9 years',
'10 years',
]
expect(described_class.durations).to eq(durations)
end
end
describe 'zone validation', db: false do
subject(:price) { described_class.new }
it 'rejects absent' do
price.zone = nil
price.validate
expect(price.errors).to have_key(:zone)
end
end
describe 'price validation', db: false do
subject(:price) { described_class.new }
it 'rejects absent' do
price.price = nil
price.validate
expect(price.errors).to have_key(:price)
end
it 'rejects negative' do
price.price = -1
price.validate
expect(price.errors).to have_key(:price)
end
it 'accepts zero' do
price.price = 0
price.validate
expect(price.errors).to_not have_key(:price)
end
it 'accepts greater than zero' do
price.price = 1
price.validate
expect(price.errors).to_not have_key(:price)
end
end
describe 'duration validation', db: false do
subject(:price) { described_class.new }
it 'rejects absent' do
price.duration = nil
price.validate
expect(price.errors).to have_key(:duration)
end
it 'rejects invalid' do
price.duration = 'invalid'
price.validate
expect(price.errors).to have_key(:duration)
end
it 'accepts valid' do
price.duration = described_class.durations.first
price.validate
expect(price.errors).to_not have_key(:duration)
end
end
describe 'operation category validation', db: false do
subject(:price) { described_class.new }
it 'rejects absent' do
price.operation_category = nil
price.validate
expect(price.errors).to have_key(:operation_category)
end
it 'rejects invalid' do
price.operation_category = 'invalid'
price.validate
expect(price.errors).to have_key(:operation_category)
end
it 'accepts valid' do
price.operation_category = described_class.operation_categories.first
price.validate
expect(price.errors).to_not have_key(:operation_category)
end
end
describe '#name', db: false do
let(:price) { described_class.new }
before :example do
allow(price).to receive(:operation_category).and_return('category')
allow(price).to receive(:zone_name).and_return('zone')
end
it 'returns operation_category and zone name' do
expect(price.name).to eq('category zone')
end
end
describe '#zone_name', db: false do
let(:price) { described_class.new(zone: zone) }
let(:zone) { build_stubbed(:zone, origin: 'test') }
it 'returns zone name' do
expect(price.zone_name).to eq('test')
end
end
end

View file

@ -0,0 +1,46 @@
require 'rails_helper'
RSpec.describe 'admin price create', settings: false do
let!(:zone) { create(:zone, id: 1, origin: 'test') }
subject(:price) { Billing::Price.first }
before :example do
sign_in_to_admin_area
end
it 'creates new price' do
expect { post admin_prices_path, price: attributes_for(:price, zone_id: '1') }
.to change { Billing::Price.count }.from(0).to(1)
end
it 'saves zone' do
post admin_prices_path, price: attributes_for(:price, zone_id: '1')
expect(price.zone_id).to eq(1)
end
it 'saves operation category' do
post admin_prices_path, price:
attributes_for(:price, zone_id: '1', operation_category: Billing::Price.operation_categories.first)
expect(price.operation_category).to eq(Billing::Price.operation_categories.first)
end
it 'saves duration' do
post admin_prices_path, price: attributes_for(:price, zone_id: '1', duration: '1 year')
expect(price.duration).to eq('1 year')
end
it 'saves valid_from' do
post admin_prices_path, price: attributes_for(:price, zone_id: '1', valid_from: '2010-07-06')
expect(price.valid_from).to eq(Time.zone.parse('06.07.2010'))
end
it 'saves valid_to' do
post admin_prices_path, price: attributes_for(:price, zone_id: '1', valid_to: '2010-07-06')
expect(price.valid_to).to eq(Time.zone.parse('06.07.2010'))
end
it 'redirects to :index' do
post admin_prices_path, price: attributes_for(:price, zone_id: '1')
expect(response).to redirect_to admin_prices_url
end
end

View file

@ -0,0 +1,18 @@
require 'rails_helper'
RSpec.describe 'admin price destroy', settings: false do
let!(:price) { create(:price) }
before :example do
sign_in_to_admin_area
end
it 'deletes price' do
expect { delete admin_price_path(price) }.to change { Billing::Price.count }.from(1).to(0)
end
it 'redirects to :index' do
delete admin_price_path(price)
expect(response).to redirect_to admin_prices_url
end
end

View file

@ -0,0 +1,62 @@
require 'rails_helper'
RSpec.describe 'admin price update', settings: false do
before :example do
sign_in_to_admin_area
end
it 'updates zone' do
price = create(:price)
create(:zone, id: 2)
patch admin_price_path(price), price: attributes_for(:price, zone_id: '2')
price.reload
expect(price.zone_id).to eq(2)
end
it 'updates operation category' do
price = create(:price, operation_category: Billing::Price.operation_categories.first)
patch admin_price_path(price),
price: attributes_for(:price, operation_category: Billing::Price.operation_categories.second)
price.reload
expect(price.operation_category).to eq(Billing::Price.operation_categories.second)
end
it 'updates duration' do
price = create(:price, duration: '1 year')
patch admin_price_path(price), price: attributes_for(:price, duration: '2 years')
price.reload
expect(price.duration).to eq('2 years')
end
it 'updates valid_from' do
price = create(:price, valid_from: '2010-07-05')
patch admin_price_path(price), price: attributes_for(:price, valid_from: '2010-07-06')
price.reload
expect(price.valid_from).to eq(Time.zone.parse('06.07.2010'))
end
it 'updates valid_to' do
price = create(:price, valid_to: '2010-07-05')
patch admin_price_path(price), price: attributes_for(:price, valid_to: '2010-07-06')
price.reload
expect(price.valid_to).to eq(Time.zone.parse('06.07.2010'))
end
it 'redirects to :index' do
price = create(:price)
patch admin_price_path(price), price: attributes_for(:price)
expect(response).to redirect_to admin_prices_url
end
end

View file

@ -0,0 +1,67 @@
require 'rails_helper'
RSpec.describe 'EPP domain:create', settings: false do
let(:request) { post '/epp/command/create', frame: request_xml }
let!(:user) { create(:api_user_epp, registrar: registrar) }
let!(:contact) { create(:contact, code: 'test') }
let!(:zone) { create(:zone, origin: 'test') }
let!(:price) { create(:price,
duration: '1 year',
price: Money.from_amount(1),
operation_category: 'create',
valid_from: Time.zone.parse('05.07.2010'),
valid_to: Time.zone.parse('05.07.2010'),
zone: zone)
}
let(:request_xml) { <<-XML
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<epp xmlns="https://epp.tld.ee/schema/epp-ee-1.0.xsd">
<command>
<create>
<domain:create xmlns:domain="https://epp.tld.ee/schema/domain-eis-1.0.xsd">
<domain:name>test.test</domain:name>
<domain:registrant>test</domain:registrant>
</domain:create>
</create>
<extension>
<eis:extdata xmlns:eis="https://epp.tld.ee/schema/eis-1.0.xsd">
<eis:legalDocument type="pdf">#{valid_legal_document}</eis:legalDocument>
</eis:extdata>
</extension>
</command>
</epp>
XML
}
before :example do
travel_to Time.zone.parse('05.07.2010')
Setting.days_to_renew_domain_before_expire = 0
sign_in_to_epp_area(user: user)
end
context 'when account balance is sufficient' do
let!(:registrar) { create(:registrar_with_unlimited_balance) }
it 'creates domain' do
expect { request }.to change { Domain.count }.from(0).to(1)
end
specify do
request
expect(response).to have_code_of(1000)
end
end
context 'when account balance is not sufficient' do
let!(:registrar) { create(:registrar_with_zero_balance) }
it 'does not create domain' do
expect { request }.to_not change { Domain.count }
end
specify do
request
expect(response).to have_code_of(2104)
end
end
end

View file

@ -1,28 +1,22 @@
require 'rails_helper'
RSpec.describe 'EPP domain:create' do
subject(:response_xml) { Nokogiri::XML(response.body) }
subject(:response_code) { response_xml.xpath('//xmlns:result').first['code'] }
subject(:response_description) { response_xml.css('result msg').text }
RSpec.describe 'EPP domain:create', settings: false do
let(:request) { post '/epp/command/create', frame: request_xml }
let!(:registrar) { create(:registrar_with_unlimited_balance) }
let!(:user) { create(:api_user_epp, registrar: registrar) }
let!(:contact) { create(:contact, code: 'test') }
let!(:zone) { create(:zone, origin: 'test') }
let!(:price) { create(:price,
duration: '1 year',
price: Money.from_amount(1),
operation_category: 'create',
valid_from: Time.zone.parse('05.07.2010'),
valid_to: Time.zone.parse('05.07.2010'),
zone: zone)
}
before :example do
travel_to Time.zone.parse('05.07.2010')
registrar = create(:registrar)
user = create(:api_user_epp, registrar: registrar)
create(:account, registrar: registrar, balance: 1.0)
create(:contact, code: 'test')
create(:pricelist,
category: 'com',
duration: '1year',
price: 1.to_money,
operation_category: 'create',
valid_from: Time.zone.parse('05.07.2010'),
valid_to: Time.zone.parse('05.07.2010')
)
sign_in_to_epp_area(user: user)
end
@ -38,7 +32,7 @@ RSpec.describe 'EPP domain:create' do
<command>
<create>
<domain:create xmlns:domain="https://epp.tld.ee/schema/domain-eis-1.0.xsd">
<domain:name>test.com</domain:name>
<domain:name>test.test</domain:name>
<domain:period unit="y">1</domain:period>
<domain:ns>
<domain:hostAttr>
@ -47,13 +41,11 @@ RSpec.describe 'EPP domain:create' do
</domain:hostAttr>
</domain:ns>
<domain:registrant>test</domain:registrant>
<domain:contact type="admin">test</domain:contact>
<domain:contact type="tech">test</domain:contact>
</domain:create>
</create>
<extension>
<eis:extdata xmlns:eis="https://epp.tld.ee/schema/eis-1.0.xsd">
<eis:legalDocument type="pdf">#{Base64.encode64('a' * 5000)}</eis:legalDocument>
<eis:legalDocument type="pdf">#{valid_legal_document}</eis:legalDocument>
</eis:extdata>
</extension>
</command>
@ -65,18 +57,13 @@ RSpec.describe 'EPP domain:create' do
Setting.ns_min_count = 2
end
it 'returns epp code of 2308' do
post '/epp/command/create', frame: request_xml
expect(response_code).to eq('2308')
it 'does not create domain' do
expect { request }.to_not change { Domain.count }
end
it 'returns epp description' do
post '/epp/command/create', frame: request_xml
description = 'Data management policy violation;' \
" Nameserver count must be between #{Setting.ns_min_count}-#{Setting.ns_max_count}" \
' for active domains [nameservers]'
expect(response_description).to eq(description)
specify do
request
expect(response).to have_code_of(2308)
end
end
@ -87,16 +74,14 @@ RSpec.describe 'EPP domain:create' do
<command>
<create>
<domain:create xmlns:domain="https://epp.tld.ee/schema/domain-eis-1.0.xsd">
<domain:name>test.com</domain:name>
<domain:name>test.test</domain:name>
<domain:period unit="y">1</domain:period>
<domain:registrant>test</domain:registrant>
<domain:contact type="admin">test</domain:contact>
<domain:contact type="tech">test</domain:contact>
</domain:create>
</create>
<extension>
<eis:extdata xmlns:eis="https://epp.tld.ee/schema/eis-1.0.xsd">
<eis:legalDocument type="pdf">#{Base64.encode64('a' * 5000)}</eis:legalDocument>
<eis:legalDocument type="pdf">#{valid_legal_document}</eis:legalDocument>
</eis:extdata>
</extension>
</command>
@ -104,21 +89,20 @@ RSpec.describe 'EPP domain:create' do
XML
}
it 'returns epp code of 1000' do
post '/epp/command/create', frame: request_xml
expect(response_code).to eq('1000'), "Expected EPP code of 1000, got #{response_code} (#{response_description})"
end
it 'creates new domain' do
expect { post '/epp/command/create', frame: request_xml }.to change { Domain.count }.from(0).to(1)
expect { request }.to change { Domain.count }.from(0).to(1)
end
describe 'new domain' do
it 'has status of inactive' do
post '/epp/command/create', frame: request_xml
domain = Domain.find_by(name: 'test.com')
expect(domain.statuses).to include(DomainStatus::INACTIVE)
end
request
expect(Domain.first.statuses).to include(DomainStatus::INACTIVE)
end
end
specify do
request
expect(response).to have_code_of(1000)
end
end
end

View file

@ -0,0 +1,59 @@
require 'rails_helper'
RSpec.describe 'EPP domain:create', settings: false do
let(:request) { post '/epp/command/create', frame: request_xml }
let!(:user) { create(:api_user_epp, registrar: registrar) }
let!(:contact) { create(:contact, code: 'test') }
let!(:zone) { create(:zone, origin: 'test') }
let!(:registrar) { create(:registrar_with_unlimited_balance) }
let!(:price) { create(:price,
duration: '1 year',
price: Money.from_amount(1),
operation_category: 'create',
valid_from: Time.zone.parse('05.07.2010'),
valid_to: Time.zone.parse('05.07.2010'),
zone: zone)
}
let(:request_xml) { <<-XML
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<epp xmlns="https://epp.tld.ee/schema/epp-ee-1.0.xsd">
<command>
<create>
<domain:create xmlns:domain="https://epp.tld.ee/schema/domain-eis-1.0.xsd">
<domain:name>test.test</domain:name>
<domain:registrant>test</domain:registrant>
</domain:create>
</create>
<extension>
<eis:extdata xmlns:eis="https://epp.tld.ee/schema/eis-1.0.xsd">
<eis:legalDocument type="pdf">#{valid_legal_document}</eis:legalDocument>
</eis:extdata>
</extension>
</command>
</epp>
XML
}
before :example do
travel_to Time.zone.parse('05.07.2010 10:30')
Setting.days_to_renew_domain_before_expire = 0
sign_in_to_epp_area(user: user)
end
context 'when period is absent' do
it 'creates domain' do
expect { request }.to change { Domain.count }.from(0).to(1)
end
it 'uses default duration of 1 year' do
request
valid_to = (Time.zone.parse('05.07.2010') + 1.year + 1.day).beginning_of_day
expect(Domain.first.valid_to).to eq(valid_to)
end
specify do
request
expect(response).to have_code_of(1000)
end
end
end

View file

@ -0,0 +1,66 @@
require 'rails_helper'
RSpec.describe 'EPP domain:create', settings: false do
let(:request) { post '/epp/command/create', frame: request_xml }
let!(:user) { create(:api_user_epp, registrar: registrar) }
let!(:contact) { create(:contact, code: 'test') }
let!(:zone) { create(:zone, origin: 'test') }
let!(:registrar) { create(:registrar_with_unlimited_balance) }
let(:request_xml) { <<-XML
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<epp xmlns="https://epp.tld.ee/schema/epp-ee-1.0.xsd">
<command>
<create>
<domain:create xmlns:domain="https://epp.tld.ee/schema/domain-eis-1.0.xsd">
<domain:name>test.test</domain:name>
<domain:period unit="y">1</domain:period>
<domain:registrant>test</domain:registrant>
</domain:create>
</create>
<extension>
<eis:extdata xmlns:eis="https://epp.tld.ee/schema/eis-1.0.xsd">
<eis:legalDocument type="pdf">#{valid_legal_document}</eis:legalDocument>
</eis:extdata>
</extension>
</command>
</epp>
XML
}
before :example do
travel_to Time.zone.parse('05.07.2010')
Setting.days_to_renew_domain_before_expire = 0
sign_in_to_epp_area(user: user)
end
context 'when price is present' do
let!(:price) { create(:price,
duration: '1 year',
price: Money.from_amount(1),
operation_category: 'create',
valid_from: Time.zone.parse('05.07.2010'),
valid_to: Time.zone.parse('05.07.2010'),
zone: zone)
}
it 'creates domain' do
expect { request }.to change { Domain.count }.from(0).to(1)
end
specify do
request
expect(response).to have_code_of(1000)
end
end
context 'when price is absent' do
it 'does not create domain' do
expect { request }.to_not change { Domain.count }
end
specify do
request
expect(response).to have_code_of(2104)
end
end
end

View file

@ -1,28 +1,22 @@
require 'rails_helper'
RSpec.describe 'EPP domain:create' do
subject(:response_xml) { Nokogiri::XML(response.body) }
subject(:response_code) { response_xml.xpath('//xmlns:result').first['code'] }
subject(:response_description) { response_xml.css('result msg').text }
RSpec.describe 'EPP domain:create', settings: false do
let(:request) { post '/epp/command/create', frame: request_xml }
let!(:registrar) { create(:registrar_with_unlimited_balance) }
let!(:user) { create(:api_user_epp, registrar: registrar) }
let!(:contact) { create(:contact, code: 'test') }
let!(:zone) { create(:zone, origin: 'test') }
let!(:price) { create(:price,
duration: '1 year',
price: Money.from_amount(1),
operation_category: 'create',
valid_from: Time.zone.parse('05.07.2010'),
valid_to: Time.zone.parse('05.07.2010'),
zone: zone)
}
before :example do
travel_to Time.zone.parse('05.07.2010')
registrar = create(:registrar)
user = create(:api_user_epp, registrar: registrar)
create(:account, registrar: registrar, balance: 1.0)
create(:contact, code: 'test')
create(:pricelist,
category: 'com',
duration: '1year',
price: 1.to_money,
operation_category: 'create',
valid_from: Time.zone.parse('05.07.2010'),
valid_to: Time.zone.parse('05.07.2010')
)
sign_in_to_epp_area(user: user)
end
@ -39,7 +33,7 @@ RSpec.describe 'EPP domain:create' do
<command>
<create>
<domain:create xmlns:domain="https://epp.tld.ee/schema/domain-eis-1.0.xsd">
<domain:name>test.com</domain:name>
<domain:name>test.test</domain:name>
<domain:period unit="y">1</domain:period>
<domain:ns>
<domain:hostAttr>
@ -48,13 +42,11 @@ RSpec.describe 'EPP domain:create' do
</domain:hostAttr>
</domain:ns>
<domain:registrant>test</domain:registrant>
<domain:contact type="admin">test</domain:contact>
<domain:contact type="tech">test</domain:contact>
</domain:create>
</create>
<extension>
<eis:extdata xmlns:eis="https://epp.tld.ee/schema/eis-1.0.xsd">
<eis:legalDocument type="pdf">#{Base64.encode64('a' * 5000)}</eis:legalDocument>
<eis:legalDocument type="pdf">#{valid_legal_document}</eis:legalDocument>
</eis:extdata>
</extension>
</command>
@ -62,9 +54,13 @@ RSpec.describe 'EPP domain:create' do
XML
}
it 'returns epp code of 1000' do
post '/epp/command/create', frame: request_xml
expect(response_code).to eq('1000'), "Expected EPP code of 1000, got #{response_code} (#{response_description})"
it 'creates new domain' do
expect { request }.to change { Domain.count }.from(0).to(1)
end
specify do
request
expect(response).to have_code_of(1000)
end
end
@ -75,16 +71,14 @@ RSpec.describe 'EPP domain:create' do
<command>
<create>
<domain:create xmlns:domain="https://epp.tld.ee/schema/domain-eis-1.0.xsd">
<domain:name>test.com</domain:name>
<domain:name>test.test</domain:name>
<domain:period unit="y">1</domain:period>
<domain:registrant>test</domain:registrant>
<domain:contact type="admin">test</domain:contact>
<domain:contact type="tech">test</domain:contact>
</domain:create>
</create>
<extension>
<eis:extdata xmlns:eis="https://epp.tld.ee/schema/eis-1.0.xsd">
<eis:legalDocument type="pdf">#{Base64.encode64('a' * 5000)}</eis:legalDocument>
<eis:legalDocument type="pdf">#{valid_legal_document}</eis:legalDocument>
</eis:extdata>
</extension>
</command>
@ -92,9 +86,13 @@ RSpec.describe 'EPP domain:create' do
XML
}
it 'returns epp code of 2003' do
post '/epp/command/create', frame: request_xml
expect(response_code).to eq('2003')
it 'does not create domain' do
expect { request }.to_not change { Domain.count }
end
specify do
request
expect(response).to have_code_of(2003)
end
end
end

View file

@ -3,13 +3,14 @@ require 'rails_helper'
RSpec.describe 'EPP domain:renew' do
let(:request) { post '/epp/command/renew', frame: request_xml }
let!(:user) { create(:api_user_epp, registrar: registrar) }
let!(:pricelist) { create(:pricelist,
category: 'com',
let!(:zone) { create(:zone, origin: 'test') }
let!(:price) { create(:price,
duration: '1 year',
price: Money.from_amount(1),
operation_category: 'renew',
valid_from: Time.zone.parse('05.07.2010'),
valid_to: Time.zone.parse('05.07.2010'))
valid_to: Time.zone.parse('05.07.2010'),
zone: zone)
}
before :example do
@ -22,7 +23,7 @@ RSpec.describe 'EPP domain:renew' do
let!(:registrar) { create(:registrar_with_unlimited_balance) }
let!(:domain) { create(:domain,
registrar: registrar,
name: 'test.com',
name: 'test.test',
expire_time: Time.zone.parse('05.07.2010'))
}
let(:request_xml) { <<-XML
@ -31,7 +32,7 @@ RSpec.describe 'EPP domain:renew' do
<command>
<renew>
<domain:renew xmlns:domain="https://epp.tld.ee/schema/domain-eis-1.0.xsd">
<domain:name>test.com</domain:name>
<domain:name>test.test</domain:name>
<domain:curExpDate>2010-07-05</domain:curExpDate>
<domain:period unit="y">1</domain:period>
</domain:renew>
@ -57,7 +58,7 @@ RSpec.describe 'EPP domain:renew' do
let!(:registrar) { create(:registrar_with_zero_balance) }
let!(:domain) { create(:domain,
registrar: registrar,
name: 'test.com',
name: 'test.test',
expire_time: Time.zone.parse('05.07.2010'))
}
let(:request_xml) { <<-XML
@ -66,7 +67,7 @@ RSpec.describe 'EPP domain:renew' do
<command>
<renew>
<domain:renew xmlns:domain="https://epp.tld.ee/schema/domain-eis-1.0.xsd">
<domain:name>test.com</domain:name>
<domain:name>test.test</domain:name>
<domain:curExpDate>2010-07-04</domain:curExpDate>
<domain:period unit="y">1</domain:period>
</domain:renew>

View file

@ -4,13 +4,14 @@ RSpec.describe 'EPP domain:renew' do
let(:request) { post '/epp/command/renew', frame: request_xml }
let!(:user) { create(:api_user_epp, registrar: registrar) }
let!(:registrar) { create(:registrar_with_unlimited_balance) }
let!(:pricelist) { create(:pricelist,
category: 'com',
let!(:zone) { create(:zone, origin: 'test') }
let!(:price) { create(:price,
duration: '1 year',
price: Money.from_amount(1),
operation_category: 'renew',
valid_from: Time.zone.parse('05.07.2010'),
valid_to: Time.zone.parse('05.07.2010'))
valid_to: Time.zone.parse('05.07.2010'),
zone: zone)
}
before :example do
@ -22,7 +23,7 @@ RSpec.describe 'EPP domain:renew' do
context 'when given expire time and current match' do
let!(:domain) { create(:domain,
registrar: registrar,
name: 'test.com',
name: 'test.test',
expire_time: Time.zone.parse('05.07.2010'))
}
let(:request_xml) { <<-XML
@ -31,7 +32,7 @@ RSpec.describe 'EPP domain:renew' do
<command>
<renew>
<domain:renew xmlns:domain="https://epp.tld.ee/schema/domain-eis-1.0.xsd">
<domain:name>test.com</domain:name>
<domain:name>test.test</domain:name>
<domain:curExpDate>2010-07-05</domain:curExpDate>
<domain:period unit="y">1</domain:period>
</domain:renew>
@ -56,7 +57,7 @@ RSpec.describe 'EPP domain:renew' do
context 'when given expire time and current do not match' do
let!(:domain) { create(:domain,
registrar: registrar,
name: 'test.com',
name: 'test.test',
expire_time: Time.zone.parse('05.07.2010'))
}
let(:request_xml) { <<-XML
@ -65,7 +66,7 @@ RSpec.describe 'EPP domain:renew' do
<command>
<renew>
<domain:renew xmlns:domain="https://epp.tld.ee/schema/domain-eis-1.0.xsd">
<domain:name>test.com</domain:name>
<domain:name>test.test</domain:name>
<domain:curExpDate>2010-07-04</domain:curExpDate>
<domain:period unit="y">1</domain:period>
</domain:renew>