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