Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP #1037 Add Quantity to Customer and Add Query or Create Variant … #1055

Open
wants to merge 1 commit into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 27 additions & 5 deletions app/controllers/spree/billing/subscriptions_controller.rb
Original file line number Diff line number Diff line change
@@ -1,8 +1,22 @@
module Spree
module Billing
class SubscriptionsController < Spree::Billing::BaseController
before_action :load_customer
before_action :load_subscription, if: -> { member_action? }
before_action :load_variant, only: :create

helper_method :customer

def create
@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

Expand All @@ -13,14 +27,14 @@ def collection
@collection = @search.result.page(page).per(per_page)
end

def load_customer
customer
end

def load_subscription
@subscription = @object
end

def load_variant
@variant = SpreeCmCommissioner::VariantChecker.new(variant_params, current_vendor).find_or_create_variant
end

def customer
@customer ||= SpreeCmCommissioner::Customer.find(params[:customer_id])
Regene27 marked this conversation as resolved.
Show resolved Hide resolved
end
Expand All @@ -39,6 +53,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, :variant_id)
end
end
end
end
10 changes: 10 additions & 0 deletions app/controllers/spree/billing/variants_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,16 @@ class VariantsController < Spree::Billing::BaseController
belongs_to 'spree/product', find_by: :slug
before_action :load_data

def new
if request.xhr?
@variant = @product.variants.build

render :show, layout: false
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

render layout: false instead and create a new.html.erb in the view.

else
redirect_to new_billing_product_variant_url(@product)
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this will redirect to itself and then it will end up with a loop redirect

end
end

def collection
return @collection if @collection.present?

Expand Down
3 changes: 3 additions & 0 deletions app/models/spree_cm_commissioner/subscription.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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'
Expand All @@ -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
Expand Down
2 changes: 2 additions & 0 deletions app/models/spree_cm_commissioner/variant_decorator.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,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
Expand Down
29 changes: 29 additions & 0 deletions app/services/spree_cm_commissioner/sku_generator.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
module SpreeCmCommissioner
class SkuGenerator
def initialize(product, variant_params)
@product = product
@variant_params = variant_params
end

def generate_sku
return if @variant_params.nil? || @variant_params.blank?

option_values = @variant_params[:option_value_ids].map { |id| Spree::OptionValue.find(id) }
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use Spree::OptionValue.find(@variant_params[:option_value_ids) instead.

sku_parts = [product.name]

option_values.each do |option_value|
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

use the map method instead.

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 product
@product ||= Spree::Product.find(@variant_params[:product_id])
end
end
end
32 changes: 32 additions & 0 deletions app/services/spree_cm_commissioner/variant_checker.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
module SpreeCmCommissioner
class VariantChecker
Regene27 marked this conversation as resolved.
Show resolved Hide resolved
attr_reader :variant

def initialize(variant_params, current_vendor)
@product = Spree::Product.find_by(id: variant_params[:product_id])
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

use the find method instead and create a method called product with

@product ||= Spree::Product.find(variant_params[:product_id])

@variant_params = variant_params
@current_vendor = current_vendor
end

def find_or_create_variant
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

rename find_or_create_variant to variant instead and merge the implementation of the find_variant_by_sku and create_variant. No need to have find_variant_by_sku and create_variant methods.

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
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

memoize this method.

end
end
end
37 changes: 37 additions & 0 deletions app/services/spree_cm_commissioner/variant_creator.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
module SpreeCmCommissioner
class VariantCreator
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

apply the same concept here.

attr_reader :variant

def initialize(product, variant_params, current_vendor)
@product = product
@variant_params = variant_params
@current_vendor = current_vendor
end

def create_variant
Regene27 marked this conversation as resolved.
Show resolved Hide resolved
@variant = @product.variants.build
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

inconsistent code.

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
Regene27 marked this conversation as resolved.
Show resolved Hide resolved
@stock_location ||= Spree::StockLocation.find_by!(vendor_id: @current_vendor.id).id
end
end
end
6 changes: 3 additions & 3 deletions app/views/spree/billing/shared/_subscription_tabs.html.erb
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
<% content_for :page_title do %>
<%= page_header_back_button spree.billing_customer_subscriptions_path(@customer) %>
<%= page_header_back_button spree.billing_customer_subscriptions_path(customer) %>
<%= @subscription.variant.sku %>
<% end %>
<% content_for :page_tabs do %>
<li class="nav-item">
<%= link_to_with_icon 'tag.svg',
Spree.t(:edit),
spree.edit_billing_customer_subscription_path(@customer, @subscription),
spree.edit_billing_customer_subscription_path(customer, @subscription),
class: "nav-link #{'active' if current == :account}" %>
</li>
<% end %>
<% content_for :page_tabs do %>
<li class="nav-item">
<%= link_to_with_icon 'cart.svg',
Spree.t(:orders),
spree.billing_orders_path(customer_id: @customer.id, subscription_id: @subscription.id),
spree.billing_orders_path(customer_id: customer.id, subscription_id: @subscription.id),
class: "nav-link #{'active' if current == :order}" %>
</li>
<% end %>
104 changes: 86 additions & 18 deletions app/views/spree/billing/subscriptions/_form.html.erb
Original file line number Diff line number Diff line change
@@ -1,22 +1,90 @@
<div data-hook="admin_user_form_fields" class="row">
<div class="col-12 col-md-6">
<%= 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 %>
<div class="col-12">
<%= f.hidden_field :customer_id, value: customer.id %>

<div class="col-12">
<% if @subscription.persisted? %>
<%= f.field_container :product do %>
<%= f.label :product, Spree.t(:product) %>
<%= f.text_field :product, value: f.object.variant.product.name, class: 'form-control', disabled: true %>
<%= f.error_message_on :product %>
<% end %>
<% else %>
<%= 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.sku] }),
{ include_blank: true },
{ class: "select2-clear" } %>
<%= f.error_message_on :product %>
<% end %>
<% end %>
<% end %>
</div>

<div class="col-12">
<% if @subscription.persisted? %>
<%= f.field_container :variant do %>
<%= f.label :variant, Spree.t(:variant) %>
<%= f.text_field :variant, value: f.object.variant.sku, class: 'form-control', disabled: true %>
<%= f.error_message_on :product %>
<% end %>
<% else %>
<div id="option-types-form-container">
</div>
<% end %>
</div>

<div class="col-12">
<%= 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 %>
</div>

<div class="col-12">
<% 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 %>
</div>
</div>
</div>

<script>
$(document).ready(function () {
const productSelector = "#spree_cm_commissioner_subscription_product";
const variantIdSelector = "#spree_cm_commissioner_subscription_variant_id";
const optionTypesFormDiv = "#option-types-form-container";

$(productSelector).on("change", function () {
removeOptionTypesForm();
appendOptionTypesForm();
});

function appendOptionTypesForm() {
var productSku = $(productSelector).val();

$.ajax({
url: '/en/billing/products/' + productSku + '/variants/new',
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

pass the URL from the Rails. Don't construct the URL in the js

type: 'GET',
dataType: 'html',
success: function (response) {
console.log('Success fetching form:', response);
$(optionTypesFormDiv).append(response);
},
error: function (error) {
console.error('Error fetching form:', error);
}
});
}

function removeOptionTypesForm() {
$(optionTypesFormDiv).empty();
}
});
</script>
33 changes: 33 additions & 0 deletions app/views/spree/billing/variants/show.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<%= fields_for @variant do |f| %>
<div class="card mb-3">
<div class="card-header">
<h5 class="mb-0"><%= Spree.t(:variant) %></h5>
</div>
<%= f.hidden_field :product_id, value: @product.id %>

<div class="row">
<div data-hook="billing_variant_form_fields" class="col-6 p-4">
<div data-hook="variants">
<div class="form-group " data-hook="price">
<%= 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' %>
</div>
</div>
</div>
<div data-hook="billing_varaint_option_types_field" class="col-6 p-4">
<% @product.option_types.each do |option_type| %>
<div class="form-group" data-hook="presentation">
<%= 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 %>
</div>
<% end %>
</div>
</div>
</div>
<% end %>
1 change: 1 addition & 0 deletions config/locales/en.yml
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,7 @@ en:
overdue: "Overdue"
failed: "Failed"
unknown: "Unknown"
subscription_price_placeholder: "Subscription Price In %{currency}"
upsupported_payment: "Unsupported event"
exceeded_available_quantity_on_date:
zero: "Rooms are not available on %{date}"
Expand Down
1 change: 1 addition & 0 deletions config/locales/km.yml
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,7 @@ km:
overdue: "ហួសថ្ងៃបង់"
failed: "បរាជ័យ"
unknown: "មិនស្គាល់"
subscription_price_placeholder: "តម្លៃជា​​​ %{currency}"
upsupported_payment: "មិនស្គាល់ការបង់ប្រាក់"
selected_item_not_available_on_date: "Selected item not available on %{date}"
auto_apply: "ដាក់ប្រើដោយស្វ័យប្រវត្តិ"
Expand Down
4 changes: 4 additions & 0 deletions config/routes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,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
Expand Down
Loading
Loading