diff --git a/.rspec b/.rspec
new file mode 100644
index 0000000..c99d2e7
--- /dev/null
+++ b/.rspec
@@ -0,0 +1 @@
+--require spec_helper
diff --git a/Gemfile b/Gemfile
index a29151f..30b89f1 100644
--- a/Gemfile
+++ b/Gemfile
@@ -56,11 +56,16 @@ gem 'faker'
gem 'kaminari'
+gem 'sassc'
+
+gem 'activeadmin'
+
group :development, :test do
# See https://guides.rubyonrails.org/debugging_rails_applications.html#debugging-with-the-debug-gem
gem 'bullet'
gem 'debug', platforms: %i[mri mswin mswin64 mingw x64_mingw]
gem 'factory_bot_rails'
+ gem 'rspec-rails'
end
group :development do
@@ -83,5 +88,8 @@ end
group :test do
# Use system testing [https://guides.rubyonrails.org/testing.html#system-testing]
gem 'capybara'
+ gem 'database_cleaner-active_record'
gem 'selenium-webdriver'
+ gem 'shoulda-matchers'
+ gem 'simplecov', require: false
end
diff --git a/Gemfile.lock b/Gemfile.lock
index a26fe3a..b99b6e7 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -50,6 +50,16 @@ GEM
erubi (~> 1.11)
rails-dom-testing (~> 2.2)
rails-html-sanitizer (~> 1.6)
+ activeadmin (3.2.2)
+ arbre (~> 1.2, >= 1.2.1)
+ csv
+ formtastic (>= 3.1)
+ formtastic_i18n (>= 0.4)
+ inherited_resources (~> 1.7)
+ jquery-rails (>= 4.2)
+ kaminari (>= 1.2.1)
+ railties (>= 6.1)
+ ransack (>= 4.0)
activejob (7.1.3.3)
activesupport (= 7.1.3.3)
globalid (>= 0.3.6)
@@ -77,6 +87,9 @@ GEM
tzinfo (~> 2.0)
addressable (2.8.6)
public_suffix (>= 2.0.2, < 6.0)
+ arbre (1.7.0)
+ activesupport (>= 3.0.0)
+ ruby2_keywords (>= 0.0.2)
ast (2.4.2)
base64 (0.2.0)
bcrypt (3.1.20)
@@ -105,6 +118,11 @@ GEM
crass (1.0.6)
cssbundling-rails (1.4.0)
railties (>= 6.0.0)
+ csv (3.3.0)
+ database_cleaner-active_record (2.2.0)
+ activerecord (>= 5.a)
+ database_cleaner-core (~> 2.0.0)
+ database_cleaner-core (2.0.1)
date (3.3.4)
debug (1.9.2)
irb (~> 1.10)
@@ -115,6 +133,8 @@ GEM
railties (>= 4.1.0)
responders
warden (~> 1.2.3)
+ diff-lcs (1.5.1)
+ docile (1.4.0)
drb (2.2.1)
dry-configurable (1.1.0)
dry-core (~> 1.0, < 2)
@@ -155,13 +175,24 @@ GEM
ffi (1.17.0)
ffi (1.17.0-arm64-darwin)
ffi (1.17.0-x86_64-darwin)
+ formtastic (5.0.0)
+ actionpack (>= 6.0.0)
+ formtastic_i18n (0.7.0)
globalid (1.2.1)
activesupport (>= 6.1)
+ has_scope (0.8.2)
+ actionpack (>= 5.2)
+ activesupport (>= 5.2)
i18n (1.14.5)
concurrent-ruby (~> 1.0)
image_processing (1.12.2)
mini_magick (>= 4.9.5, < 5)
ruby-vips (>= 2.0.17, < 3)
+ inherited_resources (1.14.0)
+ actionpack (>= 6.0)
+ has_scope (>= 0.6)
+ railties (>= 6.0)
+ responders (>= 2)
io-console (0.7.2)
irb (1.13.1)
rdoc (>= 4.0.0)
@@ -169,6 +200,10 @@ GEM
jbuilder (2.12.0)
actionview (>= 5.0.0)
activesupport (>= 5.0.0)
+ jquery-rails (4.6.0)
+ rails-dom-testing (>= 1, < 3)
+ railties (>= 4.2.0)
+ thor (>= 0.14, < 2.0)
jsbundling-rails (1.3.0)
railties (>= 6.0.0)
json (2.7.2)
@@ -286,6 +321,10 @@ GEM
zeitwerk (~> 2.6)
rainbow (3.1.1)
rake (13.2.1)
+ ransack (4.2.0)
+ activerecord (>= 6.1.5)
+ activesupport (>= 6.1.5)
+ i18n
rdoc (6.7.0)
psych (>= 4.0.0)
reek (6.3.0)
@@ -302,6 +341,23 @@ GEM
railties (>= 5.2)
rexml (3.2.8)
strscan (>= 3.0.9)
+ rspec-core (3.13.0)
+ rspec-support (~> 3.13.0)
+ rspec-expectations (3.13.1)
+ diff-lcs (>= 1.2.0, < 2.0)
+ rspec-support (~> 3.13.0)
+ rspec-mocks (3.13.1)
+ diff-lcs (>= 1.2.0, < 2.0)
+ rspec-support (~> 3.13.0)
+ rspec-rails (6.1.3)
+ actionpack (>= 6.1)
+ activesupport (>= 6.1)
+ railties (>= 6.1)
+ rspec-core (~> 3.13)
+ rspec-expectations (~> 3.13)
+ rspec-mocks (~> 3.13)
+ rspec-support (~> 3.13)
+ rspec-support (3.13.1)
rubocop (1.64.1)
json (~> 2.3)
language_server-protocol (>= 3.17.0)
@@ -318,13 +374,24 @@ GEM
ruby-progressbar (1.13.0)
ruby-vips (2.2.1)
ffi (~> 1.12)
+ ruby2_keywords (0.0.5)
rubyzip (2.3.2)
+ sassc (2.4.0)
+ ffi (~> 1.9)
selenium-webdriver (4.21.1)
base64 (~> 0.2)
rexml (~> 3.2, >= 3.2.5)
rubyzip (>= 1.2.2, < 3.0)
websocket (~> 1.0)
sexp_processor (4.17.1)
+ shoulda-matchers (5.3.0)
+ activesupport (>= 5.2.0)
+ simplecov (0.22.0)
+ docile (~> 1.1)
+ simplecov-html (~> 0.11)
+ simplecov_json_formatter (~> 0.1)
+ simplecov-html (0.12.3)
+ simplecov_json_formatter (0.1.4)
sprockets (4.2.1)
concurrent-ruby (~> 1.0)
rack (>= 2.2.4, < 4)
@@ -377,10 +444,12 @@ PLATFORMS
x86_64-linux
DEPENDENCIES
+ activeadmin
bootsnap
bullet
capybara
cssbundling-rails
+ database_cleaner-active_record
debug
devise (~> 4.9)
factory_bot_rails
@@ -395,8 +464,12 @@ DEPENDENCIES
rails (~> 7.1.3, >= 7.1.3.3)
rails_best_practices
reek
+ rspec-rails
rubocop
+ sassc
selenium-webdriver
+ shoulda-matchers
+ simplecov
sprockets-rails
sqlite3 (~> 1.4)
stimulus-rails
diff --git a/app/admin/admin_users.rb b/app/admin/admin_users.rb
new file mode 100644
index 0000000..4ea7d8c
--- /dev/null
+++ b/app/admin/admin_users.rb
@@ -0,0 +1,26 @@
+ActiveAdmin.register AdminUser do
+ permit_params :email, :password, :password_confirmation
+ index do
+ selectable_column
+ id_column
+ column :email
+ column :current_sign_in_at
+ column :sign_in_count
+ column :created_at
+ actions
+ end
+
+ filter :email
+ filter :current_sign_in_at
+ filter :sign_in_count
+ filter :created_at
+
+ form do |f|
+ f.inputs do
+ f.input :email
+ f.input :password
+ f.input :password_confirmation
+ end
+ f.actions
+ end
+end
diff --git a/app/admin/categories.rb b/app/admin/categories.rb
new file mode 100644
index 0000000..fd287aa
--- /dev/null
+++ b/app/admin/categories.rb
@@ -0,0 +1,33 @@
+ActiveAdmin.register Category do
+ remove_filter :gift_categorizations
+ filter :name
+ filter :created_at
+ filter :updated_at
+ permit_params :name
+
+ show do
+ attributes_table do
+ row :name
+ row :created_at
+ row :updated_at
+ end
+ active_admin_comments
+ end
+
+ index do
+ selectable_column
+ id_column
+ column :name
+ column :created_at
+ column :updated_at
+
+ actions
+ end
+
+ form do |f|
+ f.inputs 'Detalles' do
+ f.input :name
+ end
+ f.actions
+ end
+end
diff --git a/app/admin/customizations.rb b/app/admin/customizations.rb
new file mode 100644
index 0000000..b520768
--- /dev/null
+++ b/app/admin/customizations.rb
@@ -0,0 +1,33 @@
+ActiveAdmin.register Customization do
+ permit_params :name, :price
+ filter :name
+ filter :price
+
+ index do
+ selectable_column
+ id_column
+ column :name
+ column :price
+ column :created_at
+ column :updated_at
+ actions
+ end
+
+ show do
+ attributes_table do
+ row :name
+ row :price
+ row :created_at
+ row :updated_at
+ end
+ active_admin_comments
+ end
+
+ form do |f|
+ f.inputs 'Detalles' do
+ f.input :name
+ f.input :price
+ end
+ f.actions
+ end
+end
diff --git a/app/admin/dashboard.rb b/app/admin/dashboard.rb
new file mode 100644
index 0000000..21064f9
--- /dev/null
+++ b/app/admin/dashboard.rb
@@ -0,0 +1,34 @@
+# frozen_string_literal: true
+
+ActiveAdmin.register_page 'Dashboard' do
+ menu priority: 1, label: proc { I18n.t('active_admin.dashboard') }
+
+ content title: proc { I18n.t('active_admin.dashboard') } do
+ div class: 'blank_slate_container', id: 'dashboard_default_message' do
+ span class: 'blank_slate' do
+ span I18n.t('active_admin.dashboard_welcome.welcome')
+ small I18n.t('active_admin.dashboard_welcome.call_to_action')
+ end
+ end
+
+ # Here is an example of a simple dashboard with columns and panels.
+ #
+ # columns do
+ # column do
+ # panel "Recent Posts" do
+ # ul do
+ # Post.recent(5).map do |post|
+ # li link_to(post.title, admin_post_path(post))
+ # end
+ # end
+ # end
+ # end
+
+ # column do
+ # panel "Info" do
+ # para "Welcome to ActiveAdmin."
+ # end
+ # end
+ # end
+ end
+end
diff --git a/app/admin/gifts.rb b/app/admin/gifts.rb
new file mode 100644
index 0000000..b16c27b
--- /dev/null
+++ b/app/admin/gifts.rb
@@ -0,0 +1,80 @@
+ActiveAdmin.register Gift do
+ permit_params :name, :price, :valoration, :supplier_id, :image, :content, category_ids: [],
+ customization_ids: []
+
+ remove_filter :gift_customizations, :gift_categorizations, :purchases,
+ :image_attachment, :image_blob, :rich_text_content
+
+ filter :name
+ filter :price
+ filter :valoration
+ filter :supplier
+ filter :categories, multiple: true
+ filter :customizations, multiple: true
+ filter :created_at
+ filter :updated_at
+
+ controller do
+ def scoped_collection
+ super.includes(:supplier)
+ end
+ end
+
+ index do
+ selectable_column
+ id_column
+ column :name
+ column :price
+ column :valoration
+ column :supplier
+ column :created_at
+ column :updated_at
+ actions
+ end
+
+ show do
+ attributes_table do
+ row :name
+ row :price
+ row :valoration
+ row :supplier
+ row 'Imagen' do |gift|
+ image_tag gift.image_resized_for_purchase
+ end
+ row 'Contenido' do |gift|
+ gift.content.to_s
+ end
+ row 'Categorías' do |gift|
+ dropdown_menu '' do
+ gift.categories.each do |category|
+ item category.name
+ end
+ end
+ end
+ row 'Personalizaciones' do |gift|
+ dropdown_menu '' do
+ gift.customizations.each do |customization|
+ item customization.name, admin_customization_path(customization)
+ end
+ end
+ end
+ row :created_at
+ row :updated_at
+ end
+ active_admin_comments
+ end
+
+ form do |f|
+ f.inputs 'Detalles' do
+ f.input :name
+ f.input :price
+ f.input :valoration
+ f.input :supplier
+ f.input :image, as: :file
+ f.input :content
+ f.input :categories
+ f.input :customizations
+ end
+ f.actions
+ end
+end
diff --git a/app/admin/purchases.rb b/app/admin/purchases.rb
new file mode 100644
index 0000000..b935d83
--- /dev/null
+++ b/app/admin/purchases.rb
@@ -0,0 +1,98 @@
+ActiveAdmin.register Purchase do
+ permit_params :RUT, :social_reason, :suprise_delivery,
+ :personalization, :resend_delivery, :amount, :company_logo,
+ :gift_id,
+ :payment_method_id,
+ customization_ids: [],
+ destinations_attributes: %i[id receiver day address number cost schedules _destroy]
+
+ controller do
+ def scoped_collection
+ super.includes(:user, :gift, :customizations)
+ end
+ end
+
+ remove_filter :payment_method, :destinations, :subtotal, :personalization
+ filter :gift
+ filter :user, as: :select, collection: User.all.map { |user|
+ [user.email, user.id]
+ }
+ filter :price
+ filter :amount
+ filter :suprise_delivery
+ filter :resend_delivery
+ filter :created_at
+ filter :updated_at
+
+ index do
+ selectable_column
+ id_column
+ column :price
+ column :amount
+ column :suprise_delivery
+ column :resend_delivery
+ column :gift
+ column 'Usuario' do |purchase|
+ link_to purchase.user_email, admin_user_path(purchase.user)
+ end
+ column :created_at
+ actions
+ end
+
+ show do
+ attributes_table do
+ row :RUT
+ row :social_reason
+ row :price
+ row :amount
+ row :personalization
+ row :suprise_delivery
+ row :resend_delivery
+ row 'Logo' do |purchase|
+ image_tag purchase.company_logo if purchase.company_logo.present?
+ end
+ row :gift
+ row 'Usuario' do |purchase|
+ link_to purchase.user_email, admin_user_path(purchase.user)
+ end
+ row :created_at
+ row :updated_at
+ end
+ active_admin_comments
+ end
+
+ form do |f|
+ f.inputs 'Detalles de la Compra' do
+ f.input :RUT
+ f.input :social_reason
+ f.input :amount
+ f.input :personalization
+ f.input :suprise_delivery
+ f.input :resend_delivery
+ f.input :gift if f.object.new_record?
+
+ unless f.object.new_record?
+ f.input :customizations, as: :select,
+ collection: Customization.joins(:gift_customizations)
+ .where(gift_customizations: { gift_id:
+ f.object.gift_id })
+ end
+ f.input :company_logo, as: :file
+ f.input :payment_method, as: :select,
+ collection: PaymentMethod.all.order('user_id').map { |pm|
+ ["#{pm.name} (#{pm.user.email})", pm.id]
+ }
+ f.inputs 'Destinatarios' do
+ f.has_many :destinations, allow_destroy: true, heading: false do |destination|
+ destination.input :receiver
+ destination.input :day, as: :date_picker
+ destination.input :address
+ destination.input :number
+ destination.input :cost
+ destination.input :schedules
+ end
+ end
+ end
+ f.actions
+ end
+end
diff --git a/app/admin/suppliers.rb b/app/admin/suppliers.rb
new file mode 100644
index 0000000..92129b7
--- /dev/null
+++ b/app/admin/suppliers.rb
@@ -0,0 +1,53 @@
+ActiveAdmin.register Supplier do
+ remove_filter :gifts
+ filter :name
+ filter :created_at
+ filter :updated_at
+ permit_params :name
+
+ controller do
+ def scoped_collection
+ super.includes(:gifts)
+ end
+ end
+
+ index do
+ selectable_column
+ id_column
+ column :name
+ column 'Regalos' do |supplier|
+ dropdown_menu '' do
+ supplier.gifts.each do |gift|
+ item gift.name, admin_gift_path(gift)
+ end
+ end
+ end
+ column :created_at
+ column :updated_at
+
+ actions
+ end
+
+ form do |f|
+ f.inputs 'Detalles' do
+ f.input :name
+ end
+ f.actions
+ end
+
+ show do
+ attributes_table do
+ row :name
+ row 'Regalos' do |supplier|
+ dropdown_menu '' do
+ supplier.gifts.each do |gift|
+ item gift.name, admin_gift_path(gift)
+ end
+ end
+ end
+ row :created_at
+ row :updated_at
+ end
+ active_admin_comments
+ end
+end
diff --git a/app/admin/users.rb b/app/admin/users.rb
new file mode 100644
index 0000000..995eee1
--- /dev/null
+++ b/app/admin/users.rb
@@ -0,0 +1,76 @@
+ActiveAdmin.register User do
+ permit_params :name, :last_name, :email, :company_name, :password,
+ payment_methods_attributes: %i[id name owner card_number due_date CVV _destroy]
+
+ filter :name
+ filter :last_name
+ filter :email
+ filter :company_name
+ filter :created_at
+ filter :updated_at
+
+ controller do
+ def scoped_collection
+ super.includes(:payment_methods)
+ end
+ end
+
+ index do
+ selectable_column
+ id_column
+ column :name
+ column :last_name
+ column :email
+ column :company_name
+ column 'Métodos de Pago' do |user|
+ dropdown_menu '' do
+ user.payment_methods.each do |payment_method|
+ item payment_method.name
+ end
+ end
+ end
+ column :created_at
+ column :updated_at
+ actions
+ end
+
+ show do
+ attributes_table do
+ row :name
+ row :last_name
+ row :email
+ row :company_name
+ row 'Métodos de Pago' do |user|
+ dropdown_menu '' do
+ user.payment_methods.each do |payment_method|
+ item payment_method.name
+ end
+ end
+ end
+ row :created_at
+ row :updated_at
+ end
+ active_admin_comments
+ end
+
+ form do |f|
+ f.inputs 'Detalles del Usuario' do
+ f.input :name
+ f.input :last_name
+ f.inputs 'Métodos de Pago' do
+ f.has_many :payment_methods,
+ allow_destroy: true, heading: false do |payment_method|
+ payment_method.input :name
+ payment_method.input :owner
+ payment_method.input :card_number
+ payment_method.input :due_date, as: :date_picker
+ payment_method.input :CVV
+ end
+ end
+ f.input :email
+ f.input :company_name
+ f.input :password if f.object.new_record?
+ end
+ f.actions
+ end
+end
diff --git a/app/assets/javascripts/active_admin.js b/app/assets/javascripts/active_admin.js
new file mode 100644
index 0000000..d2b66c5
--- /dev/null
+++ b/app/assets/javascripts/active_admin.js
@@ -0,0 +1 @@
+//= require active_admin/base
diff --git a/app/assets/stylesheets/active_admin.scss b/app/assets/stylesheets/active_admin.scss
new file mode 100644
index 0000000..41c27b3
--- /dev/null
+++ b/app/assets/stylesheets/active_admin.scss
@@ -0,0 +1,17 @@
+// Sass variable overrides must be declared before loading up Active Admin's styles.
+//
+// To view the variables that Active Admin provides, take a look at
+// `app/assets/stylesheets/active_admin/mixins/_variables.scss` in the
+// Active Admin source.
+//
+// For example, to change the sidebar width:
+// $sidebar-width: 242px;
+
+// Active Admin's got SASS!
+@import "active_admin/mixins";
+@import "active_admin/base";
+
+// Overriding any non-variable Sass must be done after the fact.
+// For example, to change the default status-tag color:
+//
+// .status_tag { background: #6090DB; }
diff --git a/app/controllers/purchases_controller.rb b/app/controllers/purchases_controller.rb
index 2258afe..41f2471 100644
--- a/app/controllers/purchases_controller.rb
+++ b/app/controllers/purchases_controller.rb
@@ -1,6 +1,7 @@
class PurchasesController < ApplicationController
def new
@purchase = Purchase.new(purchase_params_with_defaults)
+ puts @purchase.subtotal
@purchase.destinations.build
end
diff --git a/app/models/admin_user.rb b/app/models/admin_user.rb
new file mode 100644
index 0000000..4be21dc
--- /dev/null
+++ b/app/models/admin_user.rb
@@ -0,0 +1,11 @@
+class AdminUser < ApplicationRecord
+ # Include default devise modules. Others available are:
+ # :confirmable, :lockable, :timeoutable, :trackable and :omniauthable
+ devise :database_authenticatable,
+ :recoverable, :rememberable, :validatable
+
+ def self.ransackable_attributes(_auth_object = nil)
+ %w[created_at email id id_value remember_created_at
+ updated_at]
+ end
+end
diff --git a/app/models/category.rb b/app/models/category.rb
index 7c7dfa9..8e10d7e 100644
--- a/app/models/category.rb
+++ b/app/models/category.rb
@@ -1,4 +1,4 @@
class Category < ApplicationRecord
- has_many :gift_categorizations
+ has_many :gift_categorizations, dependent: :destroy
has_many :gifts, through: :gift_categorizations
end
diff --git a/app/models/customization.rb b/app/models/customization.rb
index 64362fb..44bd9c3 100644
--- a/app/models/customization.rb
+++ b/app/models/customization.rb
@@ -1,5 +1,7 @@
class Customization < ApplicationRecord
- has_many :gift_customizations
+ has_many :gift_customizations, dependent: :destroy
has_many :gifts, through: :gift_customizations
has_and_belongs_to_many :purchases
+
+ validates :name, :price, presence: true
end
diff --git a/app/models/destination.rb b/app/models/destination.rb
index 6a3d1d7..4f123af 100644
--- a/app/models/destination.rb
+++ b/app/models/destination.rb
@@ -1,4 +1,5 @@
class Destination < ApplicationRecord
belongs_to :purchase
validates :receiver, :day, :schedules, :address, :number, :cost, presence: true
+ validates :day, comparison: { greater_than: Date.today }
end
diff --git a/app/models/gift.rb b/app/models/gift.rb
index 99feb91..58431c0 100644
--- a/app/models/gift.rb
+++ b/app/models/gift.rb
@@ -1,14 +1,19 @@
class Gift < ApplicationRecord
- has_many :gift_categorizations
+ has_many :gift_categorizations, dependent: :destroy
has_many :categories, through: :gift_categorizations
- has_many :gift_customizations
+ has_many :gift_customizations, dependent: :destroy
has_many :customizations, through: :gift_customizations
- has_many :purchases
+ has_many :purchases, dependent: :destroy
belongs_to :supplier
delegate :name, to: :supplier, prefix: true
has_one_attached :image
has_rich_text :content
+ validates :name, :price, :valoration, :supplier, :image, :categories,
+ :content, presence: true
+ validates :price, numericality: { greater_than: 0 }
+ validates :valoration, numericality: { greater_than_or_equal_to: 0, less_than_or_equal_to: 5 }
+
scope :with_categories, lambda { |categories|
joins(:gift_categorizations)
.where(gift_categorizations: { category_id: categories })
diff --git a/app/models/payment_method.rb b/app/models/payment_method.rb
index 3a7beac..dd40efa 100644
--- a/app/models/payment_method.rb
+++ b/app/models/payment_method.rb
@@ -1,6 +1,6 @@
class PaymentMethod < ApplicationRecord
belongs_to :user
- has_many :purchases
+ has_many :purchases, dependent: :destroy
validates :name, :owner, :card_number, :due_date, :CVV, presence: true
end
diff --git a/app/models/purchase.rb b/app/models/purchase.rb
index 5ff887e..bf51fb4 100644
--- a/app/models/purchase.rb
+++ b/app/models/purchase.rb
@@ -1,16 +1,30 @@
class Purchase < ApplicationRecord
belongs_to :payment_method
+ has_one :user, through: :payment_method
belongs_to :gift
- has_many :destinations
+ has_many :destinations, dependent: :destroy
accepts_nested_attributes_for :destinations
has_and_belongs_to_many :customizations
accepts_nested_attributes_for :customizations
has_one_attached :company_logo
+ validates :amount, numericality: { greater_than: 0 }
+ validates :destinations, length: { minimum: 1 }
+ validates :personalization, :amount, :social_reason, :RUT, :destinations, :payment_method,
+ presence: true
+
delegate :price, :name, to: :gift, prefix: true
delegate :name, to: :payment_method, prefix: true
- validates :destinations, length: { minimum: 1 }
- validates :personalization, :social_reason, :RUT, :destinations, presence: true
+ delegate :email, to: :user, prefix: true
+
+ def price
+ subtotal + (subtotal * 0.22).to_i + 180
+ end
+
+ def subtotal
+ customizations_cost = customizations.map(&:price).sum.to_i
+ (gift_price + customizations_cost) * amount
+ end
def logo_resized
company_logo.variant(resize_to_limit: [50, 25]).processed
diff --git a/app/models/supplier.rb b/app/models/supplier.rb
index 142f48d..d3d1cdd 100644
--- a/app/models/supplier.rb
+++ b/app/models/supplier.rb
@@ -1,3 +1,4 @@
class Supplier < ApplicationRecord
- has_many :gifts
+ has_many :gifts, dependent: :destroy
+ validates :name, presence: true
end
diff --git a/app/models/user.rb b/app/models/user.rb
index f1e53a1..d25cc66 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -1,6 +1,7 @@
class User < ApplicationRecord
- has_many :payment_methods
-
+ has_many :payment_methods, dependent: :destroy
+ accepts_nested_attributes_for :payment_methods, allow_destroy: true
+ has_many :purchases, through: :payment_methods
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable, :trackable and :omniauthable
devise :database_authenticatable, :registerable,
diff --git a/app/views/purchases/index.html.erb b/app/views/purchases/index.html.erb
index 6660212..ffcc137 100644
--- a/app/views/purchases/index.html.erb
+++ b/app/views/purchases/index.html.erb
@@ -19,7 +19,7 @@
-
<%= purchase.gift_name.truncate(12, separator: ' ') %>
+
<%= purchase.gift_name.truncate(10, separator: ' ') %>
<%= I18n.l(purchase.created_at, format: "%B %d, %Y") %>
diff --git a/app/views/purchases/show.html.erb b/app/views/purchases/show.html.erb
index 298b0af..a5dc893 100644
--- a/app/views/purchases/show.html.erb
+++ b/app/views/purchases/show.html.erb
@@ -78,6 +78,7 @@
<%= image_tag(@purchase.gift.image_resized_for_purchase, class:'img-gift-purchase') %>
<%= "#{@purchase.gift.supplier_name} | #{@purchase.gift_name}" %>
+
Se compraron <%= @purchase.amount %> Unidades
Pagado a través de <%= @purchase.payment_method_name %>
diff --git a/config/initializers/active_admin.rb b/config/initializers/active_admin.rb
new file mode 100644
index 0000000..e8b8cef
--- /dev/null
+++ b/config/initializers/active_admin.rb
@@ -0,0 +1,355 @@
+ActiveAdmin.setup do |config|
+ # == Site Title
+ #
+ # Set the title that is displayed on the main layout
+ # for each of the active admin pages.
+ #
+ config.site_title = 'Planit'
+ config.skip_before_action :authenticate_user!
+
+ # Set the link url for the title. For example, to take
+ # users to your main site. Defaults to no link.
+ #
+ # config.site_title_link = "/"
+
+ # Set an optional image to be displayed for the header
+ # instead of a string (overrides :site_title)
+ #
+ # Note: Aim for an image that's 21px high so it fits in the header.
+ #
+ # config.site_title_image = "logo.png"
+
+ # == Load Paths
+ #
+ # By default Active Admin files go inside app/admin/.
+ # You can change this directory.
+ #
+ # eg:
+ # config.load_paths = [File.join(Rails.root, 'app', 'ui')]
+ #
+ # Or, you can also load more directories.
+ # Useful when setting namespaces with users that are not your main AdminUser entity.
+ #
+ # eg:
+ # config.load_paths = [
+ # File.join(Rails.root, 'app', 'admin'),
+ # File.join(Rails.root, 'app', 'cashier')
+ # ]
+
+ # == Default Namespace
+ #
+ # Set the default namespace each administration resource
+ # will be added to.
+ #
+ # eg:
+ # config.default_namespace = :hello_world
+ #
+ # This will create resources in the HelloWorld module and
+ # will namespace routes to /hello_world/*
+ #
+ # To set no namespace by default, use:
+ # config.default_namespace = false
+ #
+ # Default:
+ # config.default_namespace = :admin
+ #
+ # You can customize the settings for each namespace by using
+ # a namespace block. For example, to change the site title
+ # within a namespace:
+ #
+ # config.namespace :admin do |admin|
+ # admin.site_title = "Custom Admin Title"
+ # end
+ #
+ # This will ONLY change the title for the admin section. Other
+ # namespaces will continue to use the main "site_title" configuration.
+
+ # == User Authentication
+ #
+ # Active Admin will automatically call an authentication
+ # method in a before filter of all controller actions to
+ # ensure that there is a currently logged in admin user.
+ #
+ # This setting changes the method which Active Admin calls
+ # within the application controller.
+ config.authentication_method = :authenticate_admin_user!
+
+ # == User Authorization
+ #
+ # Active Admin will automatically call an authorization
+ # method in a before filter of all controller actions to
+ # ensure that there is a user with proper rights. You can use
+ # CanCanAdapter or make your own. Please refer to documentation.
+ # config.authorization_adapter = ActiveAdmin::CanCanAdapter
+
+ # In case you prefer Pundit over other solutions you can here pass
+ # the name of default policy class. This policy will be used in every
+ # case when Pundit is unable to find suitable policy.
+ # config.pundit_default_policy = "MyDefaultPunditPolicy"
+
+ # If you wish to maintain a separate set of Pundit policies for admin
+ # resources, you may set a namespace here that Pundit will search
+ # within when looking for a resource's policy.
+ # config.pundit_policy_namespace = :admin
+
+ # You can customize your CanCan Ability class name here.
+ # config.cancan_ability_class = "Ability"
+
+ # You can specify a method to be called on unauthorized access.
+ # This is necessary in order to prevent a redirect loop which happens
+ # because, by default, user gets redirected to Dashboard. If user
+ # doesn't have access to Dashboard, he'll end up in a redirect loop.
+ # Method provided here should be defined in application_controller.rb.
+ # config.on_unauthorized_access = :access_denied
+
+ # == Current User
+ #
+ # Active Admin will associate actions with the current
+ # user performing them.
+ #
+ # This setting changes the method which Active Admin calls
+ # (within the application controller) to return the currently logged in user.
+ config.current_user_method = :current_admin_user
+
+ # == Logging Out
+ #
+ # Active Admin displays a logout link on each screen. These
+ # settings configure the location and method used for the link.
+ #
+ # This setting changes the path where the link points to. If it's
+ # a string, the strings is used as the path. If it's a Symbol, we
+ # will call the method to return the path.
+ #
+ # Default:
+ config.logout_link_path = :destroy_admin_user_session_path
+
+ # This setting changes the http method used when rendering the
+ # link. For example :get, :delete, :put, etc..
+ #
+ # Default:
+ # config.logout_link_method = :get
+
+ # == Root
+ #
+ # Set the action to call for the root path. You can set different
+ # roots for each namespace.
+ #
+ # Default:
+ # config.root_to = 'dashboard#index'
+
+ # == Admin Comments
+ #
+ # This allows your users to comment on any resource registered with Active Admin.
+ #
+ # You can completely disable comments:
+ # config.comments = false
+ #
+ # You can change the name under which comments are registered:
+ # config.comments_registration_name = 'AdminComment'
+ #
+ # You can change the order for the comments and you can change the column
+ # to be used for ordering:
+ # config.comments_order = 'created_at ASC'
+ #
+ # You can disable the menu item for the comments index page:
+ # config.comments_menu = false
+ #
+ # You can customize the comment menu:
+ # config.comments_menu = { parent: 'Admin', priority: 1 }
+
+ # == Batch Actions
+ #
+ # Enable and disable Batch Actions
+ #
+ config.batch_actions = true
+
+ # == Controller Filters
+ #
+ # You can add before, after and around filters to all of your
+ # Active Admin resources and pages from here.
+ #
+ # config.before_action :do_something_awesome
+
+ # == Attribute Filters
+ #
+ # You can exclude possibly sensitive model attributes from being displayed,
+ # added to forms, or exported by default by ActiveAdmin
+ #
+ config.filter_attributes = [:encrypted_password, :password, :password_confirmation]
+
+ # == Localize Date/Time Format
+ #
+ # Set the localize format to display dates and times.
+ # To understand how to localize your app with I18n, read more at
+ # https://guides.rubyonrails.org/i18n.html
+ #
+ # You can run `bin/rails runner 'puts I18n.t("date.formats")'` to see the
+ # available formats in your application.
+ #
+ config.localize_format = :long
+
+ # == Setting a Favicon
+ #
+ # config.favicon = 'favicon.ico'
+
+ # == Meta Tags
+ #
+ # Add additional meta tags to the head element of active admin pages.
+ #
+ # Add tags to all pages logged in users see:
+ # config.meta_tags = { author: 'My Company' }
+
+ # By default, sign up/sign in/recover password pages are excluded
+ # from showing up in search engine results by adding a robots meta
+ # tag. You can reset the hash of meta tags included in logged out
+ # pages:
+ # config.meta_tags_for_logged_out_pages = {}
+
+ # == Removing Breadcrumbs
+ #
+ # Breadcrumbs are enabled by default. You can customize them for individual
+ # resources or you can disable them globally from here.
+ #
+ # config.breadcrumb = false
+
+ # == Create Another Checkbox
+ #
+ # Create another checkbox is disabled by default. You can customize it for individual
+ # resources or you can enable them globally from here.
+ #
+ # config.create_another = true
+
+ # == Register Stylesheets & Javascripts
+ #
+ # We recommend using the built in Active Admin layout and loading
+ # up your own stylesheets / javascripts to customize the look
+ # and feel.
+ #
+ # To load a stylesheet:
+ # config.register_stylesheet 'my_stylesheet.css'
+ #
+ # You can provide an options hash for more control,
+ # which is passed along to stylesheet_link_tag():
+ # config.register_stylesheet 'my_print_stylesheet.css', media: :print
+ #
+ # To load a javascript file:
+ # config.register_javascript 'my_javascript.js'
+
+ # == CSV options
+ #
+ # Set the CSV builder separator
+ # config.csv_options = { col_sep: ';' }
+ #
+ # Force the use of quotes
+ # config.csv_options = { force_quotes: true }
+
+ # == Menu System
+ #
+ # You can add a navigation menu to be used in your application, or configure a provided menu
+ #
+ # To change the default utility navigation to show a link to your website & a logout btn
+ #
+ # config.namespace :admin do |admin|
+ # admin.build_menu :utility_navigation do |menu|
+ # menu.add label: "My Great Website", url: "http://www.mygreatwebsite.com", html_options: { target: :blank }
+ # admin.add_logout_button_to_menu menu
+ # end
+ # end
+ #
+ # If you wanted to add a static menu item to the default menu provided:
+ #
+ # config.namespace :admin do |admin|
+ # admin.build_menu :default do |menu|
+ # menu.add label: "My Great Website", url: "http://www.mygreatwebsite.com", html_options: { target: "_blank" }
+ # end
+ # end
+
+ # == Download Links
+ #
+ # You can disable download links on resource listing pages,
+ # or customize the formats shown per namespace/globally
+ #
+ # To disable/customize for the :admin namespace:
+ #
+ # config.namespace :admin do |admin|
+ #
+ # # Disable the links entirely
+ # admin.download_links = false
+ #
+ # # Only show XML & PDF options
+ # admin.download_links = [:xml, :pdf]
+ #
+ # # Enable/disable the links based on block
+ # # (for example, with cancan)
+ # admin.download_links = proc { can?(:view_download_links) }
+ #
+ # end
+
+ # == Pagination
+ #
+ # Pagination is enabled by default for all resources.
+ # You can control the default per page count for all resources here.
+ #
+ # config.default_per_page = 30
+ #
+ # You can control the max per page count too.
+ #
+ # config.max_per_page = 10_000
+
+ # == Filters
+ #
+ # By default the index screen includes a "Filters" sidebar on the right
+ # hand side with a filter for each attribute of the registered model.
+ # You can enable or disable them for all resources here.
+ #
+ # config.filters = true
+ #
+ # By default the filters include associations in a select, which means
+ # that every record will be loaded for each association (up
+ # to the value of config.maximum_association_filter_arity).
+ # You can enabled or disable the inclusion
+ # of those filters by default here.
+ #
+ # config.include_default_association_filters = true
+
+ # config.maximum_association_filter_arity = 256
+ # default value of :unlimited will change to 256 in a future version
+ # config.filter_columns_for_large_association = [
+ # :display_name,
+ # :full_name,
+ # :name,
+ # :username,
+ # :login,
+ # :title,
+ # :email,
+ # ]
+ # config.filter_method_for_large_association = '_start'
+
+ # == Head
+ #
+ # You can add your own content to the site head like analytics. Make sure
+ # you only pass content you trust.
+ #
+ # config.head = ''.html_safe
+
+ # == Footer
+ #
+ # By default, the footer shows the current Active Admin version. You can
+ # override the content of the footer here.
+ #
+ # config.footer = 'my custom footer text'
+
+ # == Sorting
+ #
+ # By default ActiveAdmin::OrderClause is used for sorting logic
+ # You can inherit it with own class and inject it for all resources
+ #
+ # config.order_clause = MyOrderClause
+
+ # == Webpacker
+ #
+ # By default, Active Admin uses Sprocket's asset pipeline.
+ # You can switch to using Webpacker here.
+ #
+ # config.use_webpacker = true
+end
diff --git a/config/initializers/ransack.rb b/config/initializers/ransack.rb
new file mode 100644
index 0000000..cea3b36
--- /dev/null
+++ b/config/initializers/ransack.rb
@@ -0,0 +1,102 @@
+Rails.application.config.to_prepare do
+ ActiveStorage::Attachment.class_eval do
+ def self.ransackable_attributes(_auth_object = nil)
+ %w[blob_id created_at id id_value name record_id record_type]
+ end
+ end
+
+ ActionText::RichText.class_eval do
+ def self.ransackable_attributes(_auth_object = nil)
+ %w[body created_at id id_value name record_id record_type updated_at]
+ end
+ end
+
+ Supplier.class_eval do
+ def self.ransackable_associations(_auth_object = nil)
+ ['gifts']
+ end
+
+ def self.ransackable_attributes(_auth_object = nil)
+ %w[created_at id id_value name updated_at]
+ end
+ end
+
+ Purchase.class_eval do
+ def self.ransackable_attributes(_auth_object = nil)
+ %w[RUT amount created_at gift_id id id_value payment_method_id
+ personalization price resend_delivery social_reason subtotal suprise_delivery updated_at]
+ end
+ end
+
+ Gift.class_eval do
+ def self.ransackable_attributes(_auth_object = nil)
+ %w[created_at id id_value name price supplier_id updated_at valoration]
+ end
+
+ def self.ransackable_associations(_auth_object = nil)
+ %w[categories customizations gift_categorizations gift_customizations
+ image_attachment image_blob purchases rich_text_content supplier]
+ end
+ end
+
+ GiftCustomization.class_eval do
+ def self.ransackable_attributes(_auth_object = nil)
+ %w[created_at customization_id gift_id id id_value updated_at]
+ end
+ end
+
+ GiftCategorization.class_eval do
+ def self.ransackable_attributes(_auth_object = nil)
+ %w[category_id created_at gift_id id id_value updated_at]
+ end
+ end
+ User.class_eval do
+ def self.ransackable_associations(_auth_object = nil)
+ ['payment_methods']
+ end
+
+ def self.ransackable_attributes(_auth_object = nil)
+ %w[company_name created_at email id id_value last_name
+ name remember_created_at updated_at]
+ end
+ end
+
+ PaymentMethod.class_eval do
+ def self.ransackable_attributes(_auth_object = nil)
+ %w[CVV card_number created_at due_date id id_value name owner updated_at user_id]
+ end
+ end
+
+ Customization.class_eval do
+ def self.ransackable_attributes(_auth_object = nil)
+ %w[created_at id id_value name price updated_at]
+ end
+ end
+
+ Category.class_eval do
+ def self.ransackable_associations(_auth_object = nil)
+ %w[gift_categorizations gifts]
+ end
+
+ def self.ransackable_attributes(_auth_object = nil)
+ %w[created_at id id_value name updated_at]
+ end
+ end
+
+ Purchase.class_eval do
+ def self.ransackable_associations(_auth_object = nil)
+ %w[gift payment_method user]
+ end
+
+ def self.ransackable_attributes(_auth_object = nil)
+ %w[created_at updated_at RUT social_reason price suprise_delivery resend_delivery amount]
+ end
+ end
+
+ Destination.class_eval do
+ def self.ransackable_attributes(_auth_object = nil)
+ %w[address cost created_at day id id_value number purchase_id
+ receiver schedules updated_at]
+ end
+ end
+end
diff --git a/config/locales/es.yml b/config/locales/es.yml
index c8306ed..287a1d1 100644
--- a/config/locales/es.yml
+++ b/config/locales/es.yml
@@ -16,15 +16,98 @@ es:
signed_up: Usuario creado correctamente
updated: Usuario actualizado correctamente
sessions:
- user:
- signed_out: Sesión cerrada correctamente
- signed_in: Usuario logeado correctamente
+ signed_out: Sesión cerrada correctamente
+ signed_in: Usuario logeado correctamente
failure:
+ unauthenticated: Debe iniciar sesión primero
+ invalid: Usuario o Contraseña incorrectos
+ not_found_in_database: Usuario o Contraseña incorrectos
+ active_admin:
+ resources:
user:
- unauthenticated: Debe iniciar sesión primero
- invalid: Usuario o Contraseña incorrectos
- not_found_in_database: Usuario o Contraseña incorrectos
+ new_model: "Añadir Usuario"
+ gift:
+ new_model: "Añadir Regalo"
+ supplier:
+ new_model: "Añadir Proveedor"
activerecord:
+ attributes:
+ category:
+ name: Nombre
+ created_at: Fecha de Creación
+ updated_at: Última Actualización
+ customization:
+ name: Nombre
+ price: Precio
+ created_at: Fecha de Creación
+ updated_at: Última Actualización
+ gift:
+ name: Nombre
+ price: Precio
+ valoration: Valoración
+ supplier: Proveedor
+ content: Contenido
+ categories: Categorías
+ image: Imagen
+ customizations: Personalizaciones
+ created_at: Fecha de Creación
+ updated_at: Última Actualización
+ purchase:
+ RUT: RUT
+ social_reason: Razón Social
+ destinatios: Destinos
+ personalization: Mensaje Personalizado
+ payment_method: Método de Pago
+ user: Usuario
+ created_at: Fecha de Compra
+ updated_at: Última Actualización
+ supplier: Proveedor
+ customizations: Agregados
+ suprise_delivery: Entrega Sorpresa
+ resend_delivery: Reenvío Disponible
+ amount: Cantidad
+ gift: Regalo
+ price: Precio
+ company_logo: Logo
+ destination:
+ receiver: Nombre
+ day: Día
+ schedules: Horarios
+ address: Dirección
+ number: Número de Contacto
+ cost: Costo
+ created_at: Fecha de Creación
+ updated_at: Última Actualización
+ supplier:
+ name: Nombre
+ gifts: Regalos
+ created_at: Fecha de Creación
+ updated_at: Última Actualización
+ user:
+ name: Nombre
+ last_name: Apellido
+ email: Email
+ company_name: Empresa
+ password: Contraseña
+ created_at: Fecha de Creación
+ updated_at: Última Actualización
+ payment_method:
+ name: Nombre
+ owner: Titular
+ card_number: Número de Tarjeta
+ due_date: Fecha de Venicimiento
+ CVV: CVV
+ created_at: Fecha de Creación
+ updated_at: Última Actualización
+ models:
+ supplier: Proveedor
+ gift: Regalo
+ user: Usuario
+ purchase: Compra
+ payment_method: Método de Pago
+ customization: Personalización
+ category: Categoría
+ destination: Destino
errors:
models:
payment_method:
diff --git a/config/routes.rb b/config/routes.rb
index 37c6aad..1fbab76 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -1,4 +1,6 @@
Rails.application.routes.draw do
+ devise_for :admin_users, ActiveAdmin::Devise.config
+ ActiveAdmin.routes(self)
get 'users/show'
# Define your application routes per the DSL in https://guides.rubyonrails.org/routing.html
diff --git a/db/migrate/20240722171325_devise_create_admin_users.rb b/db/migrate/20240722171325_devise_create_admin_users.rb
new file mode 100644
index 0000000..8c28176
--- /dev/null
+++ b/db/migrate/20240722171325_devise_create_admin_users.rb
@@ -0,0 +1,44 @@
+# frozen_string_literal: true
+
+class DeviseCreateAdminUsers < ActiveRecord::Migration[7.1]
+ def change
+ create_table :admin_users do |t|
+ ## Database authenticatable
+ t.string :email, null: false, default: ""
+ t.string :encrypted_password, null: false, default: ""
+
+ ## Recoverable
+ t.string :reset_password_token
+ t.datetime :reset_password_sent_at
+
+ ## Rememberable
+ t.datetime :remember_created_at
+
+ ## Trackable
+ # 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
+ # t.string :last_sign_in_ip
+
+ ## Confirmable
+ # t.string :confirmation_token
+ # t.datetime :confirmed_at
+ # t.datetime :confirmation_sent_at
+ # t.string :unconfirmed_email # Only if using reconfirmable
+
+ ## Lockable
+ # t.integer :failed_attempts, default: 0, null: false # Only if lock strategy is :failed_attempts
+ # t.string :unlock_token # Only if unlock strategy is :email or :both
+ # t.datetime :locked_at
+
+
+ t.timestamps null: false
+ end
+
+ add_index :admin_users, :email, unique: true
+ add_index :admin_users, :reset_password_token, unique: true
+ # add_index :admin_users, :confirmation_token, unique: true
+ # add_index :admin_users, :unlock_token, unique: true
+ end
+end
diff --git a/db/migrate/20240722171327_create_active_admin_comments.rb b/db/migrate/20240722171327_create_active_admin_comments.rb
new file mode 100644
index 0000000..54c3fa1
--- /dev/null
+++ b/db/migrate/20240722171327_create_active_admin_comments.rb
@@ -0,0 +1,16 @@
+class CreateActiveAdminComments < ActiveRecord::Migration[7.1]
+ def self.up
+ create_table :active_admin_comments do |t|
+ t.string :namespace
+ t.text :body
+ t.references :resource, polymorphic: true
+ t.references :author, polymorphic: true
+ t.timestamps
+ end
+ add_index :active_admin_comments, [:namespace]
+ end
+
+ def self.down
+ drop_table :active_admin_comments
+ end
+end
diff --git a/db/schema.rb b/db/schema.rb
index f1bf848..57cd8fa 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -10,7 +10,7 @@
#
# It's strongly recommended that you check this file into your version control system.
-ActiveRecord::Schema[7.1].define(version: 2024_07_13_015228) do
+ActiveRecord::Schema[7.1].define(version: 2024_07_22_171327) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
@@ -24,6 +24,20 @@
t.index ["record_type", "record_id", "name"], name: "index_action_text_rich_texts_uniqueness", unique: true
end
+ create_table "active_admin_comments", force: :cascade do |t|
+ t.string "namespace"
+ t.text "body"
+ t.string "resource_type"
+ t.bigint "resource_id"
+ t.string "author_type"
+ t.bigint "author_id"
+ t.datetime "created_at", null: false
+ t.datetime "updated_at", null: false
+ t.index ["author_type", "author_id"], name: "index_active_admin_comments_on_author"
+ t.index ["namespace"], name: "index_active_admin_comments_on_namespace"
+ t.index ["resource_type", "resource_id"], name: "index_active_admin_comments_on_resource"
+ end
+
create_table "active_storage_attachments", force: :cascade do |t|
t.string "name", null: false
t.string "record_type", null: false
@@ -52,6 +66,18 @@
t.index ["blob_id", "variation_digest"], name: "index_active_storage_variant_records_uniqueness", unique: true
end
+ create_table "admin_users", force: :cascade do |t|
+ 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.datetime "created_at", null: false
+ t.datetime "updated_at", null: false
+ t.index ["email"], name: "index_admin_users_on_email", unique: true
+ t.index ["reset_password_token"], name: "index_admin_users_on_reset_password_token", unique: true
+ end
+
create_table "categories", force: :cascade do |t|
t.string "name"
t.datetime "created_at", null: false
diff --git a/db/seeds.rb b/db/seeds.rb
index 0d7c21f..ea902ac 100644
--- a/db/seeds.rb
+++ b/db/seeds.rb
@@ -10,3 +10,7 @@
# ["Action", "Comedy", "Drama", "Horror"].each do |genre_name|
# MovieGenre.find_or_create_by!(name: genre_name)
# end
+if Rails.env.development?
+ AdminUser.create!(email: 'admin@example.com', password: 'password',
+ password_confirmation: 'password')
+end
diff --git a/spec/rails_helper.rb b/spec/rails_helper.rb
new file mode 100644
index 0000000..d2d2978
--- /dev/null
+++ b/spec/rails_helper.rb
@@ -0,0 +1,74 @@
+require 'simplecov'
+SimpleCov.start
+require 'capybara/rails'
+# This file is copied to spec/ when you run 'rails generate rspec:install'
+require 'spec_helper'
+ENV['RAILS_ENV'] ||= 'test'
+require_relative '../config/environment'
+# Prevent database truncation if the environment is production
+abort('The Rails environment is running in production mode!') if Rails.env.production?
+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.
+#
+# Rails.root.glob('spec/support/**/*.rb').sort.each { |f| require f }
+
+# Checks for pending migrations and applies them before tests are run.
+# If you are not using ActiveRecord, you can remove these lines.
+begin
+ ActiveRecord::Migration.maintain_test_schema!
+rescue ActiveRecord::PendingMigrationError => e
+ abort e.to_s.strip
+end
+RSpec.configure do |config|
+ # Remove this line if you're not using ActiveRecord or ActiveRecord fixtures
+ config.fixture_paths = [
+ Rails.root.join('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
+
+ # You can uncomment this line to turn off ActiveRecord support entirely.
+ # config.use_active_record = false
+
+ # 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://rspec.info/features/6-0/rspec-rails
+ config.infer_spec_type_from_file_location!
+
+ # Filter lines from Rails gems in backtraces.
+ config.filter_rails_from_backtrace!
+ # arbitrary gems may also be filtered via:
+ # config.filter_gems_from_backtrace("gem name")
+end
+Shoulda::Matchers.configure do |config|
+ config.integrate do |with|
+ with.test_framework :rspec
+ with.library :rails
+ end
+end
diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb
new file mode 100644
index 0000000..9c96a9b
--- /dev/null
+++ b/spec/spec_helper.rb
@@ -0,0 +1,92 @@
+# 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.
+#
+# See https://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
+
+ # This option will default to `:apply_to_host_groups` in RSpec 4 (and will
+ # have no way to turn it off -- the option exists only for backwards
+ # compatibility in RSpec 3). It causes shared context metadata to be
+ # inherited by the metadata hash of host groups and examples, rather than
+ # triggering implicit auto-inclusion in groups with matching metadata.
+ config.shared_context_metadata_behavior = :apply_to_host_groups
+
+ # The settings below are suggested to provide a good initial experience
+ # with RSpec, but feel free to customize to your heart's content.
+ # # This allows 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. RSpec also provides
+ # # aliases for `it`, `describe`, and `context` that include `:focus`
+ # # metadata: `fit`, `fdescribe` and `fcontext`, respectively.
+ # config.filter_run_when_matching :focus
+ #
+ # # Allows RSpec to persist some state between runs in order to support
+ # # the `--only-failures` and `--next-failure` CLI options. We recommend
+ # # you configure your source control system to ignore this file.
+ # config.example_status_persistence_file_path = "spec/examples.txt"
+ #
+ # # Limits the available syntax to the non-monkey patched syntax that is
+ # # recommended. For more details, see:
+ # # https://rspec.info/features/3-12/rspec-core/configuration/zero-monkey-patching-mode/
+ # 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
diff --git a/test/factories/categories.rb b/test/factories/categories.rb
new file mode 100644
index 0000000..7cd2246
--- /dev/null
+++ b/test/factories/categories.rb
@@ -0,0 +1,7 @@
+FactoryBot.define do
+ factory :category do
+ sequence :name do |n|
+ ['Para Compartir', 'Sin azucar', 'Sin Tacc', 'Picadas', 'Veganos/Vegetarianos'][n % 5]
+ end
+ end
+end
diff --git a/test/factories/category.rb b/test/factories/category.rb
deleted file mode 100644
index e4d2d1e..0000000
--- a/test/factories/category.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-FactoryBot.define do
- factory :category do
- name { 'dummy' }
- end
-end
diff --git a/test/factories/customizations.rb b/test/factories/customizations.rb
index ed8e7a0..9ed0a65 100644
--- a/test/factories/customizations.rb
+++ b/test/factories/customizations.rb
@@ -1,6 +1,6 @@
FactoryBot.define do
factory :customization do
- name { 'MyString' }
- price { 1.5 }
+ name { Faker::Food.unique.ingredient }
+ price { Faker::Number.between(from: 1, to: 100) }
end
end
diff --git a/test/factories/destinations.rb b/test/factories/destinations.rb
index f731c3a..ee82916 100644
--- a/test/factories/destinations.rb
+++ b/test/factories/destinations.rb
@@ -1,11 +1,13 @@
FactoryBot.define do
factory :destination do
- receiver { 'MyString' }
- day { '2024-07-10' }
- address { 'MyString' }
- number { 'MyString' }
- schedules { 'MyString' }
- cost { 'MyString' }
- purchase { nil }
+ receiver { Faker::Name.name }
+ day { Faker::Date.forward(days: 30) }
+ address { Faker::Address.street_address }
+ number { Faker::PhoneNumber.cell_phone }
+ schedules { "#{Faker::Number.between(from: 10, to: 18)}hs" }
+ cost { Faker::Number.between(from: 1, to: 100) }
+ after(:build) do |destination|
+ destination.purchase ||= build(:purchase, destinations: [destination])
+ end
end
end
diff --git a/test/factories/gift.rb b/test/factories/gifts.rb
similarity index 73%
rename from test/factories/gift.rb
rename to test/factories/gifts.rb
index ec6e7e1..c770913 100644
--- a/test/factories/gift.rb
+++ b/test/factories/gifts.rb
@@ -4,18 +4,6 @@
price { Faker::Number.between(from: 1, to: 1000) }
valoration { Faker::Number.between(from: 0.0, to: 5.0).round(1) }
- supplier do
- Supplier.all.sample
- end
-
- categories do
- Category.all.sample(3)
- end
-
- customizations do
- Customization.all.sample(4)
- end
-
content do
GIFT_CONTENT_LISTS.sample
end
@@ -29,9 +17,12 @@
filename: random_image,
content_type: 'image/png'
)
+ gift.supplier ||= create(:supplier)
+ gift.categories = create_list(:category, 3) if gift.categories.empty?
+ end
+
+ trait(:with_customizations) do
+ customizations { create_list(:customization, 3, gifts: [gift]) }
end
- # trait(:with_categories) do
- # Category.all.sample(3)
- # end
end
end
diff --git a/test/factories/payment_methods.rb b/test/factories/payment_methods.rb
index 3cf8ef0..0af91af 100644
--- a/test/factories/payment_methods.rb
+++ b/test/factories/payment_methods.rb
@@ -1,10 +1,12 @@
FactoryBot.define do
factory :payment_method do
- name { 'MyString' }
- owner { 'MyString' }
- card_number { 'MyString' }
- due_date { '2024-07-09' }
- CVV { 'MyString' }
- user { nil }
+ name { Faker::Bank.name }
+ owner { Faker::Name.name }
+ card_number { Faker::Bank.account_number }
+ due_date { Faker::Date.between(from: Date.today, to: 4.year.from_now) }
+ CVV { Faker::Number.number(digits: 3) }
+ after(:build) do |payment_method|
+ payment_method.user ||= build(:user, payment_methods: [payment_method])
+ end
end
end
diff --git a/test/factories/purchases.rb b/test/factories/purchases.rb
index 88da901..d3e16f4 100644
--- a/test/factories/purchases.rb
+++ b/test/factories/purchases.rb
@@ -1,13 +1,21 @@
FactoryBot.define do
factory :purchase do
- RUT { 'MyString' }
- social_reason { 'MyString' }
- price { 1 }
- payment_method { nil }
- gift { nil }
- suprise_delivery { false }
- personalization { 'MyString' }
- resend_delivery { false }
+ RUT { Faker::Number.unique.number(digits: 8).to_s }
+ social_reason { Faker::Company.name }
+ suprise_delivery { Faker::Boolean.boolean }
+ personalization { 'Hola, esta es el mensaje personalizado que te envío' }
+ resend_delivery { Faker::Boolean.boolean }
company_logo { nil }
+ amount { Faker::Number.between(from: 1, to: 5) }
+ after(:build) do |purchase|
+ if purchase.destinations.empty?
+ purchase.destinations = build_list(:destination, 1,
+ purchase: purchase)
+ end
+ purchase.gift ||= create(:gift)
+ purchase.payment_method ||= create(:payment_method)
+ purchase.subtotal = purchase.amount * purchase.gift_price
+ purchase.price = purchase.subtotal + (purchase.subtotal * 0.22).to_i + 180
+ end
end
end
diff --git a/test/factories/supplier.rb b/test/factories/suppliers.rb
similarity index 55%
rename from test/factories/supplier.rb
rename to test/factories/suppliers.rb
index dc3854c..47308d9 100644
--- a/test/factories/supplier.rb
+++ b/test/factories/suppliers.rb
@@ -1,5 +1,5 @@
FactoryBot.define do
factory :supplier do
- name { Faker::Commerce.unique.vendor }
+ name { Faker::Commerce.vendor }
end
end
diff --git a/test/factories/users.rb b/test/factories/users.rb
new file mode 100644
index 0000000..d67a477
--- /dev/null
+++ b/test/factories/users.rb
@@ -0,0 +1,9 @@
+FactoryBot.define do
+ factory :user do
+ email { Faker::Internet.email }
+ password { Faker::Internet.password(min_length: 8) }
+ name { Faker::Name.first_name }
+ last_name { Faker::Name.last_name }
+ company_name { Faker::Company.name }
+ end
+end
diff --git a/test/models/admin_user_test.rb b/test/models/admin_user_test.rb
new file mode 100644
index 0000000..6215c04
--- /dev/null
+++ b/test/models/admin_user_test.rb
@@ -0,0 +1,7 @@
+require 'test_helper'
+
+class AdminUserTest < ActiveSupport::TestCase
+ # test "the truth" do
+ # assert true
+ # end
+end