From 66062a8ce724ef1f7f6121adc738f17e89eac39b Mon Sep 17 00:00:00 2001 From: Regene27 Date: Mon, 29 Jan 2024 11:59:19 +0700 Subject: [PATCH] Close #1037 Add Quantity to Customer and Add Query or Create Variant in Subscription --- .../spree/billing/subscriptions_controller.rb | 64 +++++++++++ .../spree_cm_commissioner/subscription.rb | 3 + .../variant_decorator.rb | 2 + .../spree/billing/customers/_form.html.erb | 5 + .../spree/billing/shared/_invoice.html.erb | 16 ++- .../billing/subscriptions/_form.html.erb | 104 +++++++++++++++--- .../subscriptions/_option_types_form.html.erb | 31 ++++++ config/locales/en.yml | 1 + config/routes.rb | 10 +- ...0119110257_add_quantity_to_cm_customers.rb | 5 + 10 files changed, 223 insertions(+), 18 deletions(-) create mode 100644 app/views/spree/billing/subscriptions/_option_types_form.html.erb create mode 100644 db/migrate/20240119110257_add_quantity_to_cm_customers.rb diff --git a/app/controllers/spree/billing/subscriptions_controller.rb b/app/controllers/spree/billing/subscriptions_controller.rb index 488d304b0..1fc7a75ce 100644 --- a/app/controllers/spree/billing/subscriptions_controller.rb +++ b/app/controllers/spree/billing/subscriptions_controller.rb @@ -4,6 +4,54 @@ class SubscriptionsController < Spree::Billing::BaseController before_action :load_customer before_action :load_subscription, if: -> { member_action? } + def load_option_types_form + @product = Spree::Product.find(params[:product_id]) + + @variant = @product.variants.new + + session[:product_id] = @product.id + + render partial: 'spree/billing/subscriptions/option_types_form' + end + + def create_sku + @product = Spree::Product.find(session[:product_id]) + + return if params[:variant].blank? + + option_values = params[:variant][:option_value_ids].map { |id| Spree::OptionValue.find(id) } + sku_parts = [@product.name] + + option_values.each do |option_value| + sku_parts << "#{option_value.option_type.name}-#{option_value.name}" + end + + sku_parts << "price-#{params[:variant][:price]}" + + params[:variant][:sku] = sku_parts.join('-').gsub(' ', '-').downcase + end + + def create + @product = Spree::Product.find(session[:product_id]) + @variant = @product.variants.new + create_sku + @variant = @product.variants.where(variant_params).first_or_initialize if variant_params.present? + + if @variant.persisted? + @subscription = @variant.subscriptions.new(subscription_params.merge(variant_id: @variant.id)) + else + save_variant + @subscription = @variant.subscriptions.new(subscription_params) + @subscription.variant_id = @variant.id + end + + @subscription.save + return unless @subscription + + flash[:success] = flash_message_for(@subscription, :successfully_created) + redirect_to billing_customer_subscriptions_url(@customer) + end + protected def collection @@ -13,6 +61,14 @@ def collection @collection = @search.result.page(page).per(per_page) end + def save_variant + @variant = @product.variants.new(variant_params) + @variant.option_value_ids = params[:variant][:option_value_ids] + @variant.price = params[:variant][:price] + @variant.stock_items.new(stock_location_id: @current_vendor.id, count_on_hand: 1) + @variant.save + end + def load_customer customer end @@ -39,6 +95,14 @@ def object_name def collection_url(options = {}) billing_customer_subscriptions_url(options) end + + def variant_params + params.require(:variant).permit(:sku) + end + + def subscription_params + params.require(:spree_cm_commissioner_subscription).permit(:start_date, :customer_id, :status) + end end end end diff --git a/app/models/spree_cm_commissioner/subscription.rb b/app/models/spree_cm_commissioner/subscription.rb index 159bda4cc..dc148ca1c 100644 --- a/app/models/spree_cm_commissioner/subscription.rb +++ b/app/models/spree_cm_commissioner/subscription.rb @@ -6,6 +6,7 @@ class Subscription < SpreeCmCommissioner::Base belongs_to :variant, class_name: 'Spree::Variant' belongs_to :customer, class_name: 'SpreeCmCommissioner::Customer' + belongs_to :product, class_name: 'Spree::Product' has_many :orders, -> { order(:created_at) }, class_name: 'Spree::Order', dependent: :nullify has_many :line_items, through: :orders, class_name: 'Spree::LineItem' @@ -23,6 +24,8 @@ class Subscription < SpreeCmCommissioner::Base after_create :create_order after_commit :update_customer_active_subscriptions_count + accepts_nested_attributes_for :variant + def create_order SpreeCmCommissioner::SubscribedOrderCreator.call(subscription: self) end diff --git a/app/models/spree_cm_commissioner/variant_decorator.rb b/app/models/spree_cm_commissioner/variant_decorator.rb index 754f5afae..8eb1d3396 100644 --- a/app/models/spree_cm_commissioner/variant_decorator.rb +++ b/app/models/spree_cm_commissioner/variant_decorator.rb @@ -8,6 +8,8 @@ def self.prepended(base) base.validate :validate_option_types base.scope :subscribable, -> { active.joins(:product).where(product: { subscribable: true, status: :active }) } + + base.has_many :subscriptions, class_name: 'SpreeCmCommissioner::Subscription', dependent: :destroy end def selected_option_value_ids diff --git a/app/views/spree/billing/customers/_form.html.erb b/app/views/spree/billing/customers/_form.html.erb index 8f8f5cc9e..e0a695365 100644 --- a/app/views/spree/billing/customers/_form.html.erb +++ b/app/views/spree/billing/customers/_form.html.erb @@ -31,5 +31,10 @@ <%= f.collection_select(:taxon_id, Spree::Taxon.where(depth: 1), :id, :name, { include_blank: Spree.t('match_choices.none') }, { class: 'select2', required: true })%> <%= f.error_message_on :taxon_id %> <% end %> + <%= f.field_container :quantity do %> + <%= f.label :quantity, I18n.t('activerecord.attributes.spree/order.quantity') %> + <%= f.number_field :quantity, class: 'form-control', required: true %> + <%= f.error_message_on :quantity %> + <% end %> diff --git a/app/views/spree/billing/shared/_invoice.html.erb b/app/views/spree/billing/shared/_invoice.html.erb index b5ad7c154..e508ad06a 100644 --- a/app/views/spree/billing/shared/_invoice.html.erb +++ b/app/views/spree/billing/shared/_invoice.html.erb @@ -8,8 +8,10 @@ @email = @vendor.notification_email @note = @vendor.note + @quantity = @customer.quantity @product = @invoice.order.line_items.first.variant.sku @price = @invoice.order.line_items.first.display_price + @total_price = @price.to_s.gsub(/[^\d.]/, '').to_d * @quantity @total = @invoice.order.display_total @from_date = @invoice.order.line_items.first.to_date.strftime("%B %Y") @date = @invoice.date.strftime('%Y-%m-%d') @@ -92,8 +94,10 @@ ល.រ​​​ / N បរិយាយ / Description + ចំនួន / Quantity ប្រចាំខែ / Month ទឹកប្រាក់​ / Amount + ទឹកប្រាក់​សរុប / Total Amount @@ -104,6 +108,11 @@
  • <%= @product %>
  • + + + + + + <% @order.adjustments.each do |adjustment| %> @@ -142,7 +156,7 @@

    ទឹកប្រាក់​ត្រូវទូទាត់​​ / Total Amount due

    - <%= @total %> + <%= @total_price %>

    diff --git a/app/views/spree/billing/subscriptions/_form.html.erb b/app/views/spree/billing/subscriptions/_form.html.erb index b8d6267f7..9d3f122ed 100644 --- a/app/views/spree/billing/subscriptions/_form.html.erb +++ b/app/views/spree/billing/subscriptions/_form.html.erb @@ -1,22 +1,94 @@
    -
    +
    <%= f.hidden_field :customer_id, value: @customer.id %> - <%= f.field_container :variant_id do %> - <%= f.label :variant, Spree.t(:variant) %> - <%= f.collection_select(:variant_id, @customer.subscribable_variants, :id, :display_variant, { include_blank: false }, { class: 'select2' ,disabled: @subscription.persisted?}) %> - <%= f.error_message_on :product_id %> - <% end %> - <%= f.field_container :start_date do %> - <%= f.label :start_date, Spree.t(:start_date) %> - <%= f.date_field :start_date, class: 'form-control', disabled: @subscription.persisted? %> - <%= f.error_message_on :start_date %> - <% end %> - <% if @subscription.id.present? %> - <%= f.field_container :status do %> - <%= f.label :status, Spree.t(:status) %> - <%= f.select :status, SpreeCmCommissioner::Subscription.statuses.keys, {}, class: 'select2' %> - <%= f.error_message_on :status %> + +
    + <%= f.field_container :product do %> + <%= f.label :product, Spree:t(:product) %> + <%= f.select :product, options_for_select(Spree::Product.joins(:taxons) + .where(spree_taxons: { id: @customer.taxon_id }) + .map{ |product| [product.name, product.id] }), + if @subscription.persisted? + { placeholder: @subscription.variant.product.name } + else + { include_blank: true } + end, + { class: "select2-clear", disabled: @subscription.persisted? } %> + <%= f.error_message_on :product %> <% end %> +
    + + <% if @subscription.id.present? %> +
    + <%= f.field_container :variant_id do %> + <%= f.label :variant_id, Spree:t(:variant) %> + <%= f.select :variant_id, options_for_select(Spree::Variant.joins(:subscriptions).where(cm_subscriptions: { customer_id: @customer.id }) + .map{ |variant| [variant.sku, variant.id] }), + if @subscription.persisted? + { placeholder: @subscription.variant.sku } + else + { include_blank: true } + end, + { class: "select2-clear", disabled: @subscription.persisted? } %> + <%= f.error_message_on :product %> + <% end %> +
    + <% else %> +
    +
    <% end %> + +
    + <%= f.field_container :start_date do %> + <%= f.label :start_date, Spree.t(:start_date) %> + <%= f.date_field :start_date, class: 'form-control', disabled: @subscription.persisted? %> + <%= f.error_message_on :start_date %> + <% end %> +
    + +
    + <% if @subscription.id.present? %> + <%= f.field_container :status do %> + <%= f.label :status, Spree.t(:status) %> + <%= f.select :status, SpreeCmCommissioner::Subscription.statuses.keys, {}, class: 'select2' %> + <%= f.error_message_on :status %> + <% end %> + <% end %> +
    + + \ No newline at end of file diff --git a/app/views/spree/billing/subscriptions/_option_types_form.html.erb b/app/views/spree/billing/subscriptions/_option_types_form.html.erb new file mode 100644 index 000000000..ac3ba3475 --- /dev/null +++ b/app/views/spree/billing/subscriptions/_option_types_form.html.erb @@ -0,0 +1,31 @@ +<%= fields_for @variant do |f| %> +
    +
    +
    <%= Spree.t(:variant) %>
    +
    +
    +
    +
    +
    + <%= f.label :price, Spree.t(:price) %> + <%= f.text_field :price, value: number_to_currency(@variant.price, unit: ''), class: 'form-control' %> +
    +
    +
    +
    + <% @product.option_types.each do |option_type| %> +
    + <%= label :new_variant, option_type.presentation %> + <% if option_type.name == 'color' %> + <%= f.collection_select 'option_value_ids', option_type.option_values, :id, :name, + { include_blank: true }, { name: 'variant[option_value_ids][]', class: 'select2-clear form-control', id: "option_value_ids-#{option_type.id}" } %> + <% else %> + <%= f.collection_select 'option_value_ids', option_type.option_values, :id, :presentation, + { include_blank: true }, { name: 'variant[option_value_ids][]', class: 'select2-clear form-control', id: "option_value_ids-#{option_type.id}" } %> + <% end %> +
    + <% end %> +
    +
    +
    +<% end %> diff --git a/config/locales/en.yml b/config/locales/en.yml index 590b8f39d..ba28c1164 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -266,6 +266,7 @@ en: type: "Type" select_date: "Select Date" taxon: "Taxon" + quantity: "Quantity" spree/report: cashier: "Cashier" errors: diff --git a/config/routes.rb b/config/routes.rb index ba0197da3..b8aee1021 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -172,7 +172,11 @@ end resources :vendors resources :customers do - resources :subscriptions + resources :subscriptions do + collection do + get :load_option_types_form + end + end resources :addresses end resources :roles @@ -219,6 +223,10 @@ resources :homepage_section_relatable_options end + namespace :billing do + resources :variants, only: %i[index show] + end + namespace :storefront do resource :cart, controller: :cart, only: %i[show create destroy] do patch :restart_checkout_flow diff --git a/db/migrate/20240119110257_add_quantity_to_cm_customers.rb b/db/migrate/20240119110257_add_quantity_to_cm_customers.rb new file mode 100644 index 000000000..77c34a9a4 --- /dev/null +++ b/db/migrate/20240119110257_add_quantity_to_cm_customers.rb @@ -0,0 +1,5 @@ +class AddQuantityToCmCustomers < ActiveRecord::Migration[7.0] + def change + add_column :cm_customers, :quantity, :integer, default: 1, if_not_exists: true + end +end