diff --git a/app/controllers/spree/billing/products_controller.rb b/app/controllers/spree/billing/products_controller.rb index 14e3b4daa..cb5725147 100644 --- a/app/controllers/spree/billing/products_controller.rb +++ b/app/controllers/spree/billing/products_controller.rb @@ -7,6 +7,16 @@ def scope current_vendor.products.where(subscribable: true) end + def show + if request.xhr? + @variant = @product.variants.build + + render layout: false + else + redirect_to edit_billing_product_url(@product) + end + end + def collection return @collection if defined?(@collection) diff --git a/app/controllers/spree/billing/subscriptions_controller.rb b/app/controllers/spree/billing/subscriptions_controller.rb index 488d304b0..c78ec9ee9 100644 --- a/app/controllers/spree/billing/subscriptions_controller.rb +++ b/app/controllers/spree/billing/subscriptions_controller.rb @@ -1,8 +1,22 @@ module Spree module Billing class SubscriptionsController < Spree::Billing::BaseController - before_action :load_customer + before_action :customer before_action :load_subscription, if: -> { member_action? } + before_action :product, only: :create + + def create + find_or_create_variant + + @subscription = @variant.subscriptions.build(subscription_params.merge(variant_id: @variant.id)) + + if @subscription.save + flash[:success] = flash_message_for(@subscription, :successfully_created) + else + flash[:error] = flash_message_for(@subscription, :not_created) + end + redirect_to billing_customer_subscriptions_url(@customer) + end protected @@ -13,14 +27,19 @@ def collection @collection = @search.result.page(page).per(per_page) end - def load_customer - customer + def product + product_id = params[:product_id] || params.dig(:variant, :product_id) + @product = Spree::Product.find(product_id) end def load_subscription @subscription = @object end + def find_or_create_variant + @variant = SpreeCmCommissioner::VariantChecker.new(@product, variant_params, current_vendor).find_or_create_variant + end + def customer @customer ||= SpreeCmCommissioner::Customer.find(params[:customer_id]) end @@ -39,6 +58,14 @@ def object_name def collection_url(options = {}) billing_customer_subscriptions_url(options) end + + def variant_params + params.require(:variant).permit(:product_id, :sku, :price, option_value_ids: []) + 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/services/spree_cm_commissioner/sku_generator.rb b/app/services/spree_cm_commissioner/sku_generator.rb new file mode 100644 index 000000000..d58c6ee9c --- /dev/null +++ b/app/services/spree_cm_commissioner/sku_generator.rb @@ -0,0 +1,31 @@ +module SpreeCmCommissioner + class SkuGenerator + def initialize(product, variant_params) + @product = product + @variant_params = variant_params + end + + def generate_sku + load_product + + return if @variant_params.nil? || @variant_params.blank? + + option_values = @variant_params[: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-#{@variant_params[:price]}" + + sku_parts.join('-').gsub(' ', '-').downcase + end + + private + + def load_product + @product ||= Spree::Product.find(@variant_params[:product_id]) + end + end +end diff --git a/app/services/spree_cm_commissioner/variant_checker.rb b/app/services/spree_cm_commissioner/variant_checker.rb new file mode 100644 index 000000000..00f8cd9c2 --- /dev/null +++ b/app/services/spree_cm_commissioner/variant_checker.rb @@ -0,0 +1,32 @@ +module SpreeCmCommissioner + class VariantChecker + attr_reader :variant + + def initialize(product, variant_params, current_vendor) + @product = product + @variant_params = variant_params + @current_vendor = current_vendor + end + + def find_or_create_variant + find_variant_by_sku || create_variant + end + + private + + def find_variant_by_sku + @variant = @product.variants.where(sku: variant_sku).first + end + + def create_variant + variant_creator = SpreeCmCommissioner::VariantCreator.new(@product, @variant_params, @current_vendor) + variant_creator.create_variant + @variant = variant_creator.variant + end + + def variant_sku + sku_generator = SpreeCmCommissioner::SkuGenerator.new(@product, @variant_params) + sku_generator.generate_sku + end + end +end diff --git a/app/services/spree_cm_commissioner/variant_creator.rb b/app/services/spree_cm_commissioner/variant_creator.rb new file mode 100644 index 000000000..b517110ae --- /dev/null +++ b/app/services/spree_cm_commissioner/variant_creator.rb @@ -0,0 +1,37 @@ +module SpreeCmCommissioner + class VariantCreator + attr_reader :variant + + def initialize(product, variant_params, current_vendor) + @product = product + @variant_params = variant_params + @current_vendor = current_vendor + end + + def create_variant + @variant = @product.variants.build + generate_sku + set_variant_attributes + @variant.save + @variant + end + + private + + def generate_sku + sku_generator = SpreeCmCommissioner::SkuGenerator.new(@product, @variant_params) + @variant.sku = sku_generator.generate_sku + end + + def set_variant_attributes + @variant.option_value_ids = @variant_params[:option_value_ids] + @variant.price = @variant_params[:price] + stock_item = @variant.stock_items.build(stock_location_id: stock_location, count_on_hand: 1, backorderable: false) + stock_item.save + end + + def stock_location + @stock_location ||= Spree::StockLocation.find_by!(vendor_id: @current_vendor.id).id + end + end +end 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/products/show.erb b/app/views/spree/billing/products/show.erb new file mode 100644 index 000000000..8bb02de74 --- /dev/null +++ b/app/views/spree/billing/products/show.erb @@ -0,0 +1,33 @@ + <%= fields_for @variant do |f| %> +
+
+
<%= Spree.t(:variant) %>
+
+ <%= f.hidden_field :product_id, value: @product.id %> + +
+
+
+
+ <%= f.label :price, Spree.t(:price) %> + <%= f.text_field :price, placeholder: I18n.t('spree.billing.subscription_price_placeholder', currency: @variant.currency), 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/app/views/spree/billing/shared/_invoice.html.erb b/app/views/spree/billing/shared/_invoice.html.erb index b5ad7c154..77770bf6b 100644 --- a/app/views/spree/billing/shared/_invoice.html.erb +++ b/app/views/spree/billing/shared/_invoice.html.erb @@ -8,8 +8,16 @@ @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 + @sum_total = @price.to_s.gsub(/[^\d.]/, '').to_d * @quantity + @total_price = @sum_total + @sum_total = Spree::Money.new(@sum_total, currency: @price.currency).to_s + @order.adjustments.each do |adjustment| + @total_price += adjustment.amount + end + @total_price = Spree::Money.new(@total_price, currency: @price.currency).to_s @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 +100,10 @@ ល.រ​​​ / N បរិយាយ / Description + ចំនួន / Quantity ប្រចាំខែ / Month ទឹកប្រាក់​ / Amount + ទឹកប្រាក់​សរុប / Total Amount @@ -104,6 +114,11 @@
  • <%= @product %>
  • + + + + + + <% @order.adjustments.each do |adjustment| %> @@ -126,6 +146,15 @@ + + + + +