From 45657b0f20f918cd72797d0f49178141ed97762d Mon Sep 17 00:00:00 2001 From: bruno Date: Wed, 24 Jul 2024 16:22:06 -0300 Subject: [PATCH 1/6] finished admin panel --- Gemfile | 4 + Gemfile.lock | 38 ++ app/admin/admin_users.rb | 26 ++ app/admin/categories.rb | 34 ++ app/admin/customizations.rb | 34 ++ app/admin/dashboard.rb | 34 ++ app/admin/gifts.rb | 81 ++++ app/admin/purchases.rb | 100 +++++ app/admin/suppliers.rb | 54 +++ app/admin/users.rb | 76 ++++ app/assets/javascripts/active_admin.js | 1 + app/assets/stylesheets/active_admin.scss | 17 + app/controllers/purchases_controller.rb | 1 + app/models/admin_user.rb | 11 + app/models/category.rb | 2 +- app/models/customization.rb | 4 +- app/models/destination.rb | 1 + app/models/gift.rb | 11 +- app/models/payment_method.rb | 2 +- app/models/purchase.rb | 20 +- app/models/supplier.rb | 3 +- app/models/user.rb | 5 +- app/views/purchases/index.html.erb | 2 +- app/views/purchases/show.html.erb | 1 + config/initializers/active_admin.rb | 355 ++++++++++++++++++ config/initializers/ransack.rb | 102 +++++ config/locales/es.yml | 27 +- config/routes.rb | 2 + ...0240722171325_devise_create_admin_users.rb | 44 +++ ...0722171327_create_active_admin_comments.rb | 16 + db/schema.rb | 28 +- db/seeds.rb | 4 + test/models/admin_user_test.rb | 7 + 33 files changed, 1127 insertions(+), 20 deletions(-) create mode 100644 app/admin/admin_users.rb create mode 100644 app/admin/categories.rb create mode 100644 app/admin/customizations.rb create mode 100644 app/admin/dashboard.rb create mode 100644 app/admin/gifts.rb create mode 100644 app/admin/purchases.rb create mode 100644 app/admin/suppliers.rb create mode 100644 app/admin/users.rb create mode 100644 app/assets/javascripts/active_admin.js create mode 100644 app/assets/stylesheets/active_admin.scss create mode 100644 app/models/admin_user.rb create mode 100644 config/initializers/active_admin.rb create mode 100644 config/initializers/ransack.rb create mode 100644 db/migrate/20240722171325_devise_create_admin_users.rb create mode 100644 db/migrate/20240722171327_create_active_admin_comments.rb create mode 100644 test/models/admin_user_test.rb diff --git a/Gemfile b/Gemfile index a29151f..1e6122e 100644 --- a/Gemfile +++ b/Gemfile @@ -56,6 +56,10 @@ 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' diff --git a/Gemfile.lock b/Gemfile.lock index a26fe3a..9bd1657 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,7 @@ GEM crass (1.0.6) cssbundling-rails (1.4.0) railties (>= 6.0.0) + csv (3.3.0) date (3.3.4) debug (1.9.2) irb (~> 1.10) @@ -155,13 +169,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 +194,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 +315,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) @@ -318,7 +351,10 @@ 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) @@ -377,6 +413,7 @@ PLATFORMS x86_64-linux DEPENDENCIES + activeadmin bootsnap bullet capybara @@ -396,6 +433,7 @@ DEPENDENCIES rails_best_practices reek rubocop + sassc selenium-webdriver sprockets-rails sqlite3 (~> 1.4) 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..b116d30 --- /dev/null +++ b/app/admin/categories.rb @@ -0,0 +1,34 @@ +ActiveAdmin.register Category do + menu label: 'Categorías' + remove_filter :gift_categorizations + filter :name, label: 'Nombre' + filter :created_at, label: 'Fecha de creación' + filter :updated_at, label: 'Última actualización' + permit_params :name + + show do + attributes_table do + row 'Nombre', &:name + row 'Fecha de creación', &:created_at + row 'Última actualización', &:updated_at + end + active_admin_comments + end + + index do + selectable_column + id_column + column 'Nombre', :name + column 'Fecha de creación', :created_at + column 'Última actualización', :updated_at + + actions + end + + form do |f| + f.inputs 'Detalles' do + f.input :name, label: 'Nombre' + end + f.actions + end +end diff --git a/app/admin/customizations.rb b/app/admin/customizations.rb new file mode 100644 index 0000000..026ddca --- /dev/null +++ b/app/admin/customizations.rb @@ -0,0 +1,34 @@ +ActiveAdmin.register Customization do + permit_params :name, :price + menu label: 'Personalizaciones' + filter :name, label: 'Nombre' + filter :price, label: 'Precio' + + index do + selectable_column + id_column + column 'Nombre', :name + column 'Precio', :price + column 'Fecha de creación', :created_at + column 'Última actualización', :updated_at + actions + end + + show do + attributes_table do + row 'Nombre', &:name + row 'Precio', &:price + row 'Fecha de creación', &:created_at + row 'Última actualización', &:updated_at + end + active_admin_comments + end + + form do |f| + f.inputs 'Detalles' do + f.input :name, label: 'Nombre' + f.input :price, label: 'Precio' + 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..62ab60f --- /dev/null +++ b/app/admin/gifts.rb @@ -0,0 +1,81 @@ +ActiveAdmin.register Gift do + permit_params :name, :price, :valoration, :supplier_id, :image, :content, category_ids: [], + customization_ids: [] + + menu label: 'Regalos' + remove_filter :gift_customizations, :gift_categorizations, :purchases, + :image_attachment, :image_blob, :rich_text_content + + filter :name, label: 'Nombre' + filter :price, label: 'Precio' + filter :valoration, label: 'Valoración' + filter :supplier, label: 'Proveedor' + filter :categories, label: 'Categorías', multiple: true + filter :customizations, label: 'Personalizaciones', multiple: true + filter :created_at, label: 'Fecha de creación' + filter :updated_at, label: 'Última actualización' + + controller do + def scoped_collection + super.includes(:supplier) + end + end + + index do + selectable_column + id_column + column 'Nombre', :name + column 'Precio', :price + column 'Valoración', :valoration + column 'Proveedor', :supplier + column 'Fecha de creación', :created_at + column 'Última actualización', :updated_at + actions + end + + show do + attributes_table do + row 'Nombre', &:name + row 'Precio', &:price + row 'Valoración', &:valoration + row 'Proveedor', &: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 'Fecha de creación', &:created_at + row 'Última actualización', &:updated_at + end + active_admin_comments + end + + form do |f| + f.inputs 'Detalles' do + f.input :name, label: 'Nombre' + f.input :price, label: 'Precio' + f.input :valoration, label: 'Valoración' + f.input :supplier, label: 'Proveedor' + f.input :image, label: 'Imagen', as: :file + f.input :content, label: 'Contenido' + f.input :categories, label: 'Categorías' + f.input :customizations, label: 'Personalizaciones' + end + f.actions + end +end diff --git a/app/admin/purchases.rb b/app/admin/purchases.rb new file mode 100644 index 0000000..170fd75 --- /dev/null +++ b/app/admin/purchases.rb @@ -0,0 +1,100 @@ +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] + + menu label: 'Compras' + + controller do + def scoped_collection + super.includes(:user, :gift, :customizations) + end + end + + remove_filter :payment_method, :destinations, :subtotal, :personalization + filter :gift, label: 'Regalo' + filter :user, label: 'Usuario', as: :select, collection: User.all.map { |user| + [user.email, user.id] + } + filter :price, label: 'Precio' + filter :amount, label: 'Cantidad' + filter :suprise_delivery, label: 'Entrega Sorpresa' + filter :resend_delivery, label: 'Reenvío Disponible' + filter :created_at, label: 'Fecha de creación' + filter :updated_at, label: 'Última actualización' + + index do + selectable_column + id_column + column 'Precio', :price + column 'Cantidad', :amount + column 'Entrega Sorpresa', :suprise_delivery + column 'Reenvío Disponible', :resend_delivery + column 'Regalo', :gift + column 'Usuario' do |purchase| + link_to purchase.user_email, admin_user_path(purchase.user) + end + column 'Fecha de compra', :created_at + actions + end + + show do + attributes_table do + row 'RUT', &:RUT + row 'Razón Social', &:social_reason + row 'Precio', &:price + row 'Cantidad', &:amount + row 'Mensaje Personalizado', &:personalization + row 'Entrega Sorpresa', &:suprise_delivery + row 'Reenvío Disponible', &:resend_delivery + row 'Logo' do |purchase| + image_tag purchase.company_logo if purchase.company_logo.present? + end + row 'Regalo', &:gift + row 'Usuario' do |purchase| + link_to purchase.user_email, admin_user_path(purchase.user) + end + row 'Fecha de compra', &:created_at + row 'Última actualización', &:updated_at + end + active_admin_comments + end + + form do |f| + f.inputs 'Detalles de la Compra' do + f.input :RUT, label: 'RUT' + f.input :social_reason, label: 'Razón Social' + f.input :amount, label: 'Cantidad' + f.input :personalization, label: 'Mensaje Personalizado' + f.input :suprise_delivery, label: 'Entrega Sorpresa' + f.input :resend_delivery, label: 'Reenvío Disponible' + f.input :gift, label: 'Regalo' if f.object.new_record? + + unless f.object.new_record? + f.input :customizations, label: 'Agregados', as: :select, + collection: Customization.joins(:gift_customizations) + .where(gift_customizations: { gift_id: + f.object.gift_id }) + end + f.input :company_logo, label: 'Logo', as: :file + f.input :payment_method, label: 'Método de Pago', 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, label: 'Receptor' + destination.input :day, label: 'Día', as: :date_picker + destination.input :address, label: 'Dirección' + destination.input :number, label: 'Número' + destination.input :cost, label: 'Costo' + destination.input :schedules, label: 'Horarios' + 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..e5c1d30 --- /dev/null +++ b/app/admin/suppliers.rb @@ -0,0 +1,54 @@ +ActiveAdmin.register Supplier do + menu label: 'Proveedores' + remove_filter :gifts + filter :name, label: 'Nombre' + filter :created_at, label: 'Fecha de creación' + filter :updated_at, label: 'Última actualización' + permit_params :name + + controller do + def scoped_collection + super.includes(:gifts) + end + end + + index do + selectable_column + id_column + column 'Nombre', :name + column 'Regalos' do |supplier| + dropdown_menu '' do + supplier.gifts.each do |gift| + item gift.name, admin_gift_path(gift) + end + end + end + column 'Fecha de creación', :created_at + column 'Última actualización', :updated_at + + actions + end + + form do |f| + f.inputs 'Detalles' do + f.input :name, label: 'Nombre' + end + f.actions + end + + show do + attributes_table do + row 'Nombre', &:name + row 'Regalos' do |supplier| + dropdown_menu '' do + supplier.gifts.each do |gift| + item gift.name, admin_gift_path(gift) + end + end + end + row 'Fecha de creación', &:created_at + row 'Última actualización', &: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..ad77734 --- /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] + menu label: 'Usuarios' + filter :name, label: 'Nombre' + filter :last_name, label: 'Apellido' + filter :email, label: 'Email' + filter :company_name, label: 'Empresa' + filter :created_at, label: 'Fecha de creación' + filter :updated_at, label: 'Última actualización' + + controller do + def scoped_collection + super.includes(:payment_methods) + end + end + + index do + selectable_column + id_column + column 'Nombre', :name + column 'Apellido', :last_name + column 'Email', :email + column 'Empresa', :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 'Fecha de creación', :created_at + column 'Última actualización', :updated_at + actions + end + + show do + attributes_table do + row 'Nombre', &:name + row 'Apellido', &:last_name + row 'Email', &:email + row 'Empresa', &: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 'Fecha de creación', &:created_at + row 'Última actualización', &:updated_at + end + active_admin_comments + end + + form do |f| + f.inputs 'Detalles del Usuario' do + f.input :name, label: 'Nombre' + f.input :last_name, label: 'Apellido' + f.inputs 'Métodos de Pago' do + f.has_many :payment_methods, + allow_destroy: true, heading: false do |payment_method| + payment_method.input :name, label: 'Nombre' + payment_method.input :owner, label: 'Titular' + payment_method.input :card_number, label: 'Número de Tarjeta' + payment_method.input :due_date, label: 'Fecha de Vencimiento', as: :date_picker + payment_method.input :CVV, label: 'CVV' + end + end + f.input :email, label: 'Email' + f.input :company_name, label: 'Empresa' + f.input :password, label: 'Contraseña' 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..4822bdd 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, :customizations, + :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..14a66d4 100644 --- a/config/locales/es.yml +++ b/config/locales/es.yml @@ -16,15 +16,30 @@ 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: + 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/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 From 9504abafad413b09b8e0cf702b74ecebd34e21b8 Mon Sep 17 00:00:00 2001 From: bruno Date: Tue, 30 Jul 2024 12:46:52 -0300 Subject: [PATCH 2/6] translations --- app/admin/categories.rb | 21 +++++---- app/admin/customizations.rb | 25 ++++++----- app/admin/gifts.rb | 57 ++++++++++++------------ app/admin/purchases.rb | 86 ++++++++++++++++++------------------- app/admin/suppliers.rb | 21 +++++---- app/admin/users.rb | 58 ++++++++++++------------- config/locales/es.yml | 68 +++++++++++++++++++++++++++++ 7 files changed, 199 insertions(+), 137 deletions(-) diff --git a/app/admin/categories.rb b/app/admin/categories.rb index b116d30..fd287aa 100644 --- a/app/admin/categories.rb +++ b/app/admin/categories.rb @@ -1,16 +1,15 @@ ActiveAdmin.register Category do - menu label: 'Categorías' remove_filter :gift_categorizations - filter :name, label: 'Nombre' - filter :created_at, label: 'Fecha de creación' - filter :updated_at, label: 'Última actualización' + filter :name + filter :created_at + filter :updated_at permit_params :name show do attributes_table do - row 'Nombre', &:name - row 'Fecha de creación', &:created_at - row 'Última actualización', &:updated_at + row :name + row :created_at + row :updated_at end active_admin_comments end @@ -18,16 +17,16 @@ index do selectable_column id_column - column 'Nombre', :name - column 'Fecha de creación', :created_at - column 'Última actualización', :updated_at + column :name + column :created_at + column :updated_at actions end form do |f| f.inputs 'Detalles' do - f.input :name, label: 'Nombre' + f.input :name end f.actions end diff --git a/app/admin/customizations.rb b/app/admin/customizations.rb index 026ddca..b520768 100644 --- a/app/admin/customizations.rb +++ b/app/admin/customizations.rb @@ -1,33 +1,32 @@ ActiveAdmin.register Customization do permit_params :name, :price - menu label: 'Personalizaciones' - filter :name, label: 'Nombre' - filter :price, label: 'Precio' + filter :name + filter :price index do selectable_column id_column - column 'Nombre', :name - column 'Precio', :price - column 'Fecha de creación', :created_at - column 'Última actualización', :updated_at + column :name + column :price + column :created_at + column :updated_at actions end show do attributes_table do - row 'Nombre', &:name - row 'Precio', &:price - row 'Fecha de creación', &:created_at - row 'Última actualización', &:updated_at + 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, label: 'Nombre' - f.input :price, label: 'Precio' + f.input :name + f.input :price end f.actions end diff --git a/app/admin/gifts.rb b/app/admin/gifts.rb index 62ab60f..b16c27b 100644 --- a/app/admin/gifts.rb +++ b/app/admin/gifts.rb @@ -2,18 +2,17 @@ permit_params :name, :price, :valoration, :supplier_id, :image, :content, category_ids: [], customization_ids: [] - menu label: 'Regalos' remove_filter :gift_customizations, :gift_categorizations, :purchases, :image_attachment, :image_blob, :rich_text_content - filter :name, label: 'Nombre' - filter :price, label: 'Precio' - filter :valoration, label: 'Valoración' - filter :supplier, label: 'Proveedor' - filter :categories, label: 'Categorías', multiple: true - filter :customizations, label: 'Personalizaciones', multiple: true - filter :created_at, label: 'Fecha de creación' - filter :updated_at, label: 'Última actualización' + 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 @@ -24,21 +23,21 @@ def scoped_collection index do selectable_column id_column - column 'Nombre', :name - column 'Precio', :price - column 'Valoración', :valoration - column 'Proveedor', :supplier - column 'Fecha de creación', :created_at - column 'Última actualización', :updated_at + column :name + column :price + column :valoration + column :supplier + column :created_at + column :updated_at actions end show do attributes_table do - row 'Nombre', &:name - row 'Precio', &:price - row 'Valoración', &:valoration - row 'Proveedor', &:supplier + row :name + row :price + row :valoration + row :supplier row 'Imagen' do |gift| image_tag gift.image_resized_for_purchase end @@ -59,22 +58,22 @@ def scoped_collection end end end - row 'Fecha de creación', &:created_at - row 'Última actualización', &:updated_at + row :created_at + row :updated_at end active_admin_comments end form do |f| f.inputs 'Detalles' do - f.input :name, label: 'Nombre' - f.input :price, label: 'Precio' - f.input :valoration, label: 'Valoración' - f.input :supplier, label: 'Proveedor' - f.input :image, label: 'Imagen', as: :file - f.input :content, label: 'Contenido' - f.input :categories, label: 'Categorías' - f.input :customizations, label: 'Personalizaciones' + 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 diff --git a/app/admin/purchases.rb b/app/admin/purchases.rb index 170fd75..b935d83 100644 --- a/app/admin/purchases.rb +++ b/app/admin/purchases.rb @@ -6,8 +6,6 @@ customization_ids: [], destinations_attributes: %i[id receiver day address number cost schedules _destroy] - menu label: 'Compras' - controller do def scoped_collection super.includes(:user, :gift, :customizations) @@ -15,83 +13,83 @@ def scoped_collection end remove_filter :payment_method, :destinations, :subtotal, :personalization - filter :gift, label: 'Regalo' - filter :user, label: 'Usuario', as: :select, collection: User.all.map { |user| - [user.email, user.id] - } - filter :price, label: 'Precio' - filter :amount, label: 'Cantidad' - filter :suprise_delivery, label: 'Entrega Sorpresa' - filter :resend_delivery, label: 'Reenvío Disponible' - filter :created_at, label: 'Fecha de creación' - filter :updated_at, label: 'Última actualización' + 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 'Precio', :price - column 'Cantidad', :amount - column 'Entrega Sorpresa', :suprise_delivery - column 'Reenvío Disponible', :resend_delivery - column 'Regalo', :gift + 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 'Fecha de compra', :created_at + column :created_at actions end show do attributes_table do - row 'RUT', &:RUT - row 'Razón Social', &:social_reason - row 'Precio', &:price - row 'Cantidad', &:amount - row 'Mensaje Personalizado', &:personalization - row 'Entrega Sorpresa', &:suprise_delivery - row 'Reenvío Disponible', &:resend_delivery + 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 'Regalo', &:gift + row :gift row 'Usuario' do |purchase| link_to purchase.user_email, admin_user_path(purchase.user) end - row 'Fecha de compra', &:created_at - row 'Última actualización', &:updated_at + row :created_at + row :updated_at end active_admin_comments end form do |f| f.inputs 'Detalles de la Compra' do - f.input :RUT, label: 'RUT' - f.input :social_reason, label: 'Razón Social' - f.input :amount, label: 'Cantidad' - f.input :personalization, label: 'Mensaje Personalizado' - f.input :suprise_delivery, label: 'Entrega Sorpresa' - f.input :resend_delivery, label: 'Reenvío Disponible' - f.input :gift, label: 'Regalo' if f.object.new_record? + 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, label: 'Agregados', as: :select, + f.input :customizations, as: :select, collection: Customization.joins(:gift_customizations) .where(gift_customizations: { gift_id: f.object.gift_id }) end - f.input :company_logo, label: 'Logo', as: :file - f.input :payment_method, label: 'Método de Pago', as: :select, + 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, label: 'Receptor' - destination.input :day, label: 'Día', as: :date_picker - destination.input :address, label: 'Dirección' - destination.input :number, label: 'Número' - destination.input :cost, label: 'Costo' - destination.input :schedules, label: 'Horarios' + destination.input :receiver + destination.input :day, as: :date_picker + destination.input :address + destination.input :number + destination.input :cost + destination.input :schedules end end end diff --git a/app/admin/suppliers.rb b/app/admin/suppliers.rb index e5c1d30..92129b7 100644 --- a/app/admin/suppliers.rb +++ b/app/admin/suppliers.rb @@ -1,9 +1,8 @@ ActiveAdmin.register Supplier do - menu label: 'Proveedores' remove_filter :gifts - filter :name, label: 'Nombre' - filter :created_at, label: 'Fecha de creación' - filter :updated_at, label: 'Última actualización' + filter :name + filter :created_at + filter :updated_at permit_params :name controller do @@ -15,7 +14,7 @@ def scoped_collection index do selectable_column id_column - column 'Nombre', :name + column :name column 'Regalos' do |supplier| dropdown_menu '' do supplier.gifts.each do |gift| @@ -23,22 +22,22 @@ def scoped_collection end end end - column 'Fecha de creación', :created_at - column 'Última actualización', :updated_at + column :created_at + column :updated_at actions end form do |f| f.inputs 'Detalles' do - f.input :name, label: 'Nombre' + f.input :name end f.actions end show do attributes_table do - row 'Nombre', &:name + row :name row 'Regalos' do |supplier| dropdown_menu '' do supplier.gifts.each do |gift| @@ -46,8 +45,8 @@ def scoped_collection end end end - row 'Fecha de creación', &:created_at - row 'Última actualización', &:updated_at + row :created_at + row :updated_at end active_admin_comments end diff --git a/app/admin/users.rb b/app/admin/users.rb index ad77734..995eee1 100644 --- a/app/admin/users.rb +++ b/app/admin/users.rb @@ -1,13 +1,13 @@ 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] - menu label: 'Usuarios' - filter :name, label: 'Nombre' - filter :last_name, label: 'Apellido' - filter :email, label: 'Email' - filter :company_name, label: 'Empresa' - filter :created_at, label: 'Fecha de creación' - filter :updated_at, label: 'Última actualización' + + filter :name + filter :last_name + filter :email + filter :company_name + filter :created_at + filter :updated_at controller do def scoped_collection @@ -18,10 +18,10 @@ def scoped_collection index do selectable_column id_column - column 'Nombre', :name - column 'Apellido', :last_name - column 'Email', :email - column 'Empresa', :company_name + 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| @@ -29,17 +29,17 @@ def scoped_collection end end end - column 'Fecha de creación', :created_at - column 'Última actualización', :updated_at + column :created_at + column :updated_at actions end show do attributes_table do - row 'Nombre', &:name - row 'Apellido', &:last_name - row 'Email', &:email - row 'Empresa', &:company_name + 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| @@ -47,29 +47,29 @@ def scoped_collection end end end - row 'Fecha de creación', &:created_at - row 'Última actualización', &:updated_at + row :created_at + row :updated_at end active_admin_comments end form do |f| f.inputs 'Detalles del Usuario' do - f.input :name, label: 'Nombre' - f.input :last_name, label: 'Apellido' + 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, label: 'Nombre' - payment_method.input :owner, label: 'Titular' - payment_method.input :card_number, label: 'Número de Tarjeta' - payment_method.input :due_date, label: 'Fecha de Vencimiento', as: :date_picker - payment_method.input :CVV, label: 'CVV' + 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, label: 'Email' - f.input :company_name, label: 'Empresa' - f.input :password, label: 'Contraseña' if f.object.new_record? + f.input :email + f.input :company_name + f.input :password if f.object.new_record? end f.actions end diff --git a/config/locales/es.yml b/config/locales/es.yml index 14a66d4..287a1d1 100644 --- a/config/locales/es.yml +++ b/config/locales/es.yml @@ -31,6 +31,74 @@ es: 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 From b1359d761f5229089fc282d54d61add51523e9c0 Mon Sep 17 00:00:00 2001 From: bruno Date: Thu, 25 Jul 2024 14:11:01 -0300 Subject: [PATCH 3/6] advanced factories --- .rspec | 1 + Gemfile | 4 ++ Gemfile.lock | 35 ++++++++++++ spec/rails_helper.rb | 74 ++++++++++++++++++++++++ spec/spec_helper.rb | 94 +++++++++++++++++++++++++++++++ test/factories/category.rb | 4 +- test/factories/customizations.rb | 4 +- test/factories/destinations.rb | 12 ++-- test/factories/payment_methods.rb | 10 ++-- test/factories/purchases.rb | 19 ++++--- 10 files changed, 235 insertions(+), 22 deletions(-) create mode 100644 .rspec create mode 100644 spec/rails_helper.rb create mode 100644 spec/spec_helper.rb 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 1e6122e..30b89f1 100644 --- a/Gemfile +++ b/Gemfile @@ -65,6 +65,7 @@ group :development, :test do gem 'bullet' gem 'debug', platforms: %i[mri mswin mswin64 mingw x64_mingw] gem 'factory_bot_rails' + gem 'rspec-rails' end group :development do @@ -87,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 9bd1657..b99b6e7 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -119,6 +119,10 @@ GEM 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) @@ -129,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) @@ -335,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) @@ -361,6 +384,14 @@ GEM 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) @@ -418,6 +449,7 @@ DEPENDENCIES bullet capybara cssbundling-rails + database_cleaner-active_record debug devise (~> 4.9) factory_bot_rails @@ -432,9 +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/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..327b58e --- /dev/null +++ b/spec/spec_helper.rb @@ -0,0 +1,94 @@ +# 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. +=begin + # 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 +end diff --git a/test/factories/category.rb b/test/factories/category.rb index e4d2d1e..7cd2246 100644 --- a/test/factories/category.rb +++ b/test/factories/category.rb @@ -1,5 +1,7 @@ FactoryBot.define do factory :category do - name { 'dummy' } + sequence :name do |n| + ['Para Compartir', 'Sin azucar', 'Sin Tacc', 'Picadas', 'Veganos/Vegetarianos'][n % 5] + end 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..ae6f1d3 100644 --- a/test/factories/destinations.rb +++ b/test/factories/destinations.rb @@ -1,11 +1,11 @@ FactoryBot.define do factory :destination do - receiver { 'MyString' } - day { '2024-07-10' } - address { 'MyString' } - number { 'MyString' } - schedules { 'MyString' } - cost { 'MyString' } + 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) } purchase { nil } end end diff --git a/test/factories/payment_methods.rb b/test/factories/payment_methods.rb index 3cf8ef0..ace37c0 100644 --- a/test/factories/payment_methods.rb +++ b/test/factories/payment_methods.rb @@ -1,10 +1,10 @@ FactoryBot.define do factory :payment_method do - name { 'MyString' } - owner { 'MyString' } - card_number { 'MyString' } - due_date { '2024-07-09' } - CVV { 'MyString' } + 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) } user { nil } end end diff --git a/test/factories/purchases.rb b/test/factories/purchases.rb index 88da901..a3b3fc0 100644 --- a/test/factories/purchases.rb +++ b/test/factories/purchases.rb @@ -1,13 +1,16 @@ 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) } + social_reason { Faker::Company.name } + payment_method { PaymentMethod.all.sample } + gift { Gift.all.sample } + 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) } + subtotal { amount * gift.price } + price { subtotal + (subtotal * 0.22).to_i + 180 } + destinations { FactoryBot.create_list(:destination, 1) } end end From 00f3945b89a91716efd775b5c4d253726c047bcf Mon Sep 17 00:00:00 2001 From: bruno Date: Thu, 25 Jul 2024 16:58:32 -0300 Subject: [PATCH 4/6] finished factories --- app/models/gift.rb | 2 +- spec/spec_helper.rb | 92 +++++++++---------- test/factories/{category.rb => categories.rb} | 0 test/factories/destinations.rb | 4 +- test/factories/{gift.rb => gifts.rb} | 18 ++-- test/factories/payment_methods.rb | 4 +- test/factories/purchases.rb | 17 ++-- test/factories/{supplier.rb => suppliers.rb} | 2 +- test/factories/users.rb | 9 ++ 9 files changed, 79 insertions(+), 69 deletions(-) rename test/factories/{category.rb => categories.rb} (100%) rename test/factories/{gift.rb => gifts.rb} (78%) rename test/factories/{supplier.rb => suppliers.rb} (55%) create mode 100644 test/factories/users.rb diff --git a/app/models/gift.rb b/app/models/gift.rb index 4822bdd..58431c0 100644 --- a/app/models/gift.rb +++ b/app/models/gift.rb @@ -9,7 +9,7 @@ class Gift < ApplicationRecord has_one_attached :image has_rich_text :content - validates :name, :price, :valoration, :supplier, :image, :categories, :customizations, + 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 } diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 327b58e..9c96a9b 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -44,51 +44,49 @@ # 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. -=begin - # 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 + # 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/category.rb b/test/factories/categories.rb similarity index 100% rename from test/factories/category.rb rename to test/factories/categories.rb diff --git a/test/factories/destinations.rb b/test/factories/destinations.rb index ae6f1d3..ee82916 100644 --- a/test/factories/destinations.rb +++ b/test/factories/destinations.rb @@ -6,6 +6,8 @@ number { Faker::PhoneNumber.cell_phone } schedules { "#{Faker::Number.between(from: 10, to: 18)}hs" } cost { Faker::Number.between(from: 1, to: 100) } - purchase { nil } + 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 78% rename from test/factories/gift.rb rename to test/factories/gifts.rb index ec6e7e1..0d04608 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,6 +17,12 @@ filename: random_image, content_type: 'image/png' ) + gift.supplier ||= create(:supplier) + gift.categories = create_list(:category, 3) + end + + trait(:with_customizations) do + customizations { create_list(:customization, 3, gifts: [gift]) } end # trait(:with_categories) do # Category.all.sample(3) diff --git a/test/factories/payment_methods.rb b/test/factories/payment_methods.rb index ace37c0..0af91af 100644 --- a/test/factories/payment_methods.rb +++ b/test/factories/payment_methods.rb @@ -5,6 +5,8 @@ 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) } - user { nil } + 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 a3b3fc0..4d86be3 100644 --- a/test/factories/purchases.rb +++ b/test/factories/purchases.rb @@ -1,16 +1,21 @@ FactoryBot.define do factory :purchase do - RUT { Faker::Number.unique.number(digits: 8) } + RUT { Faker::Number.unique.number(digits: 8).to_s } social_reason { Faker::Company.name } - payment_method { PaymentMethod.all.sample } - gift { Gift.all.sample } 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) } - subtotal { amount * gift.price } - price { subtotal + (subtotal * 0.22).to_i + 180 } - destinations { FactoryBot.create_list(:destination, 1) } + after(:build) do |purchase| + if purchase.destinations.empty? + purchase.destinations = build_list(:destination, 1, + purchase: purchase) + end + purchase.gift = create(:gift) if purchase.gift.nil? + purchase.payment_method = create(:payment_method) if purchase.payment_method.nil? + 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 From 4a3756d5d3dbccfc7594760ee1dda6d145d9daaf Mon Sep 17 00:00:00 2001 From: bruno Date: Mon, 29 Jul 2024 10:58:44 -0300 Subject: [PATCH 5/6] correction in gift factory --- test/factories/gifts.rb | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/test/factories/gifts.rb b/test/factories/gifts.rb index 0d04608..9110cb2 100644 --- a/test/factories/gifts.rb +++ b/test/factories/gifts.rb @@ -18,14 +18,11 @@ content_type: 'image/png' ) gift.supplier ||= create(:supplier) - gift.categories = create_list(:category, 3) + gift.categories ||= create_list(:category, 3) end trait(:with_customizations) do customizations { create_list(:customization, 3, gifts: [gift]) } end - # trait(:with_categories) do - # Category.all.sample(3) - # end end end From 70fc0e44822cb067016615969f08727b20bd9960 Mon Sep 17 00:00:00 2001 From: bruno Date: Mon, 29 Jul 2024 11:53:29 -0300 Subject: [PATCH 6/6] corrections --- test/factories/gifts.rb | 2 +- test/factories/purchases.rb | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/test/factories/gifts.rb b/test/factories/gifts.rb index 9110cb2..c770913 100644 --- a/test/factories/gifts.rb +++ b/test/factories/gifts.rb @@ -18,7 +18,7 @@ content_type: 'image/png' ) gift.supplier ||= create(:supplier) - gift.categories ||= create_list(:category, 3) + gift.categories = create_list(:category, 3) if gift.categories.empty? end trait(:with_customizations) do diff --git a/test/factories/purchases.rb b/test/factories/purchases.rb index 4d86be3..d3e16f4 100644 --- a/test/factories/purchases.rb +++ b/test/factories/purchases.rb @@ -12,8 +12,8 @@ purchase.destinations = build_list(:destination, 1, purchase: purchase) end - purchase.gift = create(:gift) if purchase.gift.nil? - purchase.payment_method = create(:payment_method) if purchase.payment_method.nil? + 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