1
0
mirror of https://github.com/LaCasemate/fab-manager.git synced 2025-01-17 06:52:27 +01:00

Merge branch 'tests' into dev

This commit is contained in:
cyril 2016-04-20 11:58:09 +02:00
commit 1099adb208
160 changed files with 12317 additions and 1216 deletions

13
Gemfile
View File

@ -34,12 +34,6 @@ group :development, :test do
# Spring speeds up development by keeping your application running in the background. Read more: https://github.com/rails/spring
gem 'spring'
gem 'factory_girl_rails'
gem 'rspec-rails'
gem 'spring-commands-rspec'
gem 'guard-rspec', require: false
gem 'railroady'
end
@ -62,6 +56,11 @@ end
group :test do
gem 'database_cleaner'
gem 'faker'
gem 'test_after_commit'
gem 'minitest-reporters'
gem 'webmock'
gem 'vcr'
gem 'byebug'
end
group :production do
@ -137,4 +136,4 @@ gem 'chroma'
gem 'protected_attributes'
gem 'message_format'
gem 'message_format'

View File

@ -41,6 +41,7 @@ GEM
thread_safe (~> 0.3, >= 0.3.4)
tzinfo (~> 1.1)
addressable (2.3.8)
ansi (1.5.0)
arel (6.0.3)
autoprefixer-rails (5.1.8)
execjs
@ -58,6 +59,7 @@ GEM
sass (>= 3.2.19)
buftok (0.2.0)
builder (3.2.2)
byebug (8.2.3)
camertron-eprun (1.1.0)
capistrano (2.15.5)
highline
@ -80,7 +82,6 @@ GEM
chroma (0.0.1)
chunky_png (1.3.4)
cldr-plurals-runtime-rb (1.0.1)
coderay (1.1.0)
coercible (1.0.0)
descendants_tracker (~> 0.0.1)
coffee-rails (4.1.0)
@ -107,6 +108,8 @@ GEM
sass-rails (<= 5.0.1)
sprockets (< 2.13)
connection_pool (2.2.0)
crack (0.4.3)
safe_yaml (~> 1.0.0)
database_cleaner (1.4.1)
debug_inspector (0.0.2)
descendants_tracker (0.0.4)
@ -120,7 +123,6 @@ GEM
warden (~> 1.2.3)
devise-async (0.9.0)
devise (~> 3.2)
diff-lcs (1.2.5)
domain_name (0.5.25)
unf (>= 0.0.5, < 1.0.0)
elasticsearch (1.0.12)
@ -146,11 +148,6 @@ GEM
equalizer (0.0.11)
erubis (2.7.0)
execjs (2.4.0)
factory_girl (4.5.0)
activesupport (>= 3.0.0)
factory_girl_rails (4.5.0)
factory_girl (~> 4.5.0)
railties (>= 3.0.0)
faker (1.4.3)
i18n (~> 0.5)
faraday (0.9.1)
@ -163,25 +160,11 @@ GEM
foreman (0.78.0)
thor (~> 0.19.1)
forgery (0.6.0)
formatador (0.2.5)
friendly_id (5.1.0)
activerecord (>= 4.0.0)
globalid (0.3.6)
activesupport (>= 4.1.0)
guard (2.12.5)
formatador (>= 0.2.4)
listen (~> 2.7)
lumberjack (~> 1.0)
nenv (~> 0.1)
notiffany (~> 0.0)
pry (>= 0.9.12)
shellany (~> 0.0)
thor (>= 0.18.1)
guard-compat (1.2.1)
guard-rspec (4.5.0)
guard (~> 2.1)
guard-compat (~> 1.1)
rspec (>= 2.99.0, < 4.0)
hashdiff (0.3.0)
hashie (3.4.2)
highline (1.7.1)
hike (1.2.3)
@ -211,29 +194,27 @@ GEM
letter_opener (1.3.0)
launchy (~> 2.2)
libv8 (3.16.14.11)
listen (2.10.0)
celluloid (~> 0.16.0)
rb-fsevent (>= 0.9.3)
rb-inotify (>= 0.9)
loofah (2.0.3)
nokogiri (>= 1.5.9)
lumberjack (1.0.9)
mail (2.6.3)
mime-types (>= 1.16, < 3)
memoizable (0.4.2)
thread_safe (~> 0.3, >= 0.3.1)
message_format (0.0.3)
twitter_cldr (~> 3.1)
method_source (0.8.2)
mime-types (2.99)
mini_magick (4.2.0)
mini_portile (0.6.2)
minitest (5.8.3)
minitest-reporters (1.1.8)
ansi
builder
minitest (>= 5.0)
ruby-progressbar
multi_json (1.11.2)
multi_xml (0.5.5)
multipart-post (2.0.0)
naught (1.0.0)
nenv (0.2.0)
net-scp (1.2.1)
net-ssh (>= 2.6.5)
net-sftp (2.1.2)
@ -244,9 +225,6 @@ GEM
netrc (0.10.3)
nokogiri (1.6.6.4)
mini_portile (~> 0.6.0)
notiffany (0.0.6)
nenv (~> 0.1)
shellany (~> 0.0)
notify_with (0.0.2)
jbuilder (~> 2.0)
rails (>= 4.2.0)
@ -273,10 +251,6 @@ GEM
prawn-table (0.2.1)
protected_attributes (1.1.3)
activemodel (>= 4.0.1, < 5.0)
pry (0.10.1)
coderay (~> 1.1.0)
method_source (~> 0.8.1)
slop (~> 3.4)
puma (2.11.1)
rack (>= 1.1, < 2.0)
pundit (1.0.0)
@ -338,31 +312,12 @@ GEM
mime-types (>= 1.16, < 3.0)
netrc (~> 0.7)
rolify (4.0.0)
rspec (3.2.0)
rspec-core (~> 3.2.0)
rspec-expectations (~> 3.2.0)
rspec-mocks (~> 3.2.0)
rspec-core (3.2.2)
rspec-support (~> 3.2.0)
rspec-expectations (3.2.0)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.2.0)
rspec-mocks (3.2.1)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.2.0)
rspec-rails (3.2.1)
actionpack (>= 3.0, < 4.3)
activesupport (>= 3.0, < 4.3)
railties (>= 3.0, < 4.3)
rspec-core (~> 3.2.0)
rspec-expectations (~> 3.2.0)
rspec-mocks (~> 3.2.0)
rspec-support (~> 3.2.0)
rspec-support (3.2.2)
ruby-progressbar (1.7.5)
rufus-scheduler (3.0.9)
tzinfo
rvm-capistrano (1.5.6)
capistrano (~> 2.15.4)
safe_yaml (1.0.4)
sass (3.4.13)
sass-rails (5.0.1)
railties (>= 4.0.0, < 5.0)
@ -376,7 +331,6 @@ GEM
seed_dump (3.2.2)
activerecord (~> 4)
activesupport (~> 4)
shellany (0.0.1)
sidekiq (3.3.4)
celluloid (>= 0.16.0)
connection_pool (>= 2.1.1)
@ -392,10 +346,7 @@ GEM
rack (~> 1.4)
rack-protection (~> 1.4)
tilt (>= 1.3, < 3)
slop (3.6.0)
spring (1.3.5)
spring-commands-rspec (1.0.4)
spring (>= 0.9.1)
sprockets (2.12.4)
hike (~> 1.2)
multi_json (~> 1.0)
@ -408,6 +359,8 @@ GEM
stripe (1.30.2)
json (~> 1.8.1)
rest-client (~> 1.4)
test_after_commit (1.0.0)
activerecord (>= 3.2)
therubyracer (0.12.0)
libv8 (~> 3.16.14.0)
ref
@ -447,6 +400,7 @@ GEM
kgio (~> 2.6)
rack
raindrops (~> 0.7)
vcr (3.0.1)
virtus (1.0.5)
axiom-types (~> 0.1)
coercible (~> 1.0)
@ -459,6 +413,10 @@ GEM
binding_of_caller (>= 0.7.2)
railties (>= 4.0)
sprockets-rails (>= 2.0, < 4.0)
webmock (1.24.2)
addressable (>= 2.3.6)
crack (>= 0.3.2)
hashdiff
PLATFORMS
ruby
@ -469,6 +427,7 @@ DEPENDENCIES
active_record_query_trace
awesome_print
bootstrap-sass
byebug
capistrano
capistrano-maintenance (= 0.0.5)
capistrano-sidekiq
@ -482,20 +441,19 @@ DEPENDENCIES
elasticsearch-model
elasticsearch-persistence
elasticsearch-rails
factory_girl_rails
faker
figaro
font-awesome-rails
foreman
forgery
friendly_id (~> 5.1.0)
guard-rspec
jbuilder (~> 2.0)
jquery-rails
kaminari
letter_opener
message_format
mini_magick
minitest-reporters
notify_with
oj
omniauth
@ -513,7 +471,6 @@ DEPENDENCIES
recurrence
responders (~> 2.0)
rolify
rspec-rails
rvm-capistrano
sass-rails (= 5.0.1)
sdoc (~> 0.4.0)
@ -522,14 +479,16 @@ DEPENDENCIES
sidekiq-cron
sinatra
spring
spring-commands-rspec
stripe (= 1.30.2)
test_after_commit
therubyracer (= 0.12.0)
twitter
twitter-text
uglifier (>= 1.3.0)
unicorn
vcr
web-console (~> 2.0)
webmock
BUNDLED WITH
1.10.6
1.11.2

View File

@ -530,7 +530,7 @@ After modifying any values concerning the localisation, restart the application
## Known issues
- When browsing a machine page, you may encounter an "InterceptError" in the console and the loading bar will stop loading before reaching its ending.
This may append if the machine was created through a seed file without any image.
This may happen if the machine was created through a seed file without any image.
To solve this, simply add an image to the machine's profile and refresh the web page.
- When starting the Ruby on Rails server (eg. `foreman s`) you may receive the following error:
@ -539,12 +539,30 @@ After modifying any values concerning the localisation, restart the application
web.1 | Exiting
worker.1 | ...lib/redis/client.rb...:in `_parse_options'
This may happens when the `application.yml` file is missing.
This may happen when the `application.yml` file is missing.
To solve this issue copy `config/application.yml.default` to `config/application.yml`.
This is required before the first start.
- Due to a stripe limitation, you won't be ble to create plans longer than one year.
- When running the tests suite with `rake test`, all tests may fail with errors similar to the following:
Error:
...
ActiveRecord::InvalidForeignKey: PG::ForeignKeyViolation: ERROR: insert or update on table "..." violates foreign key constraint "fk_rails_..."
DETAIL: Key (group_id)=(1) is not present in table "groups".
: ...
test_after_commit (1.0.0) lib/test_after_commit/database_statements.rb:11:in `block in transaction'
test_after_commit (1.0.0) lib/test_after_commit/database_statements.rb:5:in `transaction'
This is due to an ActiveRecord behavior witch disable referential integrity in PostgreSQL to load the fixtures.
PostgreSQL will prevent any users to disable referential integrity on the fly if they doesn't have the `SUPERUSER` role.
To fix that, logon as the `postgres` user and run the PostgreSQL shell (see [Setup the FabManager database in PostgreSQL](#setup-fabmanager-in-postgresql) for an example).
Then, run the following command (replace `sleede` with your test database user, as specified in your database.yml):
ALTER ROLE sleede WITH SUPERUSER;
DO NOT do this in a production environment, as this would lead to a serious security issue.
<a name="related-documentation"></a>
## Related Documentation

View File

@ -28,10 +28,8 @@ class API::ReservationsController < API::ApiController
is_reserve = @reservation.save_with_payment
end
if is_reserve
reservation_user = @reservation.user
if @reservation.reservable_type == 'Training' and is_first_training_and_active_subscription(reservation_user)
reservation_user.subscription.update_expired_date_with_first_training(@reservation.slots.first.start_at)
end
SubscriptionExtensionAfterReservation.new(@reservation).extend_subscription_if_eligible
render :show, status: :created, location: @reservation
else
render json: @reservation.errors, status: :unprocessable_entity
@ -57,8 +55,4 @@ class API::ReservationsController < API::ApiController
:nb_reserve_places, :nb_reserve_reduced_places,
slots_attributes: [:id, :start_at, :end_at, :availability_id, :offered])
end
def is_first_training_and_active_subscription(user)
user.reservations.where(reservable_type: 'Training').size == 1 and user.subscription and !user.subscription.is_expired?
end
end

View File

@ -6,10 +6,7 @@ class API::SlotsController < API::ApiController
def update
authorize @slot
if @slot.update(slot_params)
reservation_user = @slot.reservation.user
if @slot.reservation.reservable_type == 'Training' and is_first_training_and_active_subscription(reservation_user)
reservation_user.subscription.update_expired_date_with_first_training(@slot.start_at)
end
SubscriptionExtensionAfterReservation.new(@slot.reservation).extend_subscription_if_eligible
render :show, status: :created, location: @slot
else
render json: @slot.errors, status: :unprocessable_entity
@ -29,8 +26,4 @@ class API::SlotsController < API::ApiController
def slot_params
params.require(:slot).permit(:start_at, :end_at, :availability_id)
end
def is_first_training_and_active_subscription(user)
user.reservations.where(reservable_type: 'Training').size == 1 and user.subscription and !user.subscription.is_expired?
end
end

View File

@ -14,16 +14,18 @@ class API::SubscriptionsController < API::ApiController
else
if current_user.is_admin?
@subscription = Subscription.find_or_initialize_by(user_id: subscription_params[:user_id])
# @subscription.expired_at = nil
@subscription.update_column(:expired_at, nil) unless @subscription.new_record? # very important
@subscription.attributes = subscription_params
is_subscribe = @subscription.save_with_local_payment(!User.find(subscription_params[:user_id]).invoicing_disabled?)
else
@subscription = Subscription.find_or_initialize_by(user_id: current_user.id)
# @subscription.expired_at = nil
@subscription.update_column(:expired_at, nil) unless @subscription.new_record? # very important
@subscription.attributes = subscription_params.merge(user_id: current_user.id)
is_subscribe = @subscription.save_with_payment
if valid_card_token?(subscription_params[:card_token])
@subscription.update_column(:expired_at, nil) unless @subscription.new_record? # very important
@subscription.attributes = subscription_params.merge(user_id: current_user.id)
is_subscribe = @subscription.save_with_payment
else
is_subscribe = false
end
end
if is_subscribe
render :show, status: :created, location: @subscription
@ -61,4 +63,14 @@ class API::SubscriptionsController < API::ApiController
def subscription_update_params
params.require(:subscription).permit(:expired_at)
end
# TODO refactor subscriptions logic and move this in model/validator
def valid_card_token?(token)
begin
Stripe::Token.retrieve(token)
rescue Stripe::InvalidRequestError => e
@subscription.errors[:card_token] << e.message
false
end
end
end

View File

@ -5,6 +5,8 @@ class Abuse < ActiveRecord::Base
after_create :notify_admins_abuse_reported
validates :first_name, :last_name, :email, :message, :presence => true
private
def notify_admins_abuse_reported

View File

@ -20,7 +20,8 @@ class Availability < ActiveRecord::Base
attr_accessor :is_reserved, :slot_id, :can_modify
validate :length_must_be_1h_minimum
validates :start_at, :end_at, presence: true
validate :length_must_be_1h_minimum, unless: proc { end_at.blank? or start_at.blank? }
validate :should_be_associated
def safe_destroy
@ -64,13 +65,13 @@ class Availability < ActiveRecord::Base
private
def length_must_be_1h_minimum
if end_at < (start_at + 1.hour)
errors.add(:end_at, t('availabilities.must_be_at_least_1_hour_after_the_start_date'))
errors.add(:end_at, I18n.t('availabilities.must_be_at_least_1_hour_after_the_start_date'))
end
end
def should_be_associated
if available_type == 'machines' and machine_ids.count == 0
errors.add(:machine_ids, t('availabilities.must_be_associated_with_at_least_1_machine'))
errors.add(:machine_ids, I18n.t('availabilities.must_be_associated_with_at_least_1_machine'))
end
end

View File

@ -2,5 +2,5 @@ class InvoiceItem < ActiveRecord::Base
belongs_to :invoice
belongs_to :subscription
has_one :invoice_item
has_one :invoice_item # to associated invoice_items of an invoice to invoice_items of an avoir
end

View File

@ -1,9 +0,0 @@
##DEPRECATED, this class is not used anymore from the migration to the Pricing model
##TODO remove in future update, in conjunction with the following migrations:
# - 20140606133116_create_machines_pricings.rb
# - 20150520133409_migrate_data_from_machines_pricings_to_prices.rb
# - 20150603133050_drop_machines_pricings.rb
class MachinesPricing < ActiveRecord::Base
belongs_to :machine
belongs_to :group
end

View File

@ -45,88 +45,40 @@ class Reservation < ActiveRecord::Base
# === Machine reservation ===
when Machine
base_amount = reservable.prices.find_by(group_id: user.group_id, plan_id: plan.try(:id)).amount
if plan
machine_credit = plan.machine_credits.select {|credit| credit.creditable_id == reservable_id}.first
if machine_credit
hours_available = machine_credit.hours
if !new_plan_being_bought
user_credit = user.users_credits.find_by_credit_id(machine_credit.id)
if user_credit
hours_available = machine_credit.hours - user_credit.hours_used
end
end
slots.each_with_index do |slot, index|
description = reservable.name + " #{I18n.l slot.start_at, format: :long} - #{I18n.l slot.end_at, format: :hour_minute}"
ii_amount = (index < hours_available ? 0 : base_amount)
ii_amount = 0 if (slot.offered and on_site)
unless on_site
ii = Stripe::InvoiceItem.create(
customer: user.stp_customer_id,
amount: ii_amount,
currency: Rails.application.secrets.stripe_currency,
description: description
)
invoice_items << ii
end
self.invoice.invoice_items.push InvoiceItem.new(amount: ii_amount, stp_invoice_item_id: (ii.id if ii), description: description)
end
else
slots.each do |slot|
description = reservable.name + " #{I18n.l slot.start_at, format: :long} - #{I18n.l slot.end_at, format: :hour_minute}"
ii_amount = base_amount
ii_amount = 0 if (slot.offered and on_site)
unless on_site
ii = Stripe::InvoiceItem.create(
customer: user.stp_customer_id,
amount: ii_amount,
currency: Rails.application.secrets.stripe_currency,
description: description
)
invoice_items << ii
end
self.invoice.invoice_items.push InvoiceItem.new(amount: ii_amount, stp_invoice_item_id: (ii.id if ii), description: description)
end
users_credits_manager = UsersCredits::Manager.new(reservation: self, plan: plan)
slots.each_with_index do |slot, index|
description = reservable.name + " #{I18n.l slot.start_at, format: :long} - #{I18n.l slot.end_at, format: :hour_minute}"
ii_amount = base_amount # ii_amount default to base_amount
if users_credits_manager.will_use_credits?
ii_amount = (index < users_credits_manager.free_hours_count) ? 0 : base_amount
end
else
slots.each do |slot|
description = reservable.name + " #{I18n.l slot.start_at, format: :long} - #{I18n.l slot.end_at, format: :hour_minute}"
ii_amount = base_amount
ii_amount = 0 if (slot.offered and on_site)
unless on_site
ii = Stripe::InvoiceItem.create(
customer: user.stp_customer_id,
amount: ii_amount,
currency: Rails.application.secrets.stripe_currency,
description: description
)
invoice_items << ii
end
self.invoice.invoice_items.push InvoiceItem.new(amount: ii_amount, stp_invoice_item_id: (ii.id if ii), description: description)
ii_amount = 0 if slot.offered and on_site # if it's a local payment and slot is offered free
unless on_site # if it's local payment then do not create Stripe::InvoiceItem
ii = Stripe::InvoiceItem.create(
customer: user.stp_customer_id,
amount: ii_amount,
currency: Rails.application.secrets.stripe_currency,
description: description
)
invoice_items << ii
end
self.invoice.invoice_items.push InvoiceItem.new(amount: ii_amount, stp_invoice_item_id: (ii.id if ii), description: description)
end
# === Training reservation ===
when Training
base_amount = reservable.amount_by_group(user.group_id).amount
if plan
# Return True if the subscription link a training credit for training reserved by the user
training_is_creditable = plan.training_credits.select {|credit| credit.creditable_id == reservable.id}.size > 0
# Training reserved by the user is free when :
# be careful, variable plan can be the user's plan OR the plan user is currently purchasing
users_credits_manager = UsersCredits::Manager.new(reservation: self, plan: plan)
base_amount = 0 if users_credits_manager.will_use_credits?
# |-> the user already has a current subscription and if training_is_creditable is true and has at least one credit available.
if !new_plan_being_bought
if user.training_credits.size < plan.training_credit_nb and training_is_creditable
base_amount = 0
end
# |-> the user buys a new subscription and if training_is_creditable is true.
else
if training_is_creditable
base_amount = 0
end
end
end
slots.each do |slot|
description = reservable.name + " #{I18n.l slot.start_at, format: :long} - #{I18n.l slot.end_at, format: :hour_minute}"
ii_amount = base_amount
@ -176,32 +128,6 @@ class Reservation < ActiveRecord::Base
invoice_items
end
def update_users_credits
if user.subscribed_plan
if reservable_type == 'Machine'
machine_credit = user.subscribed_plan.machine_credits.select {|credit| credit.creditable_id == reservable_id}.first
if machine_credit
hours_available = machine_credit.hours
user_credit = user.users_credits.find_or_initialize_by(credit_id: machine_credit.id)
user_credit.hours_used ||= 0
hours_available = machine_credit.hours - user_credit.hours_used
if hours_available >= slots.size
user_credit.hours_used = user_credit.hours_used + slots.size
else
user_credit.hours_used = machine_credit.hours
end
user_credit.save
end
elsif reservable_type == 'Training'
training_credit = user.subscribed_plan.training_credits.select {|credit| credit.creditable_id == reservable_id}.first
if user.training_credits.size < user.subscribed_plan.training_credit_nb and training_credit
user.credits << training_credit
end
end
end
return self
end
def save_with_payment
build_invoice(user: user)
invoice_items = generate_invoice_items
@ -218,6 +144,10 @@ class Reservation < ActiveRecord::Base
total = invoice.invoice_items.map(&:amount).map(&:to_i).reduce(:+)
self.invoice.total = total
save!
#
# IMPORTANT NOTE: here, we don't have to create a stripe::invoice and pay it
# because subscription.create (in subscription.rb) will pay all waiting stripe invoice items
#
else
# error handling
invoice_items.each(&:delete)
@ -237,6 +167,9 @@ class Reservation < ActiveRecord::Base
customer.save
end
end
#
# IMPORTANT NOTE: here, we have to create an invoice manually and pay it to pay all waiting stripe invoice items
#
invoice = Stripe::Invoice.create(
customer: user.stp_customer_id,
)
@ -286,7 +219,8 @@ class Reservation < ActiveRecord::Base
end
end
update_users_credits
UsersCredits::Manager.new(reservation: self).update_credits
true
end
end
@ -318,7 +252,7 @@ class Reservation < ActiveRecord::Base
if user.invoicing_disabled?
if valid?
save!
update_users_credits
UsersCredits::Manager.new(reservation: self).update_credits
return true
end
else
@ -345,7 +279,8 @@ class Reservation < ActiveRecord::Base
save!
end
update_users_credits
UsersCredits::Manager.new(reservation: self).update_credits
return true
end
end

View File

@ -8,6 +8,7 @@ class Subscription < ActiveRecord::Base
has_many :offer_days, dependent: :destroy
validates_presence_of :plan_id
validates_with SubscriptionGroupValidator
attr_accessor :card_token
@ -27,7 +28,7 @@ class Subscription < ActiveRecord::Base
self.expired_at = Time.at(new_subscription.current_period_end)
save!
reset_users_credits if expired_date_changed
UsersCredits::Manager.new(user: self.user).reset_credits if expired_date_changed
# generate invoice
stp_invoice = Stripe::Invoice.all(customer: user.stp_customer_id, limit: 1).data.first
@ -76,7 +77,7 @@ class Subscription < ActiveRecord::Base
self.canceled_at = nil
set_expired_at
save!
reset_users_credits if expired_date_changed
UsersCredits::Manager.new(user: self.user).reset_credits if expired_date_changed
generate_invoice.save if invoice
return true
else
@ -101,12 +102,6 @@ class Subscription < ActiveRecord::Base
invoice.save
end
def update_expired_date_with_first_training(training_start_at)
if plan.is_rolling?
update_columns(expired_at: training_start_at + plan.duration)
end
end
def cancel
if stp_subscription_id.present?
stp_subscription = stripe_subscription
@ -139,7 +134,7 @@ class Subscription < ActiveRecord::Base
self.expired_at = expired_at
if save
reset_users_credits if !free_days
UsersCredits::Manager.new(user: self.user).reset_credits if !free_days
notify_subscription_extended(free_days)
return true
end
@ -147,18 +142,6 @@ class Subscription < ActiveRecord::Base
end
private
def update_payment
if stp_subscription_id.present?
stp_subscription = stripe_subscription
stp_subscription.plan = plan.stp_plan_id
stp_subscription.prorate = false
stp_subscription.save
else
# TODO: implement stripe payment if member update subscription
# must have a card
end
end
def notify_member_subscribed_plan
NotificationCenter.call type: 'notify_member_subscribed_plan',
receiver: user,
@ -214,10 +197,6 @@ class Subscription < ActiveRecord::Base
p_value.to_date != expired_at.to_date and expired_at > p_value
end
def reset_users_credits
user.users_credits.destroy_all
end
# def is_being_extended?
# !expired_at_was.nil? and expired_at_changed?
# end

View File

@ -65,6 +65,8 @@ class User < ActiveRecord::Base
validates :username, presence: true, uniqueness: true, length: { maximum: 30 }
scope :active, -> { where(is_active: true) }
scope :without_subscription, -> { includes(:subscriptions).where(subscriptions: { user_id: nil }) }
scope :with_subscription, -> { joins(:subscriptions) }
def to_builder
Jbuilder.new do |json|

View File

@ -0,0 +1,26 @@
class SubscriptionExtensionAfterReservation
attr_accessor :user, :reservation
def initialize(reservation)
@user, @reservation = reservation.user, reservation
end
def extend_subscription_if_eligible
extend_subscription if eligible_to_extension?
end
def eligible_to_extension?
return false unless reservation.reservable_type == 'Training'
return false if user.reservations.where(reservable_type: 'Training').count != 1
return false unless user.subscription
return false if user.subscription.is_expired?
return false unless user.subscribed_plan.is_rolling
return true
end
def extend_subscription
user.subscription.update_columns(
expired_at: reservation.slots.first.start_at + user.subscribed_plan.duration
)
end
end

View File

@ -0,0 +1,156 @@
require 'forwardable'
module UsersCredits
class AlreadyUpdatedError < StandardError;end;
class Manager
extend Forwardable
attr_reader :manager
def initialize(reservation: nil, user: nil, plan: nil)
if user
@manager = Managers::User.new(user)
elsif reservation
if reservation.reservable_type == "Training"
@manager = Managers::Training.new(reservation, plan)
elsif reservation.reservable_type == "Machine"
@manager = Managers::Machine.new(reservation, plan)
elsif reservation.reservable_type == "Event"
@manager = Managers::Event.new(reservation, plan)
else
raise ArgumentError, "reservation.reservable_type must be Training, Machine or Event"
end
else
raise ArgumentError, "you have to pass either a reservation or a user to initialize a UsersCredits::Manager"
end
end
def_delegators :@manager, :will_use_credits?, :free_hours_count, :update_credits, :reset_credits
end
module Managers
class User # that class is responsible for reseting users_credits of a user
attr_reader :user
def initialize(user)
@user = user
end
def reset_credits
user.users_credits.destroy_all
end
end
class Reservation
attr_reader :reservation
def initialize(reservation, plan) # a plan can be passed to do a simulation (if user didn't have a subscription YET)
@reservation = reservation
@already_updated = false
@plan = plan
end
def plan
@plan || user.subscribed_plan
end
def user
reservation.user
end
def update_credits
if @already_updated
raise AlreadyUpdatedError, "update credit is not idempotent ! you can't invoke update_credits method twice."
else
@already_updated = true
end
end
end
private_constant :Reservation
class Machine < Reservation # that class is responsible for knowing how to update users_credit of a given user for a given reservation
def will_use_credits? # to known if a credit will be used in the context of the given reservation
_will_use_credits?[0]
end
def free_hours_count
_will_use_credits?[1]
end
def update_credits
super
will_use_credits, free_hours_count, machine_credit = _will_use_credits?
if will_use_credits
users_credit = user.users_credits.find_or_initialize_by(credit_id: machine_credit.id)
if users_credit.new_record?
users_credit.hours_used = free_hours_count
else
users_credit.hours_used += free_hours_count
end
users_credit.save!
end
end
private
def _will_use_credits?
return false, 0 unless plan
if machine_credit = plan.machine_credits.find_by(creditable_id: reservation.reservable_id)
users_credit = user.users_credits.find_by(credit_id: machine_credit.id)
already_used_hours = users_credit ? users_credit.hours_used : 0
remaining_hours = machine_credit.hours - already_used_hours
free_hours_count = [remaining_hours, reservation.slots.size].min
if free_hours_count > 0
return true, free_hours_count, machine_credit
else
return false, free_hours_count, machine_credit
end
end
return false, 0
end
end
class Training < Reservation # same as class Machine but for Training reservation
def will_use_credits?
_will_use_credits?[0]
end
def update_credits
super
will_use_credits, training_credit = _will_use_credits?
if will_use_credits
user.credits << training_credit # we create a new UsersCredit object
end
end
private
def _will_use_credits?
return false, nil unless plan
# if there is a training_credit defined for this plan and this training
if training_credit = plan.training_credits.find_by(creditable_id: reservation.reservable_id)
# if user has not used all the plan credits
if user.training_credits.where(plan: plan).count < plan.training_credit_nb
return true, training_credit
end
end
return false, nil
end
end
class Event < Reservation
def will_use_credits?
false
end
def update_credits
end
end
end
end

View File

@ -0,0 +1,15 @@
class StripeCardTokenValidator
def validate(record)
if options[:token]
begin
res = Stripe::Token.retrieve(options[:token])
if res[:id] != options[:token]
record.errors[:card_token] << "A problem occurred while retrieving the card with the specified token: #{res.id}"
end
rescue Stripe::InvalidRequestError => e
record.errors[:card_token] << e
end
end
end
end

View File

@ -0,0 +1,7 @@
class SubscriptionGroupValidator < ActiveModel::Validator
def validate(record)
if record.user.group != record.plan.group
record.errors[:plan_id] << "This plan is not compatible with the current user's group"
end
end
end

View File

@ -1,3 +1,3 @@
json.admin do
json.reporting do
json.extract! @abuse, :id, :signaled_id, :signaled_type
end

View File

@ -39,6 +39,6 @@ Rails.application.configure do
# Raises error for missing translations
# config.action_view.raise_on_missing_translations = true
config.active_support.test_order = :random
end

View File

@ -0,0 +1,26 @@
ActiveRecord::Base.class_eval do
def dump_fixture
fixture_file = "#{Rails.root}/test/fixtures/#{self.class.table_name}.yml"
File.open(fixture_file, "a") do |f|
f.puts({ "#{self.class.table_name.singularize}_#{id}" => attributes }.
to_yaml.sub!(/---\s?/, "\n"))
end
end
def self.dump_fixtures
fixture_file = "#{Rails.root}/test/fixtures/#{self.table_name}.yml"
mode = (File.exists?(fixture_file) ? 'a' : 'w')
File.open(fixture_file, mode) do |f|
if self.attribute_names.include?("id")
self.all.each do |instance|
f.puts({ "#{self.table_name.singularize}_#{instance.id}" => instance.attributes }.to_yaml.sub!(/---\s?/, "\n"))
end
else
self.all.each_with_index do |instance, i|
f.puts({ "#{self.table_name.singularize}_#{i}" => instance.attributes }.to_yaml.sub!(/---\s?/, "\n"))
end
end
end
end
end

View File

@ -30,23 +30,23 @@ development:
elasticsearch_language_analyzer: <%= ENV["ELASTICSEARCH_LANGUAGE_ANALYZER"] %>
test:
secret_key_base: <%= ENV["SECRET_KEY_BASE"] %>
secret_key_base: 83daf5e7b80d990f037407bab78dff9904aaf3c195a50f84fa8695a22287e707dfbd9524b403b1dcf116ae1d8c06844c3d7ed942564e5b46be6ae3ead93a9d30
stripe_api_key: <%= ENV["STRIPE_API_KEY"] %>
stripe_publishable_key: <%= ENV["STRIPE_PUBLISHABLE_KEY"] %>
stripe_currency: <%= ENV["STRIPE_CURRENCY"] %>
disqus_shortname: <%= ENV["DISQUS_SHORTNAME"] %>
fablab_without_plans: <%= ENV["FABLAB_WITHOUT_PLANS"] %>
time_zone: <%= ENV["TIME_ZONE"] %>
week_starting_day: <%= ENV["WEEK_STARTING_DAY"] %>
d3_date_format: <%= ENV["D3_DATE_FORMAT"].dump %>
uib_date_format: <%= ENV["UIB_DATE_FORMAT"] %>
rails_locale: <%= ENV["RAILS_LOCALE"] %>
moment_locale: <%= ENV["MOMENT_LOCALE"] %>
summernote_locale: <%= ENV["SUMMERNOTE_LOCALE"] %>
angular_locale: <%= ENV["ANGULAR_LOCALE"] %>
messageformat_locale: <%= ENV["MESSAGEFORMAT_LOCALE"] %>
fullcalendar_locale: <%= ENV["FULLCALENDAR_LOCALE"] %>
elasticsearch_language_analyzer: <%= ENV["ELASTICSEARCH_LANGUAGE_ANALYZER"] %>
stripe_currency: usd
disqus_shortname: fablab-sleede
fablab_without_plans: false
time_zone: Paris
week_starting_day: monday
d3_date_format: '%d/%m/%y'
uib_date_format: dd/MM/yyyy
rails_locale: en
moment_locale: en
summernote_locale: en-US
angular_locale: en-us
messageformat_locale: en
fullcalendar_locale: en
elasticsearch_language_analyzer: french
staging:

View File

@ -1,13 +0,0 @@
class CreateMachinesPricings < ActiveRecord::Migration
def change
create_table :machines_pricings do |t|
t.belongs_to :machine, index: true
t.belongs_to :group, index: true
t.integer :not_subscribe_amount
t.integer :month_amount
t.integer :year_amount
t.timestamps
end
end
end

View File

@ -1,35 +0,0 @@
class MigrateDataFromMachinesPricingsToPrices < ActiveRecord::Migration
def up
insert <<-SQL
DELETE FROM machines_pricings WHERE machine_id NOT IN ( select distinct machines.id from machines )
SQL
machines_pricings = select_all("SELECT * FROM machines_pricings")
machines_pricings.each do |m_pricing|
time = "'#{Time.now.to_s(:db)}'"
plan_year = select_one("SELECT id FROM plans where plans.group_id = #{m_pricing['group_id']} and plans.interval = 'year'")
insert <<-SQL
INSERT INTO prices (group_id, plan_id, priceable_id, priceable_type, amount, created_at, updated_at)
VALUES (#{m_pricing['group_id']}, #{plan_year['id']}, #{m_pricing['machine_id']}, 'Machine', #{m_pricing['year_amount']}, #{time}, #{time})
SQL
plan_month = select_one("SELECT id FROM plans where plans.group_id = #{m_pricing['group_id']} and plans.interval = 'month'")
insert <<-SQL
INSERT INTO prices (group_id, plan_id, priceable_id, priceable_type, amount, created_at, updated_at)
VALUES (#{m_pricing['group_id']}, #{plan_month['id']}, #{m_pricing['machine_id']}, 'Machine', #{m_pricing['month_amount']}, #{time}, #{time})
SQL
insert <<-SQL
INSERT INTO prices (group_id, plan_id, priceable_id, priceable_type, amount, created_at, updated_at)
VALUES (#{m_pricing['group_id']}, NULL, #{m_pricing['machine_id']}, 'Machine', #{m_pricing['not_subscribe_amount']}, #{time}, #{time})
SQL
end
end
def down
insert <<-SQL
DELETE FROM prices
SQL
end
end

View File

@ -1,5 +0,0 @@
class DropMachinesPricings < ActiveRecord::Migration
def up
drop_table :machines_pricings
end
end

View File

@ -30,23 +30,23 @@ ActiveRecord::Schema.define(version: 20160119131623) do
add_index "abuses", ["signaled_type", "signaled_id"], name: "index_abuses_on_signaled_type_and_signaled_id", using: :btree
create_table "addresses", force: :cascade do |t|
t.string "address", limit: 255
t.string "street_number", limit: 255
t.string "route", limit: 255
t.string "locality", limit: 255
t.string "country", limit: 255
t.string "postal_code", limit: 255
t.string "address"
t.string "street_number"
t.string "route"
t.string "locality"
t.string "country"
t.string "postal_code"
t.integer "placeable_id"
t.string "placeable_type", limit: 255
t.string "placeable_type"
t.datetime "created_at"
t.datetime "updated_at"
end
create_table "assets", force: :cascade do |t|
t.integer "viewable_id"
t.string "viewable_type", limit: 255
t.string "attachment", limit: 255
t.string "type", limit: 255
t.string "viewable_type"
t.string "attachment"
t.string "type"
t.datetime "created_at"
t.datetime "updated_at"
end
@ -63,11 +63,11 @@ ActiveRecord::Schema.define(version: 20160119131623) do
create_table "availabilities", force: :cascade do |t|
t.datetime "start_at"
t.datetime "end_at"
t.string "available_type", limit: 255
t.string "available_type"
t.datetime "created_at"
t.datetime "updated_at"
t.integer "nb_total_places"
t.boolean "destroying", default: false
t.boolean "destroying", default: false
end
create_table "availability_tags", force: :cascade do |t|
@ -81,18 +81,18 @@ ActiveRecord::Schema.define(version: 20160119131623) do
add_index "availability_tags", ["tag_id"], name: "index_availability_tags_on_tag_id", using: :btree
create_table "categories", force: :cascade do |t|
t.string "name", limit: 255
t.string "name"
t.datetime "created_at"
t.datetime "updated_at"
end
create_table "components", force: :cascade do |t|
t.string "name", limit: 255, null: false
t.string "name", null: false
end
create_table "credits", force: :cascade do |t|
t.integer "creditable_id"
t.string "creditable_type", limit: 255
t.string "creditable_type"
t.integer "plan_id"
t.integer "hours"
t.datetime "created_at"
@ -113,7 +113,7 @@ ActiveRecord::Schema.define(version: 20160119131623) do
end
create_table "events", force: :cascade do |t|
t.string "title", limit: 255
t.string "title"
t.text "description"
t.datetime "created_at"
t.datetime "updated_at"
@ -139,10 +139,10 @@ ActiveRecord::Schema.define(version: 20160119131623) do
add_index "events_categories", ["event_id"], name: "index_events_categories_on_event_id", using: :btree
create_table "friendly_id_slugs", force: :cascade do |t|
t.string "slug", limit: 255, null: false
t.integer "sluggable_id", null: false
t.string "slug", null: false
t.integer "sluggable_id", null: false
t.string "sluggable_type", limit: 50
t.string "scope", limit: 255
t.string "scope"
t.datetime "created_at"
end
@ -152,17 +152,17 @@ ActiveRecord::Schema.define(version: 20160119131623) do
add_index "friendly_id_slugs", ["sluggable_type"], name: "index_friendly_id_slugs_on_sluggable_type", using: :btree
create_table "groups", force: :cascade do |t|
t.string "name", limit: 255
t.string "name"
t.datetime "created_at"
t.datetime "updated_at"
t.string "slug", limit: 255
t.string "slug"
end
add_index "groups", ["slug"], name: "index_groups_on_slug", unique: true, using: :btree
create_table "invoice_items", force: :cascade do |t|
t.integer "invoice_id"
t.string "stp_invoice_item_id", limit: 255
t.string "stp_invoice_item_id"
t.integer "amount"
t.datetime "created_at"
t.datetime "updated_at"
@ -175,17 +175,17 @@ ActiveRecord::Schema.define(version: 20160119131623) do
create_table "invoices", force: :cascade do |t|
t.integer "invoiced_id"
t.string "invoiced_type", limit: 255
t.string "stp_invoice_id", limit: 255
t.string "invoiced_type"
t.string "stp_invoice_id"
t.integer "total"
t.datetime "created_at"
t.datetime "updated_at"
t.integer "user_id"
t.string "reference", limit: 255
t.string "avoir_mode", limit: 255
t.string "reference"
t.string "avoir_mode"
t.datetime "avoir_date"
t.integer "invoice_id"
t.string "type", limit: 255
t.string "type"
t.boolean "subscription_to_expire"
t.text "description"
end
@ -194,17 +194,17 @@ ActiveRecord::Schema.define(version: 20160119131623) do
add_index "invoices", ["user_id"], name: "index_invoices_on_user_id", using: :btree
create_table "licences", force: :cascade do |t|
t.string "name", limit: 255, null: false
t.string "name", null: false
t.text "description"
end
create_table "machines", force: :cascade do |t|
t.string "name", limit: 255, null: false
t.string "name", null: false
t.text "description"
t.text "spec"
t.datetime "created_at"
t.datetime "updated_at"
t.string "slug", limit: 255
t.string "slug"
end
add_index "machines", ["slug"], name: "index_machines_on_slug", unique: true, using: :btree
@ -220,14 +220,14 @@ ActiveRecord::Schema.define(version: 20160119131623) do
create_table "notifications", force: :cascade do |t|
t.integer "receiver_id"
t.integer "attached_object_id"
t.string "attached_object_type", limit: 255
t.string "attached_object_type"
t.integer "notification_type_id"
t.boolean "is_read", default: false
t.boolean "is_read", default: false
t.datetime "created_at"
t.datetime "updated_at"
t.string "receiver_type", limit: 255
t.boolean "is_send", default: false
t.jsonb "meta_data", default: {}
t.string "receiver_type"
t.boolean "is_send", default: false
t.jsonb "meta_data", default: {}
end
add_index "notifications", ["notification_type_id"], name: "index_notifications_on_notification_type_id", using: :btree
@ -268,20 +268,20 @@ ActiveRecord::Schema.define(version: 20160119131623) do
add_index "offer_days", ["subscription_id"], name: "index_offer_days_on_subscription_id", using: :btree
create_table "plans", force: :cascade do |t|
t.string "name", limit: 255
t.string "name"
t.integer "amount"
t.string "interval", limit: 255
t.string "interval"
t.integer "group_id"
t.string "stp_plan_id", limit: 255
t.string "stp_plan_id"
t.datetime "created_at"
t.datetime "updated_at"
t.integer "training_credit_nb", default: 0
t.boolean "is_rolling", default: true
t.integer "training_credit_nb", default: 0
t.boolean "is_rolling", default: true
t.text "description"
t.string "type"
t.string "base_name"
t.integer "ui_weight", default: 0
t.integer "interval_count", default: 1
t.integer "ui_weight", default: 0
t.integer "interval_count", default: 1
end
add_index "plans", ["group_id"], name: "index_plans_on_group_id", using: :btree
@ -302,11 +302,11 @@ ActiveRecord::Schema.define(version: 20160119131623) do
create_table "profiles", force: :cascade do |t|
t.integer "user_id"
t.string "first_name", limit: 255
t.string "last_name", limit: 255
t.string "first_name"
t.string "last_name"
t.boolean "gender"
t.date "birthday"
t.string "phone", limit: 255
t.string "phone"
t.text "interest"
t.text "software_mastered"
t.datetime "created_at"
@ -320,7 +320,7 @@ ActiveRecord::Schema.define(version: 20160119131623) do
t.integer "project_id"
t.datetime "created_at"
t.datetime "updated_at"
t.string "title", limit: 255
t.string "title"
end
add_index "project_steps", ["project_id"], name: "index_project_steps_on_project_id", using: :btree
@ -330,23 +330,23 @@ ActiveRecord::Schema.define(version: 20160119131623) do
t.integer "user_id"
t.datetime "created_at"
t.datetime "updated_at"
t.boolean "is_valid", default: false
t.string "valid_token", limit: 255
t.boolean "is_valid", default: false
t.string "valid_token"
end
add_index "project_users", ["project_id"], name: "index_project_users_on_project_id", using: :btree
add_index "project_users", ["user_id"], name: "index_project_users_on_user_id", using: :btree
create_table "projects", force: :cascade do |t|
t.string "name", limit: 255
t.string "name"
t.text "description"
t.datetime "created_at"
t.datetime "updated_at"
t.integer "author_id"
t.text "tags"
t.integer "licence_id"
t.string "state", limit: 255
t.string "slug", limit: 255
t.string "state"
t.string "slug"
t.datetime "published_at"
end
@ -382,20 +382,20 @@ ActiveRecord::Schema.define(version: 20160119131623) do
t.datetime "created_at"
t.datetime "updated_at"
t.integer "reservable_id"
t.string "reservable_type", limit: 255
t.string "stp_invoice_id", limit: 255
t.string "reservable_type"
t.string "stp_invoice_id"
t.integer "nb_reserve_places"
t.integer "nb_reserve_reduced_places"
end
add_index "reservations", ["reservable_id", "reservable_type"], name: "index_reservations_on_reservable_id_and_reservable_type", using: :btree
add_index "reservations", ["reservable_type", "reservable_id"], name: "index_reservations_on_reservable_type_and_reservable_id", using: :btree
add_index "reservations", ["stp_invoice_id"], name: "index_reservations_on_stp_invoice_id", using: :btree
add_index "reservations", ["user_id"], name: "index_reservations_on_user_id", using: :btree
create_table "roles", force: :cascade do |t|
t.string "name", limit: 255
t.string "name"
t.integer "resource_id"
t.string "resource_type", limit: 255
t.string "resource_type"
t.datetime "created_at"
t.datetime "updated_at"
end
@ -420,8 +420,8 @@ ActiveRecord::Schema.define(version: 20160119131623) do
t.datetime "updated_at"
t.integer "availability_id"
t.datetime "ex_start_at"
t.datetime "canceled_at"
t.datetime "ex_end_at"
t.datetime "canceled_at"
t.boolean "offered", default: false
end
@ -430,18 +430,18 @@ ActiveRecord::Schema.define(version: 20160119131623) do
create_table "statistic_fields", force: :cascade do |t|
t.integer "statistic_index_id"
t.string "key", limit: 255
t.string "label", limit: 255
t.string "key"
t.string "label"
t.datetime "created_at"
t.datetime "updated_at"
t.string "data_type", limit: 255
t.string "data_type"
end
add_index "statistic_fields", ["statistic_index_id"], name: "index_statistic_fields_on_statistic_index_id", using: :btree
create_table "statistic_graphs", force: :cascade do |t|
t.integer "statistic_index_id"
t.string "chart_type", limit: 255
t.string "chart_type"
t.integer "limit"
t.datetime "created_at"
t.datetime "updated_at"
@ -450,17 +450,17 @@ ActiveRecord::Schema.define(version: 20160119131623) do
add_index "statistic_graphs", ["statistic_index_id"], name: "index_statistic_graphs_on_statistic_index_id", using: :btree
create_table "statistic_indices", force: :cascade do |t|
t.string "es_type_key", limit: 255
t.string "label", limit: 255
t.string "es_type_key"
t.string "label"
t.datetime "created_at"
t.datetime "updated_at"
t.boolean "table", default: true
t.boolean "ca", default: true
t.boolean "table", default: true
t.boolean "ca", default: true
end
create_table "statistic_sub_types", force: :cascade do |t|
t.string "key", limit: 255
t.string "label", limit: 255
t.string "key"
t.string "label"
t.datetime "created_at"
t.datetime "updated_at"
end
@ -477,8 +477,8 @@ ActiveRecord::Schema.define(version: 20160119131623) do
create_table "statistic_types", force: :cascade do |t|
t.integer "statistic_index_id"
t.string "key", limit: 255
t.string "label", limit: 255
t.string "key"
t.string "label"
t.boolean "graph"
t.datetime "created_at"
t.datetime "updated_at"
@ -496,7 +496,7 @@ ActiveRecord::Schema.define(version: 20160119131623) do
create_table "subscriptions", force: :cascade do |t|
t.integer "plan_id"
t.integer "user_id"
t.string "stp_subscription_id", limit: 255
t.string "stp_subscription_id"
t.datetime "created_at"
t.datetime "updated_at"
t.datetime "expired_at"
@ -515,15 +515,15 @@ ActiveRecord::Schema.define(version: 20160119131623) do
add_index "tags", ["name"], name: "index_tags_on_name", unique: true, using: :btree
create_table "themes", force: :cascade do |t|
t.string "name", limit: 255, null: false
t.string "name", null: false
end
create_table "trainings", force: :cascade do |t|
t.string "name", limit: 255
t.string "name"
t.datetime "created_at"
t.datetime "updated_at"
t.integer "nb_total_places"
t.string "slug", limit: 255
t.string "slug"
t.text "description"
end
@ -579,32 +579,32 @@ ActiveRecord::Schema.define(version: 20160119131623) do
add_index "user_trainings", ["user_id"], name: "index_user_trainings_on_user_id", using: :btree
create_table "users", force: :cascade do |t|
t.string "username", limit: 255
t.string "email", limit: 255, default: "", null: false
t.string "encrypted_password", limit: 255, default: "", null: false
t.string "reset_password_token", limit: 255
t.string "email", default: "", null: false
t.string "encrypted_password", default: "", null: false
t.string "reset_password_token"
t.datetime "reset_password_sent_at"
t.datetime "remember_created_at"
t.integer "sign_in_count", default: 0, null: false
t.integer "sign_in_count", default: 0, null: false
t.datetime "current_sign_in_at"
t.datetime "last_sign_in_at"
t.string "current_sign_in_ip", limit: 255
t.string "last_sign_in_ip", limit: 255
t.string "confirmation_token", limit: 255
t.string "current_sign_in_ip"
t.string "last_sign_in_ip"
t.string "confirmation_token"
t.datetime "confirmed_at"
t.datetime "confirmation_sent_at"
t.string "unconfirmed_email", limit: 255
t.integer "failed_attempts", default: 0, null: false
t.string "unlock_token", limit: 255
t.string "unconfirmed_email"
t.integer "failed_attempts", default: 0, null: false
t.string "unlock_token"
t.datetime "locked_at"
t.datetime "created_at"
t.datetime "updated_at"
t.boolean "is_allow_contact", default: true
t.boolean "is_allow_contact", default: true
t.integer "group_id"
t.string "stp_customer_id", limit: 255
t.string "slug", limit: 255
t.boolean "is_active", default: true
t.boolean "invoicing_disabled", default: false
t.string "stp_customer_id"
t.string "username"
t.string "slug"
t.boolean "is_active", default: true
t.boolean "invoicing_disabled", default: false
t.string "provider"
t.string "uid"
t.string "auth_token"

View File

@ -1,64 +0,0 @@
Group.create!([
{name: "standard, association", slug: "standard"},
{name: "étudiant, - de 25 ans, enseignant, demandeur d'emploi", slug: "student"},
{name: "artisan, commerçant, chercheur, auto-entrepreneur", slug: "merchant"},
{name: "PME, PMI, SARL, SA", slug: "business"}
])
if Category.count == 0
Category.create!([
{name: "Stage"},
{name: "Atelier"}
])
end
if StatisticIndex.count == 0
StatisticIndex.create!([
{id:1, es_type_key:'subscription', label:'Abonnements'},
{id:2, es_type_key:'machine', label:'Heures machines'},
{id:3, es_type_key:'training', label:'Formations'},
{id:4, es_type_key:'event', label:'Ateliers/Stages'},
{id:5, es_type_key:'account', label:'Inscriptions', ca: false},
{id:6, es_type_key:'project', label:'Projets', ca: false},
{id:7, es_type_key:'user', label:'Utilisateurs', table: false, ca: false}
])
connection = ActiveRecord::Base.connection
if connection.instance_values["config"][:adapter] == 'postgresql'
connection.execute("SELECT setval('statistic_indices_id_seq', 7);")
end
end
if StatisticField.count == 0
StatisticField.create!([
# available data_types : index, number, date, text, list
{key:'trainingId', label:'ID Formation', statistic_index_id: 3, data_type: 'index'},
{key:'trainingDate', label:'Date Formation', statistic_index_id: 3, data_type: 'date'},
{key:'eventId', label:'ID Évènement', statistic_index_id: 4, data_type: 'index'},
{key:'eventDate', label:'Date Évènement', statistic_index_id: 4, data_type: 'date'},
{key:'themes', label:'Thèmes', statistic_index_id: 6, data_type: 'list'},
{key:'components', label:'Composants', statistic_index_id: 6, data_type: 'list'},
{key:'machines', label:'Machines', statistic_index_id: 6, data_type: 'list'},
{key:'name', label:'Nom Évènement', statistic_index_id: 4, data_type: 'text'},
{key:'userId', label:'ID Utilisateur', statistic_index_id: 7, data_type: 'index'}
])
end
if StatisticType.count == 0
StatisticType.create!([
{id:1, statistic_index_id: 1, key: 'month', label:'Abonnements mensuels', graph: true, simple: true},
{id:2, statistic_index_id: 1, key: 'year', label:'Abonnements annuels', graph: true, simple: true},
{id:3, statistic_index_id: 2, key: 'booking', label:'Réservations', graph: true, simple: true},
{id:4, statistic_index_id: 2, key: 'hour', label:"Nombre d'heures", graph: true, simple: false},
{id:5, statistic_index_id: 3, key: 'booking', label:'Réservations', graph: false, simple: true},
{id:6, statistic_index_id: 3, key: 'hour', label:"Nombre d'heures", graph: false, simple: false},
{id:7, statistic_index_id: 4, key: 'booking', label:'Nombre de places', graph: false, simple: false},
{id:8, statistic_index_id: 4, key: 'hour', label:"Nombre d'heures", graph: false, simple: false},
{id:9, statistic_index_id: 5, key: 'member', label:'Utilisateurs', graph: true, simple: true},
{id:10, statistic_index_id: 6, key: 'project', label:'Projets', graph: false, simple: true},
{id:11, statistic_index_id: 7, key: 'revenue', label:"Chiffre d'affaires", graph: false, simple: false}
])
connection = ActiveRecord::Base.connection
if connection.instance_values["config"][:adapter] == 'postgresql'
connection.execute("SELECT setval('statistic_types_id_seq', 11);")
end
end

View File

@ -31,7 +31,7 @@ namespace :fablab do
puts "-> Done"
end
desc "Cancel strip subscriptions"
desc "Cancel stripe subscriptions"
task cancel_subscriptions: :environment do
Subscription.where("expired_at >= ?", Time.now.at_beginning_of_day).each do |s|
puts "-> Start cancel subscription of #{s.user.email}"
@ -170,4 +170,24 @@ namespace :fablab do
puts "\nUsers successfully notified\n\n"
end
desc "generate fixtures from db"
task generate_fixtures: :environment do
Rails.application.eager_load!
ActiveRecord::Base.descendants.reject { |c| c == ActiveRecord::SchemaMigration or c == PartnerPlan }.each do |ar_base|
p "========== #{ar_base} =============="
ar_base.dump_fixtures
end
end
desc 'clean stripe secrets from VCR cassettes'
task clean_cassettes_secrets: :environment do
Dir['test/vcr_cassettes/*.yml'].each do |cassette_file|
cassette = File.read(cassette_file)
cassette.gsub!(Rails.application.secrets.stripe_api_key, 'sk_test_testfaketestfaketestfake')
cassette.gsub!(Rails.application.secrets.stripe_publishable_key, 'pk_test_faketestfaketestfaketest')
puts cassette
File.write(cassette_file, cassette)
end
end
end

View File

@ -1,10 +0,0 @@
FactoryGirl.define do
factory :abus, :class => 'Abuse' do
signaled nil
first_name "MyString"
last_name "MyString"
email ""
message "MyText"
end
end

View File

@ -1,8 +0,0 @@
FactoryGirl.define do
factory :auth_provider do
name "MyString"
type ""
status "MyString"
end
end

View File

@ -1,6 +0,0 @@
#FactoryGirl.define do
#factory :availability do
#end
#end

View File

@ -1,7 +0,0 @@
FactoryGirl.define do
factory :availability_tag do
availability nil
tag nil
end
end

View File

@ -1,6 +0,0 @@
#FactoryGirl.define do
#factory :avoir do
#end
#end

View File

@ -1,6 +0,0 @@
#FactoryGirl.define do
#factory :credit do
#end
#end

View File

@ -1,6 +0,0 @@
FactoryGirl.define do
factory :custom_asset do
end
end

View File

@ -1,6 +0,0 @@
FactoryGirl.define do
factory :database_provider do
end
end

View File

@ -1,6 +0,0 @@
#FactoryGirl.define do
#factory :invoice do
#end
#end

View File

@ -1,6 +0,0 @@
#FactoryGirl.define do
#factory :machine do
#end
#end

View File

@ -1,10 +0,0 @@
FactoryGirl.define do
factory :o_auth2_mapping do
o_auth2_provider nil
resource_url "MyString"
local_field "MyString"
api_field "MyString"
data_type "MyString"
end
end

View File

@ -1,11 +0,0 @@
FactoryGirl.define do
factory :o_auth2_provider do
base_url "MyString"
token_endpoint "MyString"
authorization_endpoint "MyString"
client_id "MyString"
client_secret "MyString"
auth_provider nil
end
end

View File

@ -1,6 +0,0 @@
#FactoryGirl.define do
#factory :plan do
#end
#end

View File

@ -1,9 +0,0 @@
FactoryGirl.define do
factory :price do
group nil
plan nil
priceable nil
amount 1
end
end

View File

@ -1,11 +0,0 @@
FactoryGirl.define do
sequence(:last_name) { |n| n }
factory :profile do
first_name 'member'
last_name { FactoryGirl.generate :last_name }
gender true
birthday { 30.years.ago }
phone '0606060606'
end
end

View File

@ -1,8 +0,0 @@
FactoryGirl.define do
sequence(:name) { |n| "project#{n}" }
factory :project do
name { FactoryGirl.generate :name }
description { Faker::Lorem.paragraph }
end
end

View File

@ -1,6 +0,0 @@
#FactoryGirl.define do
#factory :reservation do
#end
#end

View File

@ -1,6 +0,0 @@
FactoryGirl.define do
factory :stylesheet do
contents "MyString"
end
end

View File

@ -1,6 +0,0 @@
#FactoryGirl.define do
#factory :subscription do
#end
#end

View File

@ -1,6 +0,0 @@
FactoryGirl.define do
factory :tag do
name "MyString"
end
end

View File

@ -1,6 +0,0 @@
#FactoryGirl.define do
#factory :training do
#end
#end

View File

@ -1,7 +0,0 @@
FactoryGirl.define do
factory :user_tag do
user nil
tag nil
end
end

View File

@ -1,14 +0,0 @@
FactoryGirl.define do
sequence(:email) { |n| "member#{n}@sleede.com" }
sequence(:username) { |n| "member#{n}" }
factory :user do
email { FactoryGirl.generate :email }
username { FactoryGirl.generate :username }
password 'sleede22'
password_confirmation 'sleede22'
association :profile, strategy: :build
group { Group.first }
end
end

View File

@ -1,9 +0,0 @@
class DeviseMailerPreview < ActionMailer::Preview
def confirmation_instructions
Devise::Mailer.confirmation_instructions(User.last, SecureRandom.hex)
end
def reset_password_instructions
Devise::Mailer.reset_password_instructions(User.last, SecureRandom.hex)
end
end

View File

@ -1,7 +0,0 @@
class NotificationsMailerPreview < ActionMailer::Preview
NotificationType::NAMES.each do |name|
define_method name do
NotificationsMailer.send_mail_by(Notification.where(notification_type_id: NotificationType.find_by_name(name)).last)
end
end
end

View File

@ -1,5 +0,0 @@
class UsersMailerPreview < ActionMailer::Preview
def notify_user_account_created
UsersMailer.notify_user_account_created(User.first, 'wfwwefwefsdfsdf')
end
end

View File

@ -1,5 +0,0 @@
require 'rails_helper'
RSpec.describe Abuse, type: :model do
pending "add some examples to (or delete) #{__FILE__}"
end

View File

@ -1,5 +0,0 @@
require 'rails_helper'
RSpec.describe AuthProvider, type: :model do
pending "add some examples to (or delete) #{__FILE__}"
end

View File

@ -1,24 +0,0 @@
require 'rails_helper'
RSpec.describe Availability, type: :model do
describe 'create' do
it 'is success with start at, end at and type'
it 'is invalid without start at'
it 'is invalid without end at'
it 'is invalid without type'
it 'is invalid type isnt in [training, machines, event]'
it 'is invalid without training_ids when type training'
it 'is invalid without machine_ids when type machines'
end
it 'should can associate one or many reservations'
it 'should can destroy if dont any reservations'
it 'should get a title'
it 'should set a number of places'
it 'should be completed when number of reservations equal number of places'
end

View File

@ -1,5 +0,0 @@
require 'rails_helper'
RSpec.describe AvailabilityTag, type: :model do
pending "add some examples to (or delete) #{__FILE__}"
end

View File

@ -1,9 +0,0 @@
require 'rails_helper'
RSpec.describe Avoir, type: :model do
it 'should generate a reference after create'
it 'is invoiced if avoir mode isnt in [stripe, cheque, transfer, none, cash]'
it 'should can expire user subscription if avoir indicate subscription to expire'
end

View File

@ -1,11 +0,0 @@
require 'rails_helper'
RSpec.describe Credit, type: :model do
context 'training' do
it 'should is saved with plan'
end
context 'machine' do
it 'should is saved with plan and hours'
end
end

View File

@ -1,5 +0,0 @@
require 'rails_helper'
RSpec.describe CustomAsset, type: :model do
pending "add some examples to (or delete) #{__FILE__}"
end

View File

@ -1,5 +0,0 @@
require 'rails_helper'
RSpec.describe DatabaseProvider, type: :model do
pending "add some examples to (or delete) #{__FILE__}"
end

View File

@ -1,9 +0,0 @@
require 'rails_helper'
RSpec.describe Invoice, type: :model do
it 'should generate a reference after create'
it 'should generate a invoice pdf'
it 'should can build a avoir'
end

View File

@ -1,21 +0,0 @@
require 'rails_helper'
RSpec.describe Machine, type: :model do
describe 'create' do
it 'is success with name, image, description and spec'
it 'is invalid without name'
it 'is invalid without image'
it 'is invalid without description'
it 'is invalid without spec'
it 'should auto generate slug by name'
end
it 'can have many machine files'
it 'can have many projects'
it 'can have many trainings'
it 'should return an amount by user group'
end

View File

@ -1,5 +0,0 @@
require 'rails_helper'
RSpec.describe OAuth2Mapping, type: :model do
pending "add some examples to (or delete) #{__FILE__}"
end

View File

@ -1,5 +0,0 @@
require 'rails_helper'
RSpec.describe OAuth2Provider, type: :model do
pending "add some examples to (or delete) #{__FILE__}"
end

View File

@ -1,60 +0,0 @@
require 'rails_helper'
RSpec.describe Plan, type: :model do
let(:group){ Group.new(name: 'groupe test', slug: SecureRandom.hex) }
describe 'validations' do
it 'is success with amount and group' do
plan = Plan.new(amount: 500, group: group)
expect(plan).to be_valid
end
it 'is invalid without amount' do
plan = Plan.new(group: group)
expect(plan).to be_invalid
end
it 'is invalid without group' do
plan = Plan.new(amount: 500)
expect(plan).to be_invalid
end
end
context "on creation" do
before :each do
@plan_id = SecureRandom.hex
@plan_name = SecureRandom.hex
allow(Stripe::Plan).to receive(:create).and_return(double(id: @plan_id, name: @plan_name))
end
it 'calls Stripe::Plan create method' do
plan = Plan.create(amount: 500, interval: 'month', group: group)
expect(Stripe::Plan).to have_received :create
end
it 'saves stripe_plan.id' do
plan = Plan.create(amount: 500, interval: 'month', group: group)
expect(plan.stp_plan_id).to eq(@plan_id)
end
it 'saves stripe_plan.name' do
plan = Plan.create(amount: 500, interval: 'month', group: group)
expect(plan.name).to eq(@plan_name)
end
end
context "on update" do
before :each do
allow(Stripe::Plan).to receive(:create).and_return(double(id: SecureRandom.hex, name: SecureRandom.hex))
end
let(:plan){ Plan.create(amount: 500, interval: 'month', group: group) }
describe "update_stripe_plan" do
it "should return false if plan already has subscriptions" do
allow(plan).to receive(:subscriptions).and_return([1,2])
expect(plan.send(:update_stripe_plan)).to eq(false)
end
end
end
end

View File

@ -1,5 +0,0 @@
require 'rails_helper'
RSpec.describe Price, type: :model do
pending "add some examples to (or delete) #{__FILE__}"
end

View File

@ -1,30 +0,0 @@
require 'rails_helper'
RSpec.describe Project, type: :model do
describe 'create' do
it 'is success with author, name and description'
it 'is invalid without author'
it 'is invalid without name'
it 'is invalid without description'
it 'should auto generate slug by name'
end
it 'save as draft by default'
it 'should can published'
it 'should have a published time after published'
it 'can only add one project main image'
it 'can have many project caos'
it 'can have many machines'
it 'can have many components'
it 'can have many project steps'
it 'can add a licence'
end

View File

@ -1,28 +0,0 @@
require 'rails_helper'
RSpec.describe Reservation, type: :model do
describe 'create' do
it 'is success with user, slots and reservable'
it 'is invalid if reservable isnt in [Training, Machine, Event]'
it 'is success with a subscription'
context 'stripe' do
it 'should payment success'
it 'is invalid if payment info invalid'
end
context 'satori' do
it 'should success'
it 'is invalid if payment info invalid'
end
end
it 'should update user credit after creation'
it 'should create a invoice'
it 'should can set a nb reserve places'
it 'should can set a nb reserve reduced places'
end

View File

@ -1,5 +0,0 @@
require 'rails_helper'
RSpec.describe Stylesheet, type: :model do
pending "add some examples to (or delete) #{__FILE__}"
end

View File

@ -1,26 +0,0 @@
require 'rails_helper'
RSpec.describe Subscription, type: :model do
describe 'create' do
it 'is success with user, plan'
it 'is success with a subscription'
context 'stripe' do
it 'should payment success'
it 'is invalid if payment info invalid'
end
context 'satori' do
it 'should success'
it 'is invalid if payment info invalid'
end
end
it 'should reset user credit after creation'
it 'should set a expired at after creation'
it 'should create a invoice'
end

View File

@ -1,5 +0,0 @@
require 'rails_helper'
RSpec.describe Tag, type: :model do
pending "add some examples to (or delete) #{__FILE__}"
end

View File

@ -1,18 +0,0 @@
require 'rails_helper'
RSpec.describe Training, type: :model do
describe 'create' do
it 'is success with name'
it 'is invalid without name'
it 'should auto generate slug by name'
end
it 'can associate many machines'
it 'can return a user list that valided by traning'
it 'should return an amount by user group'
it 'should can add a number place'
end

View File

@ -1,74 +0,0 @@
require 'rails_helper'
RSpec.describe User, type: :model do
let!(:user) { build :user }
describe 'create' do
it 'is success if user email, gender, first name, last name, group, birthday and phone are presents' do
expect(user.save).to be true
end
it 'is invalid when email is empty' do
user.email = nil
expect(user).to be_invalid
end
it 'is invalid when email format invalid' do
user.email = 'this a invalid email'
expect(user).to be_invalid
end
it 'is invalid when first name is empty' do
user.profile.first_name = nil
expect(user).to be_invalid
end
it 'is invalid when last name is empty' do
user.profile.last_name = nil
expect(user).to be_invalid
end
it 'is invalid when birthday is empty' do
user.profile.birthday = nil
expect(user).to be_invalid
end
it 'is invalid when phone is empty or not numerical' do
user.profile.phone = nil
expect(user).to be_invalid
user.profile.phone = "phone"
expect(user).to be_invalid
end
it 'is invalid when group is empty' do
user.group = nil
expect(user).to be_invalid
end
it 'is invalid when group is empty' do
user.group = nil
expect(user).to be_invalid
end
it 'is invalid when dont accept cgu' do
user.cgu = '0'
expect(user).to be_invalid
expect(user.errors[:cgu]).to include(I18n.t('activerecord.errors.messages.empty'))
end
end
context 'after creation' do
it 'has a member role' do
member = create(:user)
expect(member.is_member?).to be true
end
it 'create a stripe customer' do
member = create(:user)
allow(member).to receive(:create_stripe_customer) { |u| member.stp_customer_id = 'stripe customer id' }
member.run_callbacks(:commit)
expect(member.stp_customer_id).to eq 'stripe customer id'
end
end
end

View File

@ -1,5 +0,0 @@
require 'rails_helper'
RSpec.describe UserTag, type: :model do
pending "add some examples to (or delete) #{__FILE__}"
end

View File

@ -1,50 +0,0 @@
# This file is copied to spec/ when you run 'rails generate rspec:install'
ENV['RAILS_ENV'] ||= 'test'
require 'spec_helper'
require File.expand_path('../../config/environment', __FILE__)
require 'rspec/rails'
# Add additional requires below this line. Rails is not loaded until this point!
# Requires supporting ruby files with custom matchers and macros, etc, in
# spec/support/ and its subdirectories. Files matching `spec/**/*_spec.rb` are
# run as spec files by default. This means that files in spec/support that end
# in _spec.rb will both be required and run as specs, causing the specs to be
# run twice. It is recommended that you do not name files matching this glob to
# end with _spec.rb. You can configure this pattern with the --pattern
# option on the command line or in ~/.rspec, .rspec or `.rspec-local`.
#
# The following line is provided for convenience purposes. It has the downside
# of increasing the boot-up time by auto-requiring all files in the support
# directory. Alternatively, in the individual `*_spec.rb` files, manually
# require only the support files necessary.
#
Dir[Rails.root.join('spec/support/**/*.rb')].each { |f| require f }
# Checks for pending migrations before tests are run.
# If you are not using ActiveRecord, you can remove this line.
ActiveRecord::Migration.maintain_test_schema!
RSpec.configure do |config|
# Remove this line if you're not using ActiveRecord or ActiveRecord fixtures
config.fixture_path = "#{::Rails.root}/spec/fixtures"
# If you're not using ActiveRecord, or you'd prefer not to run each of your
# examples within a transaction, remove the following line or assign false
# instead of true.
config.use_transactional_fixtures = true
# RSpec Rails can automatically mix in different behaviours to your tests
# based on their file location, for example enabling you to call `get` and
# `post` in specs under `spec/controllers`.
#
# You can disable this behaviour by removing the line below, and instead
# explicitly tag your specs with their type, e.g.:
#
# RSpec.describe UsersController, :type => :controller do
# # ...
# end
#
# The different available types are documented in the features, such as in
# https://relishapp.com/rspec/rspec-rails/docs
config.infer_spec_type_from_file_location!
end

View File

@ -1,31 +0,0 @@
require 'rails_helper'
RSpec.describe NotificationCenter do
let(:receiver1) { create :user }
let(:receiver2) { create :user }
let(:project) { create :project }
it 'should respond to method .call' do
expect(NotificationCenter).to respond_to(:call)
end
it 'should create a notification' do
options = {
type: 'notify_admin_when_project_published',
receiver: receiver1,
attached_object: project
}
NotificationCenter.call(options)
expect(Notification.count).to eq 1
end
it 'should create same number of notifications with number of receiver' do
options = {
type: 'notify_admin_when_project_published',
receiver: [receiver1, receiver2],
attached_object: project
}
NotificationCenter.call(options)
expect(Notification.count).to eq 2
end
end

View File

@ -1,87 +0,0 @@
# This file was generated by the `rails generate rspec:install` command. Conventionally, all
# specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
# The generated `.rspec` file contains `--require spec_helper` which will cause
# this file to always be loaded, without a need to explicitly require it in any
# files.
#
# Given that it is always loaded, you are encouraged to keep this file as
# light-weight as possible. Requiring heavyweight dependencies from this file
# will add to the boot time of your test suite on EVERY test run, even for an
# individual file that may not need all of that loaded. Instead, consider making
# a separate helper file that requires the additional dependencies and performs
# the additional setup, and require it from the spec files that actually need
# it.
#
# The `.rspec` file also contains a few flags that are not defaults but that
# users commonly want.
#
# See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
RSpec.configure do |config|
# rspec-expectations config goes here. You can use an alternate
# assertion/expectation library such as wrong or the stdlib/minitest
# assertions if you prefer.
config.expect_with :rspec do |expectations|
# This option will default to `true` in RSpec 4. It makes the `description`
# and `failure_message` of custom matchers include text for helper methods
# defined using `chain`, e.g.:
# be_bigger_than(2).and_smaller_than(4).description
# # => "be bigger than 2 and smaller than 4"
# ...rather than:
# # => "be bigger than 2"
expectations.include_chain_clauses_in_custom_matcher_descriptions = true
end
# rspec-mocks config goes here. You can use an alternate test double
# library (such as bogus or mocha) by changing the `mock_with` option here.
config.mock_with :rspec do |mocks|
# Prevents you from mocking or stubbing a method that does not exist on
# a real object. This is generally recommended, and will default to
# `true` in RSpec 4.
mocks.verify_partial_doubles = true
end
# The settings below are suggested to provide a good initial experience
# with RSpec, but feel free to customize to your heart's content.
=begin
# These two settings work together to allow you to limit a spec run
# to individual examples or groups you care about by tagging them with
# `:focus` metadata. When nothing is tagged with `:focus`, all examples
# get run.
config.filter_run :focus
config.run_all_when_everything_filtered = true
# Limits the available syntax to the non-monkey patched syntax that is
# recommended. For more details, see:
# - http://myronmars.to/n/dev-blog/2012/06/rspecs-new-expectation-syntax
# - http://teaisaweso.me/blog/2013/05/27/rspecs-new-message-expectation-syntax/
# - http://myronmars.to/n/dev-blog/2014/05/notable-changes-in-rspec-3#new__config_option_to_disable_rspeccore_monkey_patching
config.disable_monkey_patching!
# Many RSpec users commonly either run the entire suite or an individual
# file, and it's useful to allow more verbose output when running an
# individual spec file.
if config.files_to_run.one?
# Use the documentation formatter for detailed output,
# unless a formatter has already been configured
# (e.g. via a command-line flag).
config.default_formatter = 'doc'
end
# Print the 10 slowest examples and example groups at the
# end of the spec run, to help surface which specs are running
# particularly slow.
config.profile_examples = 10
# Run specs in random order to surface order dependencies. If you find an
# order dependency and want to debug it, you can fix the order by providing
# the seed, which is printed after each run.
# --seed 1234
config.order = :random
# Seed global randomization in this process using the `--seed` CLI option.
# Setting this allows you to use `--seed` to deterministically reproduce
# test failures related to randomization by passing the same `--seed` value
# as the one that triggered the failure.
Kernel.srand config.seed
=end
end

View File

@ -1,17 +0,0 @@
RSpec.configure do |config|
config.before(:suite) do
# The :transaction strategy prevents :after_commit hooks from running
DatabaseCleaner.strategy = :transaction
DatabaseCleaner.clean_with(:truncation)
# load seeds only for test
load "#{Rails.root}/db/test_seeds.rb"
end
config.around(:each) do |example|
DatabaseCleaner.cleaning do
example.run
end
end
end

View File

@ -1,12 +0,0 @@
RSpec.configure do |config|
config.include FactoryGirl::Syntax::Methods
config.before(:suite) do
begin
DatabaseCleaner.start
FactoryGirl.lint
ensure
DatabaseCleaner.clean
end
end
end

52
test/fixtures/addresses.yml vendored Normal file
View File

@ -0,0 +1,52 @@
address_1:
id: 1
address: 14 rue Brecourt, Annecy
street_number:
route:
locality:
country:
postal_code:
placeable_id: 2
placeable_type: Profile
created_at: 2016-04-04 15:06:22.166469000 Z
updated_at: 2016-04-04 15:06:22.166469000 Z
address_2:
id: 2
address: 23 cours Berriat, Grenoble
street_number:
route:
locality:
country:
postal_code:
placeable_id: 4
placeable_type: Profile
created_at: 2016-04-04 15:10:42.353039000 Z
updated_at: 2016-04-04 15:10:42.353039000 Z
address_3:
id: 3
address: 36 chemin des puits, Mousson-sur-Luire
street_number:
route:
locality:
country:
postal_code:
placeable_id: 5
placeable_type: Profile
created_at: 2016-04-04 15:14:08.579603000 Z
updated_at: 2016-04-04 15:14:08.579603000 Z
address_4:
id: 4
address: ''
street_number:
route:
locality:
country:
postal_code:
placeable_id: 3
placeable_type: Profile
created_at: 2016-04-05 08:35:18.597812000 Z
updated_at: 2016-04-05 08:35:18.597812000 Z

126
test/fixtures/assets.yml vendored Normal file
View File

@ -0,0 +1,126 @@
asset_1:
id: 1
viewable_id: 2
viewable_type: Profile
attachment: user_avatar.jpg
type: UserAvatar
created_at: 2016-04-04 15:06:22.151882000 Z
updated_at: 2016-04-04 15:06:22.151882000 Z
asset_2:
id: 2
viewable_id: 5
viewable_type: Profile
attachment: user_avatar.jpg
type: UserAvatar
created_at: 2016-04-04 15:31:14.607327000 Z
updated_at: 2016-04-04 15:31:14.607327000 Z
asset_3:
id: 3
viewable_id: 1
viewable_type: Project
attachment: project_image.jpg
type: ProjectImage
created_at: 2016-04-04 15:39:08.230159000 Z
updated_at: 2016-04-04 15:39:08.230159000 Z
asset_4:
id: 4
viewable_id: 1
viewable_type: Event
attachment: event_image.jpg
type: EventImage
created_at: 2016-04-04 15:44:02.242194000 Z
updated_at: 2016-04-04 15:44:02.242194000 Z
asset_5:
id: 5
viewable_id: 2
viewable_type: Event
attachment: event_image.jpg
type: EventImage
created_at: 2016-04-04 15:44:03.164384000 Z
updated_at: 2016-04-04 15:44:03.164384000 Z
asset_6:
id: 6
viewable_id: 3
viewable_type: Event
attachment: event_image.jpg
type: EventImage
created_at: 2016-04-04 15:44:04.031482000 Z
updated_at: 2016-04-04 15:44:04.031482000 Z
asset_7:
id: 7
viewable_id: 3
viewable_type: Profile
attachment: user_avatar.jpg
type: UserAvatar
created_at: 2016-04-05 08:35:18.585573000 Z
updated_at: 2016-04-05 08:35:18.585573000 Z
asset_4:
id: 4
viewable_id: 1
viewable_type: Event
attachment: event_image.jpg
type: EventImage
created_at: 2016-04-04 15:44:02.242194000 Z
updated_at: 2016-04-04 15:44:02.242194000 Z
asset_5:
id: 5
viewable_id: 2
viewable_type: Event
attachment: event_image.jpg
type: EventImage
created_at: 2016-04-04 15:44:03.164384000 Z
updated_at: 2016-04-04 15:44:03.164384000 Z
asset_6:
id: 6
viewable_id: 3
viewable_type: Event
attachment: event_image.jpg
type: EventImage
created_at: 2016-04-04 15:44:04.031482000 Z
updated_at: 2016-04-04 15:44:04.031482000 Z
asset_3:
id: 3
viewable_id: 1
viewable_type: Project
attachment: project_image.jpg
type: ProjectImage
created_at: 2016-04-04 15:39:08.230159000 Z
updated_at: 2016-04-04 15:39:08.230159000 Z
asset_1:
id: 1
viewable_id: 2
viewable_type: Profile
attachment: user_avatar.jpg
type: UserAvatar
created_at: 2016-04-04 15:06:22.151882000 Z
updated_at: 2016-04-04 15:06:22.151882000 Z
asset_2:
id: 2
viewable_id: 5
viewable_type: Profile
attachment: user_avatar.jpg
type: UserAvatar
created_at: 2016-04-04 15:31:14.607327000 Z
updated_at: 2016-04-04 15:31:14.607327000 Z
asset_7:
id: 7
viewable_id: 3
viewable_type: Profile
attachment: user_avatar.jpg
type: UserAvatar
created_at: 2016-04-05 08:35:18.585573000 Z
updated_at: 2016-04-05 08:35:18.585573000 Z

9
test/fixtures/auth_providers.yml vendored Normal file
View File

@ -0,0 +1,9 @@
auth_provider_1:
id: 1
name: Fablab
status: active
created_at: 2016-04-04 14:11:34.743728000 Z
updated_at: 2016-04-04 14:11:34.743728000 Z
providable_type: DatabaseProvider
providable_id: 1

161
test/fixtures/availabilities.yml.erb vendored Normal file
View File

@ -0,0 +1,161 @@
availability_1:
id: 1
start_at: <%= DateTime.now.monday.utc.change({hour: 6}).strftime('%Y-%m-%d %H:%M:%S.%9N Z') %>
end_at: <%= DateTime.now.monday.utc.change({hour: 10}).strftime('%Y-%m-%d %H:%M:%S.%9N Z') %>
available_type: training
created_at: 2016-04-04 15:24:01.517486000 Z
updated_at: 2016-04-04 15:24:01.517486000 Z
nb_total_places:
destroying: false
availability_2:
id: 2
start_at: <%= (DateTime.now.monday + 1.day).utc.change({hour: 6}).strftime('%Y-%m-%d %H:%M:%S.%9N Z') %>
end_at: <%= (DateTime.now.monday + 1.day).utc.change({hour: 10}).strftime('%Y-%m-%d %H:%M:%S.%9N Z') %>
available_type: training
created_at: 2016-04-04 15:24:09.169364000 Z
updated_at: 2016-04-04 15:24:09.169364000 Z
nb_total_places:
destroying: false
availability_3:
id: 3
start_at: <%= DateTime.now.monday.utc.change({hour: 12}).strftime('%Y-%m-%d %H:%M:%S.%9N Z') %>
end_at: <%= DateTime.now.monday.utc.change({hour: 18}).strftime('%Y-%m-%d %H:%M:%S.%9N Z') %>
available_type: machines
created_at: 2016-04-04 15:24:27.587583000 Z
updated_at: 2016-04-04 15:24:27.587583000 Z
nb_total_places:
destroying: false
availability_4:
id: 4
start_at: <%= (DateTime.now.monday + 1.day).utc.change({hour: 12}).strftime('%Y-%m-%d %H:%M:%S.%9N Z') %>
end_at: <%= (DateTime.now.monday + 1.day).utc.change({hour: 18}).strftime('%Y-%m-%d %H:%M:%S.%9N Z') %>
available_type: machines
created_at: 2016-04-04 15:24:44.044908000 Z
updated_at: 2016-04-04 15:24:44.044908000 Z
nb_total_places:
destroying: false
availability_5:
id: 5
start_at: <%= (DateTime.now.monday + 2.day).utc.change({hour: 12}).strftime('%Y-%m-%d %H:%M:%S.%9N Z') %>
end_at: <%= (DateTime.now.monday + 2.day).utc.change({hour: 18}).strftime('%Y-%m-%d %H:%M:%S.%9N Z') %>
available_type: machines
created_at: 2016-04-04 15:25:48.584444000 Z
updated_at: 2016-04-04 15:25:48.584444000 Z
nb_total_places:
destroying: false
availability_6:
id: 6
start_at: <%= (DateTime.now.monday + 3.day).utc.change({hour: 12}).strftime('%Y-%m-%d %H:%M:%S.%9N Z') %>
end_at: <%= (DateTime.now.monday + 3.day).utc.change({hour: 18}).strftime('%Y-%m-%d %H:%M:%S.%9N Z') %>
available_type: machines
created_at: 2016-04-04 15:26:17.953216000 Z
updated_at: 2016-04-04 15:26:17.953216000 Z
nb_total_places:
destroying: false
availability_7:
id: 7
start_at: <%= (DateTime.now.monday + 3.day).utc.change({hour: 12}).strftime('%Y-%m-%d %H:%M:%S.%9N Z') %>
end_at: <%= (DateTime.now.monday + 3.day).utc.change({hour: 18}).strftime('%Y-%m-%d %H:%M:%S.%9N Z') %>
available_type: machines
created_at: 2016-04-04 15:26:39.278627000 Z
updated_at: 2016-04-04 15:26:39.278627000 Z
nb_total_places:
destroying: false
availability_8:
id: 8
start_at: <%= (DateTime.now.monday + 2.day).utc.change({hour: 6}).strftime('%Y-%m-%d %H:%M:%S.%9N Z') %>
end_at: <%= (DateTime.now.monday + 2.day).utc.change({hour: 10}).strftime('%Y-%m-%d %H:%M:%S.%9N Z') %>
available_type: training
created_at: 2016-04-04 15:26:49.572724000 Z
updated_at: 2016-04-04 15:26:49.572724000 Z
nb_total_places:
destroying: false
availability_9:
id: 9
start_at: 2016-04-18 16:00:28.000000000 Z
end_at: 2016-04-18 20:00:28.000000000 Z
available_type: event
created_at: 2016-04-04 15:44:02.228661000 Z
updated_at: 2016-04-04 15:44:02.228661000 Z
nb_total_places:
destroying: false
availability_10:
id: 10
start_at: 2016-05-18 16:00:28.000000000 Z
end_at: 2016-05-18 20:00:28.000000000 Z
available_type: event
created_at: 2016-04-04 15:44:03.156629000 Z
updated_at: 2016-04-04 15:44:03.156629000 Z
nb_total_places:
destroying: false
availability_11:
id: 11
start_at: 2016-06-18 16:00:28.000000000 Z
end_at: 2016-06-18 20:00:28.000000000 Z
available_type: event
created_at: 2016-04-04 15:44:04.023557000 Z
updated_at: 2016-04-04 15:44:04.023557000 Z
nb_total_places:
destroying: false
availability_12:
id: 12
start_at: 2012-04-11 06:00:00.000000000 Z
end_at: 2012-04-11 10:00:00.000000000 Z
available_type: training
created_at: 2012-04-04 15:24:01.517486000 Z
updated_at: 2012-04-04 15:24:01.517486000 Z
nb_total_places:
destroying: false
availability_13:
id: 13
start_at: 2015-06-15 12:00:28.000000000 Z
end_at: 2015-06-15 18:00:28.000000000 Z
available_type: machines
created_at: 2015-05-30 18:40:39.141601000 Z
updated_at: 2015-05-30 18:40:39.141601000 Z
nb_total_places:
destroying: false
availability_14:
id: 14
start_at: <%= 20.days.from_now.utc.change({hour: 6}).strftime('%Y-%m-%d %H:%M:%S.%9N Z') %>
end_at: <%= 20.days.from_now.utc.change({hour: 10}).strftime('%Y-%m-%d %H:%M:%S.%9N Z') %>
available_type: machines
created_at: 2016-04-04 15:44:04.023557000 Z
updated_at: 2016-04-04 15:44:04.023557000 Z
nb_total_places:
destroying: false
availability_15:
id: 15
start_at: <%= 40.days.from_now.utc.change({hour: 6}).strftime('%Y-%m-%d %H:%M:%S.%9N Z') %>
end_at: <%= 40.days.from_now.utc.change({hour: 10}).strftime('%Y-%m-%d %H:%M:%S.%9N Z') %>
available_type: machines
created_at: 2016-04-04 15:44:04.023557000 Z
updated_at: 2016-04-04 15:44:04.023557000 Z
nb_total_places:
destroying: false
availability_16:
id: 16
start_at: <%= 80.days.from_now.utc.change({hour: 6}).strftime('%Y-%m-%d %H:%M:%S.%9N Z') %>
end_at: <%= 80.days.from_now.utc.change({hour: 10}).strftime('%Y-%m-%d %H:%M:%S.%9N Z') %>
available_type: machines
created_at: 2016-04-04 15:44:04.023557000 Z
updated_at: 2016-04-04 15:44:04.023557000 Z
nb_total_places:
destroying: false

21
test/fixtures/availability_tags.yml vendored Normal file
View File

@ -0,0 +1,21 @@
availability_tag_1:
id: 1
availability_id: 5
tag_id: 2
created_at: 2016-04-04 15:25:48.587799000 Z
updated_at: 2016-04-04 15:25:48.587799000 Z
availability_tag_2:
id: 2
availability_id: 6
tag_id: 1
created_at: 2016-04-04 15:26:17.957014000 Z
updated_at: 2016-04-04 15:26:17.957014000 Z
availability_tag_3:
id: 3
availability_id: 8
tag_id: 2
created_at: 2016-04-04 15:26:49.576178000 Z
updated_at: 2016-04-04 15:26:49.576178000 Z

12
test/fixtures/categories.yml vendored Normal file
View File

@ -0,0 +1,12 @@
category_1:
id: 1
name: Stage
created_at: 2016-04-04 14:11:34.544995000 Z
updated_at: 2016-04-04 14:11:34.544995000 Z
category_2:
id: 2
name: Atelier
created_at: 2016-04-04 14:11:34.547621000 Z
updated_at: 2016-04-04 14:11:34.547621000 Z

40
test/fixtures/components.yml vendored Normal file
View File

@ -0,0 +1,40 @@
component_1:
id: 1
name: Silicone
component_2:
id: 2
name: Vinyle
component_3:
id: 3
name: Bois Contre plaqué
component_4:
id: 4
name: Bois Medium
component_5:
id: 5
name: Plexi / PMMA
component_6:
id: 6
name: Flex
component_7:
id: 7
name: Vinyle
component_8:
id: 8
name: Parafine
component_9:
id: 9
name: Fibre de verre
component_10:
id: 10
name: Résine

117
test/fixtures/credits.yml vendored Normal file
View File

@ -0,0 +1,117 @@
credit_1:
id: 1
creditable_id: 2
creditable_type: Training
plan_id: 1
hours:
created_at: 2001-01-01 14:11:33.852721000 Z
updated_at: 2001-01-01 14:11:33.852721000 Z
credit_2:
id: 2
creditable_id: 3
creditable_type: Training
plan_id: 1
hours:
created_at: 2016-04-04 15:19:28.449511000 Z
updated_at: 2016-04-04 15:19:28.449511000 Z
credit_3:
id: 3
creditable_id: 1
creditable_type: Training
plan_id: 1
hours:
created_at: 2016-04-04 15:19:28.495141000 Z
updated_at: 2016-04-04 15:19:28.495141000 Z
credit_5:
id: 5
creditable_id: 2
creditable_type: Training
plan_id: 2
hours:
created_at: 2016-04-04 15:19:39.416054000 Z
updated_at: 2016-04-04 15:19:39.416054000 Z
credit_7:
id: 7
creditable_id: 4
creditable_type: Training
plan_id: 2
hours:
created_at: 2016-04-04 15:19:39.486949000 Z
updated_at: 2016-04-04 15:19:39.486949000 Z
credit_8:
id: 8
creditable_id: 1
creditable_type: Training
plan_id: 2
hours:
created_at: 2016-04-04 15:19:39.521993000 Z
updated_at: 2016-04-04 15:19:39.521993000 Z
credit_9:
id: 9
creditable_id: 3
creditable_type: Training
plan_id: 2
hours:
created_at: 2016-04-04 15:19:39.553519000 Z
updated_at: 2016-04-04 15:19:39.553519000 Z
credit_10:
id: 10
creditable_id: 2
creditable_type: Training
plan_id: 3
hours:
created_at: 2016-04-04 15:21:35.437032000 Z
updated_at: 2016-04-04 15:21:35.437032000 Z
credit_11:
id: 11
creditable_id: 1
creditable_type: Training
plan_id: 3
hours:
created_at: 2016-04-04 15:21:35.470423000 Z
updated_at: 2016-04-04 15:21:35.470423000 Z
credit_12:
id: 12
creditable_id: 3
creditable_type: Training
plan_id: 3
hours:
created_at: 2016-04-04 15:21:35.547043000 Z
updated_at: 2016-04-04 15:21:35.547043000 Z
credit_13:
id: 13
creditable_id: 4
creditable_type: Machine
plan_id: 2
hours: 1
created_at: 2016-04-04 15:21:57.547939000 Z
updated_at: 2016-04-04 15:21:57.547939000 Z
credit_14:
id: 14
creditable_id: 6
creditable_type: Machine
plan_id: 3
hours: 1
created_at: 2016-04-04 15:21:57.547939000 Z
updated_at: 2016-04-04 15:21:57.547939000 Z
credit_15:
id: 15
creditable_id: 4
creditable_type: Machine
plan_id: 1
hours: 1
created_at: 2001-01-01 14:11:33.852721000 Z
updated_at: 2001-01-01 14:11:33.852721000 Z

0
test/fixtures/custom_assets.yml vendored Normal file
View File

5
test/fixtures/database_providers.yml vendored Normal file
View File

@ -0,0 +1,5 @@
database_provider_1:
id: 1
created_at: 2016-04-04 14:11:34.737301000 Z
updated_at: 2016-04-04 14:11:34.737301000 Z

42
test/fixtures/events.yml vendored Normal file
View File

@ -0,0 +1,42 @@
event_2:
id: 2
title: Skateboard DIY
description: "Apprenez à fabriquer vous-même votre skateboard :\r\n- impression
3D des roulettes\r\n- découpe moulage et décoration de la planche\r\n- assemblage"
created_at: 2016-04-04 15:44:03.161942000 Z
updated_at: 2016-04-04 15:44:03.161942000 Z
availability_id: 10
amount: 2000
reduced_amount: 1500
nb_total_places: 10
nb_free_places: 10
recurrence_id: 1
event_3:
id: 3
title: Skateboard DIY
description: "Apprenez à fabriquer vous-même votre skateboard :\r\n- impression
3D des roulettes\r\n- découpe moulage et décoration de la planche\r\n- assemblage"
created_at: 2016-04-04 15:44:04.028290000 Z
updated_at: 2016-04-04 15:44:04.028290000 Z
availability_id: 11
amount: 2000
reduced_amount: 1500
nb_total_places: 10
nb_free_places: 10
recurrence_id: 1
event_1:
id: 1
title: Skateboard DIY
description: "Apprenez à fabriquer vous-même votre skateboard :\r\n- impression
3D des roulettes\r\n- découpe moulage et décoration de la planche\r\n- assemblage"
created_at: 2016-04-04 15:44:02.236165000 Z
updated_at: 2016-04-04 15:44:02.236165000 Z
availability_id: 9
amount: 2000
reduced_amount: 1500
nb_total_places: 10
nb_free_places: 10
recurrence_id: 1

84
test/fixtures/events_categories.yml vendored Normal file
View File

@ -0,0 +1,84 @@
events_category_1:
id: 1
event_id: 1
category_id: 2
created_at: 2016-04-04 15:44:02.258622000 Z
updated_at: 2016-04-04 15:44:02.258622000 Z
events_category_2:
id: 2
event_id: 2
category_id: 2
created_at: 2016-04-04 15:44:03.173253000 Z
updated_at: 2016-04-04 15:44:03.173253000 Z
events_category_3:
id: 3
event_id: 2
category_id: 2
created_at: 2016-04-04 15:44:03.177952000 Z
updated_at: 2016-04-04 15:44:03.177952000 Z
events_category_4:
id: 4
event_id: 3
category_id: 2
created_at: 2016-04-04 15:44:04.041364000 Z
updated_at: 2016-04-04 15:44:04.041364000 Z
events_category_5:
id: 5
event_id: 3
category_id: 2
created_at: 2016-04-04 15:44:04.044667000 Z
updated_at: 2016-04-04 15:44:04.044667000 Z
events_category_6:
id: 6
event_id: 1
category_id: 2
created_at: 2016-04-04 15:44:04.049543000 Z
updated_at: 2016-04-04 15:44:04.049543000 Z
events_category_1:
id: 1
event_id: 1
category_id: 2
created_at: 2016-04-04 15:44:02.258622000 Z
updated_at: 2016-04-04 15:44:02.258622000 Z
events_category_2:
id: 2
event_id: 2
category_id: 2
created_at: 2016-04-04 15:44:03.173253000 Z
updated_at: 2016-04-04 15:44:03.173253000 Z
events_category_3:
id: 3
event_id: 2
category_id: 2
created_at: 2016-04-04 15:44:03.177952000 Z
updated_at: 2016-04-04 15:44:03.177952000 Z
events_category_4:
id: 4
event_id: 3
category_id: 2
created_at: 2016-04-04 15:44:04.041364000 Z
updated_at: 2016-04-04 15:44:04.041364000 Z
events_category_5:
id: 5
event_id: 3
category_id: 2
created_at: 2016-04-04 15:44:04.044667000 Z
updated_at: 2016-04-04 15:44:04.044667000 Z
events_category_6:
id: 6
event_id: 1
category_id: 2
created_at: 2016-04-04 15:44:04.049543000 Z
updated_at: 2016-04-04 15:44:04.049543000 Z

14
test/fixtures/groups.yml vendored Normal file
View File

@ -0,0 +1,14 @@
group_1:
id: 1
name: standard, association
created_at: 2016-04-04 14:11:33.612700000 Z
updated_at: 2016-04-04 14:11:33.612700000 Z
slug: standard
group_2:
id: 2
name: étudiant, - de 25 ans, enseignant, demandeur d'emploi
created_at: 2016-04-04 14:11:33.656537000 Z
updated_at: 2016-04-04 14:11:33.656537000 Z
slug: student

47
test/fixtures/invoice_items.yml vendored Normal file
View File

@ -0,0 +1,47 @@
invoice_item_1:
id: 1
invoice_id: 1
stp_invoice_item_id: sub_8DGB4ErIc2asOv
amount: 10000
created_at: 2016-04-05 08:35:52.934725000 Z
updated_at: 2016-04-05 08:35:52.934725000 Z
description: Sleede - standard, association - month
subscription_id: 1
invoice_item_id:
invoice_item_2:
id: 2
invoice_id: 2
stp_invoice_item_id:
amount: 2000
created_at: 2016-04-05 08:36:46.856021000 Z
updated_at: 2016-04-05 08:36:46.856021000 Z
description: Mensuel tarif réduit - étudiant, - de 25 ans, enseignant, demandeur
d'emploi - month
subscription_id: 2
invoice_item_id:
invoice_item_3:
id: 3
invoice_id: 3
stp_invoice_item_id:
amount: 3000
created_at: 2012-03-12 11:03:31.651441000 Z
updated_at: 2012-03-12 11:03:31.651441000 Z
description: Mensuel - standard, association - month
subscription_id: 3
invoice_item_id:
invoice_item_4:
id: 4
invoice_id: 4
stp_invoice_item_id:
amount: 0
created_at: 2012-03-12 13:40:22.342717000 Z
updated_at: 2012-03-12 13:40:22.342717000 Z
description: Formation Laser / Vinyle April 11, 2012 08:00 - 12:00 PM
subscription_id:
invoice_item_id:

69
test/fixtures/invoices.yml vendored Normal file
View File

@ -0,0 +1,69 @@
invoice_1:
id: 1
invoiced_id: 1
invoiced_type: Subscription
stp_invoice_id: in_17wpf92sOmf47Nz9itj6vmJw
total: 10000
created_at: 2016-04-05 08:35:52.931187000 Z
updated_at: 2016-04-05 08:35:52.931187000 Z
user_id: 3
reference: 1604001/VL
avoir_mode:
avoir_date:
invoice_id:
type:
subscription_to_expire:
description:
invoice_2:
id: 2
invoiced_id: 2
invoiced_type: Subscription
stp_invoice_id:
total: 2000
created_at: 2016-04-05 08:36:46.853368000 Z
updated_at: 2016-04-05 08:36:46.853368000 Z
user_id: 4
reference: '1604002'
avoir_mode:
avoir_date:
invoice_id:
type:
subscription_to_expire:
description:
invoice_3:
id: 3
invoiced_id: 3
invoiced_type: Subscription
stp_invoice_id:
total: 3000
created_at: 2012-03-12 11:03:31.651441000 Z
updated_at: 2012-03-12 11:03:31.651441000 Z
user_id: 7
reference: '1203001'
avoir_mode:
avoir_date:
invoice_id:
type:
subscription_to_expire:
description:
invoice_4:
id: 4
invoiced_id: 1
invoiced_type: Reservation
stp_invoice_id:
total: 0
created_at: 2012-03-12 13:40:22.342717000 Z
updated_at: 2012-03-12 13:40:22.342717000 Z
user_id: 7
reference: '1203002'
avoir_mode:
avoir_date:
invoice_id:
type:
subscription_to_expire:
description:

47
test/fixtures/licences.yml vendored Normal file
View File

@ -0,0 +1,47 @@
licence_1:
id: 1
name: Attribution (BY)
description: Le titulaire des droits autorise toute exploitation de lœuvre, y compris
à des fins commerciales, ainsi que la création dœuvres dérivées, dont la distribution
est également autorisé sans restriction, à condition de lattribuer à son lauteur
en citant son nom. Cette licence est recommandée pour la diffusion et lutilisation
maximale des œuvres.
licence_2:
id: 2
name: Attribution + Pas de modification (BY ND)
description: Le titulaire des droits autorise toute utilisation de lœuvre originale
(y compris à des fins commerciales), mais nautorise pas la création dœuvres
dérivées.
licence_3:
id: 3
name: Attribution + Pas d'Utilisation Commerciale + Pas de Modification (BY NC ND)
description: Le titulaire des droits autorise lutilisation de lœuvre originale
à des fins non commerciales, mais nautorise pas la création dœuvres dérivés.
licence_4:
id: 4
name: Attribution + Pas d'Utilisation Commerciale (BY NC)
description: Le titulaire des droits autorise lexploitation de lœuvre, ainsi que
la création dœuvres dérivées, à condition quil ne sagisse pas dune utilisation
commerciale (les utilisations commerciales restant soumises à son autorisation).
licence_5:
id: 5
name: Attribution + Pas d'Utilisation Commerciale + Partage dans les mêmes conditions
(BY NC SA)
description: Le titulaire des droits autorise lexploitation de lœuvre originale
à des fins non commerciales, ainsi que la création dœuvres dérivées, à condition
quelles soient distribuées sous une licence identique à celle qui régit lœuvre
originale.
licence_6:
id: 6
name: Attribution + Partage dans les mêmes conditions (BY SA)
description: Le titulaire des droits autorise toute utilisation de lœuvre originale
(y compris à des fins commerciales) ainsi que la création dœuvres dérivées, à
condition quelles soient distribuées sous une licence identique à celle qui régit
lœuvre originale. Cette licence est souvent comparée aux licences « copyleft
» des logiciels libres. Cest la licence utilisée par Wikipedia.

125
test/fixtures/machines.yml vendored Normal file
View File

@ -0,0 +1,125 @@
machine_1:
id: 1
name: Découpeuse laser
description: "Préparation à l'utilisation de l'EPILOG Legend 36EXT\r\nInformations
générales \r\n Pour la découpe, il suffit d'apporter votre fichier vectorisé
type illustrator, svg ou dxf avec des \"lignes de coupe\" d'une épaisseur inférieur
à 0,01 mm et la machine s'occupera du reste!\r\n La gravure est basée sur
le spectre noir et blanc. Les nuances sont obtenues par différentes profondeurs
de gravure correspondant aux niveaux de gris de votre image. Il suffit pour cela
d'apporter une image scannée ou un fichier photo en noir et blanc pour pouvoir
reproduire celle-ci sur votre support! \r\nQuels types de matériaux pouvons nous
graver/découper?\r\n Du bois au tissu, du plexiglass au cuir, cette machine
permet de découper et graver la plupart des matériaux sauf les métaux. La gravure
est néanmoins possible sur les métaux recouverts d'une couche de peinture ou les
aluminiums anodisés. \r\n Concernant l'épaisseur des matériaux découpés,
il est préférable de ne pas dépasser 5 mm pour le bois et 6 mm pour le plexiglass.\r\n"
spec: "Puissance: 40W\r\nSurface de travail: 914x609 mm \r\nEpaisseur maximale de
la matière: 305mm\r\nSource laser: tube laser type CO2\r\nContrôles de vitesse
et de puissance: ces deux paramètres sont ajustables en fonction du matériau (de
1% à 100%) .\r\n"
created_at: 2016-04-04 14:11:34.210242000 Z
updated_at: 2016-04-04 14:11:34.210242000 Z
slug: decoupeuse-laser
machine_2:
id: 2
name: Découpeuse vinyle
description: "Préparation à l'utilisation de la Roland CAMM-1 GX24\r\nInformations
générales \r\n Envie de réaliser un tee shirt personnalisé ? Un sticker
à l'effigie votre groupe préféré? Un masque pour la réalisation d'un circuit imprimé?
Pour cela, il suffit simplement de venir avec votre fichier vectorisé (ne pas
oublier de vectoriser les textes) type illustrator svg ou dxf.\r\n \r\nMatériaux
utilisés:\r\n Cette machine permet de découper principalement du vinyle,vinyle
réfléchissant, flex.\r\n"
spec: "Largeurs de support acceptées: de 50 mm à 700 mm\r\nVitesse de découpe: 50
cm/sec\r\nRésolution mécanique: 0,0125 mm/pas\r\n"
created_at: 2016-04-04 14:11:34.274025000 Z
updated_at: 2016-04-04 14:11:34.274025000 Z
slug: decoupeuse-vinyle
machine_3:
id: 3
name: Shopbot / Grande fraiseuse
description: "La fraiseuse numérique ShopBot PRS standard\r\nInformations générales\r\nCette
machine est un fraiseuse 3 axes idéale pour l'usinage de pièces de grandes dimensions.
De la réalisation d'une chaise ou d'un meuble jusqu'à la construction d'une maison
ou d'un assemblage immense, le ShopBot ouvre de nombreuses portes à votre imagination!
\r\nMatériaux usinables\r\nLes principaux matériaux usinables sont le bois, le
plastique, le laiton et bien d'autres.\r\nCette machine n'usine pas les métaux.\r\n"
spec: "Surface maximale de travail: 2440x1220x150 (Z) mm\r\nLogiciel utilisé: Partworks
2D & 3D\r\nRésolution mécanique: 0,015 mm\r\nPrécision de la position: +/- 0,127mm\r\nFormats
acceptés: DXF, STL \r\n"
created_at: 2016-04-04 14:11:34.304247000 Z
updated_at: 2016-04-04 14:11:34.304247000 Z
slug: shopbot-grande-fraiseuse
machine_4:
id: 4
name: Imprimante 3D
description: "L'utimaker est une imprimante 3D low cost utilisant une technologie
FFF (Fused Filament Fabrication) avec extrusion thermoplastique.\r\nC'est une
machine idéale pour réaliser rapidement des prototypes 3D dans des couleurs différentes.\r\n"
spec: "Surface maximale de travail: 210x210x220mm \r\nRésolution méchanique: 0,02
mm \r\nPrécision de position: +/- 0,05 \r\nLogiciel utilisé: Cura\r\nFormats de
fichier acceptés: STL \r\nMatériaux utilisés: PLA (en stock)."
created_at: 2001-01-01 14:11:34.341810000 Z
updated_at: 2001-01-01 14:11:34.341810000 Z
slug: imprimante-3d
machine_5:
id: 5
name: Petite Fraiseuse
description: "La fraiseuse numérique Roland Modela MDX-20\r\nInformations générales\r\nCette
machine est utilisée pour l'usinage et le scannage 3D de précision. Elle permet
principalement d'usiner des circuits imprimés et des moules de petite taille.
Le faible diamètre des fraises utilisées (Ø 0,3 mm à Ø 6mm) induit que certains
temps d'usinages peuvent êtres long (> 12h), c'est pourquoi cette fraiseuse peut
être laissée en autonomie toute une nuit afin d'obtenir le plus précis des usinages
au FabLab.\r\nMatériaux usinables:\r\nLes principaux matériaux usinables sont
le bois, plâtre, résine, cire usinable, cuivre.\r\n"
spec: "Taille du plateau X/Y : 220 mm x 160 mm\r\nVolume maximal de travail: 203,2
mm (X), 152,4 mm (Y), 60,5 mm (Z)\r\nPrécision usinage: 0,00625 mm\r\nPrécision
scannage: réglable de 0,05 à 5 mm (axes X,Y) et 0,025 mm (axe Z)\r\nVitesse d'analyse
(scannage): 4-15 mm/sec\r\n \r\n \r\nLogiciel utilisé pour le fraisage: Roland
Modela player 4 \r\nLogiciel utilisé pour l'usinage de circuits imprimés: Cad.py
(linux)\r\nFormats acceptés: STL,PNG 3D\r\nFormat d'exportation des données scannées:
DXF, VRML, STL, 3DMF, IGES, Grayscale, Point Group et BMP\r\n"
created_at: 2016-04-04 14:11:34.379481000 Z
updated_at: 2016-04-04 14:11:34.379481000 Z
slug: petite-fraiseuse
machine_6:
id: 6
name: FORM1+ imprimante 3D
description: |-
Form 1+, imprimante 3D stéréolithographie.
La photopolymérisation est le premier procédé de prototypage rapide à avoir été développé dans les années 1980. Le nom de SLA (pour StereoLithography Apparatus) lui a été donné. Il repose sur les propriétés qu'ont certaines résines à se polymériser sous l'effet de la lumière et de la chaleur. (Source : <a href="http://fr.wikipedia.org/wiki/St%C3%A9r%C3%A9olithographie" target="_blank"> wikipédia</a>)
<i>Possibilité d'utiliser 3 résines de couleurs différentes au Lab : noir, blanc et translucide.</i>
<a href="http://formlabs.com/fr/products/materials/standard/" Title="http://formlabs.com/fr/products/materials/standard/" target="_blank">Plus d'infos sur le site web de Formlab</a>
spec: |-
Imprimante :
- Dimensions : 30 × 28 × 45 cm
- Poids : 8 kg
- Température d'utilisation : 1828° C
- Alimentation : 100240 V ; 1.5 A 50/60 Hz ; 60 W.
Caractéristiques du laser :
- EN 60825-1:2007 certifié
- Class 1 Laser Product
- 405nm violet laser
Propriétés d'impression :
- Technologie stéréolithographie (SLA)
- Volume d'impression : 125 × 125 × 165 mm
- Dimension minimale : 300 microns
- Épaisseur des couches (Résolution verticale) : 25, 50, 100 microns
- Ressources Générées automatiquement
- Facilement amovible
created_at: 2016-04-04 14:11:34.424740000 Z
updated_at: 2016-04-04 14:11:34.424740000 Z
slug: form1-imprimante-3d

View File

@ -0,0 +1,105 @@
machines_availability_1:
id: 1
machine_id: 1
availability_id: 3
machines_availability_2:
id: 2
machine_id: 2
availability_id: 3
machines_availability_3:
id: 3
machine_id: 4
availability_id: 3
machines_availability_4:
id: 4
machine_id: 6
availability_id: 3
machines_availability_5:
id: 5
machine_id: 5
availability_id: 3
machines_availability_6:
id: 6
machine_id: 1
availability_id: 4
machines_availability_7:
id: 7
machine_id: 2
availability_id: 4
machines_availability_8:
id: 8
machine_id: 4
availability_id: 4
machines_availability_9:
id: 9
machine_id: 5
availability_id: 4
machines_availability_10:
id: 10
machine_id: 6
availability_id: 4
machines_availability_11:
id: 11
machine_id: 3
availability_id: 5
machines_availability_12:
id: 12
machine_id: 3
availability_id: 6
machines_availability_13:
id: 13
machine_id: 1
availability_id: 7
machines_availability_14:
id: 14
machine_id: 2
availability_id: 7
machines_availability_15:
id: 15
machine_id: 4
availability_id: 7
machines_availability_16:
id: 16
machine_id: 5
availability_id: 7
machines_availability_17:
id: 17
machine_id: 6
availability_id: 7
machines_availability_18:
id: 18
machine_id: 2
availability_id: 13
machines_availability_19:
id: 19
machine_id: 2
availability_id: 14
machines_availability_20:
id: 20
machine_id: 2
availability_id: 15
machines_availability_21:
id: 21
machine_id: 2
availability_id: 16

182
test/fixtures/notifications.yml vendored Normal file
View File

@ -0,0 +1,182 @@
notification_7:
id: 7
receiver_id: 1
attached_object_id: 1
attached_object_type: Project
notification_type_id: 1
is_read: false
created_at: 2016-04-04 15:39:08.273215000 Z
updated_at: 2016-04-04 15:39:08.273215000 Z
receiver_type: User
is_send: true
meta_data: {}
notification_1:
id: 1
receiver_id: 1
attached_object_id: 1
attached_object_type: User
notification_type_id: 11
is_read: true
created_at: 2016-04-04 14:11:33.885243000 Z
updated_at: 2016-04-04 14:11:33.885243000 Z
receiver_type: User
is_send: true
meta_data: {}
notification_2:
id: 2
receiver_id: 1
attached_object_id: 2
attached_object_type: User
notification_type_id: 11
is_read: true
created_at: 2016-04-04 15:00:29.145046000 Z
updated_at: 2016-04-04 15:00:29.145046000 Z
receiver_type: User
is_send: true
meta_data: {}
notification_3:
id: 3
receiver_id: 1
attached_object_id: 3
attached_object_type: User
notification_type_id: 11
is_read: true
created_at: 2016-04-04 15:07:46.698906000 Z
updated_at: 2016-04-04 15:07:46.698906000 Z
receiver_type: User
is_send: true
meta_data: {}
notification_4:
id: 4
receiver_id: 1
attached_object_id: 4
attached_object_type: User
notification_type_id: 11
is_read: true
created_at: 2016-04-04 15:10:42.365920000 Z
updated_at: 2016-04-04 15:10:42.365920000 Z
receiver_type: User
is_send: true
meta_data: {}
notification_5:
id: 5
receiver_id: 1
attached_object_id: 5
attached_object_type: User
notification_type_id: 11
is_read: true
created_at: 2016-04-04 15:14:08.589419000 Z
updated_at: 2016-04-04 15:14:08.589419000 Z
receiver_type: User
is_send: true
meta_data: {}
notification_6:
id: 6
receiver_id: 1
attached_object_id: 6
attached_object_type: User
notification_type_id: 11
is_read: true
created_at: 2016-04-04 15:17:12.548875000 Z
updated_at: 2016-04-04 15:17:12.548875000 Z
receiver_type: User
is_send: true
meta_data: {}
notification_10:
id: 10
receiver_id: 6
attached_object_id: 1
attached_object_type: Subscription
notification_type_id: 23
is_read: false
created_at: 2016-04-05 08:35:51.844242000 Z
updated_at: 2016-04-05 08:35:51.844242000 Z
receiver_type: User
is_send: true
meta_data: {}
notification_11:
id: 11
receiver_id: 3
attached_object_id: 1
attached_object_type: Invoice
notification_type_id: 13
is_read: false
created_at: 2016-04-05 08:35:53.327086000 Z
updated_at: 2016-04-05 08:35:53.327086000 Z
receiver_type: User
is_send: true
meta_data: {}
notification_9:
id: 9
receiver_id: 1
attached_object_id: 1
attached_object_type: Subscription
notification_type_id: 12
is_read: false
created_at: 2016-04-05 08:35:51.837022000 Z
updated_at: 2016-04-05 08:35:51.837022000 Z
receiver_type: User
is_send: true
meta_data: {}
notification_13:
id: 13
receiver_id: 1
attached_object_id: 2
attached_object_type: Subscription
notification_type_id: 12
is_read: false
created_at: 2016-04-05 08:36:46.841579000 Z
updated_at: 2016-04-05 08:36:46.841579000 Z
receiver_type: User
is_send: true
meta_data: {}
notification_14:
id: 14
receiver_id: 4
attached_object_id: 2
attached_object_type: Invoice
notification_type_id: 13
is_read: false
created_at: 2016-04-05 08:36:47.235854000 Z
updated_at: 2016-04-05 08:36:47.235854000 Z
receiver_type: User
is_send: true
meta_data: {}
notification_8:
id: 8
receiver_id: 3
attached_object_id: 1
attached_object_type: Subscription
notification_type_id: 5
is_read: false
created_at: 2016-04-05 08:35:51.792984000 Z
updated_at: 2016-04-05 08:35:51.792984000 Z
receiver_type: User
is_send: true
meta_data: {}
notification_12:
id: 12
receiver_id: 4
attached_object_id: 2
attached_object_type: Subscription
notification_type_id: 5
is_read: false
created_at: 2016-04-05 08:36:46.833829000 Z
updated_at: 2016-04-05 08:36:46.833829000 Z
receiver_type: User
is_send: true
meta_data: {}

Some files were not shown because too many files have changed in this diff Show More