Skip to content
Merged
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
2 changes: 2 additions & 0 deletions api/openapi/solidus-api.oas.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7168,6 +7168,8 @@ components:
type: boolean
product_id:
type: integer
shipping_category_id:
type: integer
tax_category_id:
type: integer
weight:
Expand Down
1 change: 1 addition & 0 deletions backend/app/controllers/spree/admin/variants_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ def collection

def load_data
@tax_categories = Spree::TaxCategory.order(:name)
@shipping_categories = Spree::ShippingCategory.order(:name)
end

def variant_includes
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<div data-hook="admin_<%= model_name %>_form_generate_vat_prices" class="<%= local_assigns[:wrapper_class] %> checkbox">
<div data-hook="admin_<%= model_name %>_form_generate_vat_prices" class="checkbox">
<label>
<%= form.check_box :rebuild_vat_prices, checked: form.object.prices.size <= 1 %>
<%= Spree::Variant.human_attribute_name(:rebuild_vat_prices) %>
Expand Down
22 changes: 16 additions & 6 deletions backend/app/views/spree/admin/variants/_form.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -70,14 +70,11 @@
<%= f.label :price %>
<%= render "spree/admin/shared/number_with_currency", f: f, amount_attr: :price, currency: @variant.default_price_or_build.currency %>
</div>
<% if show_rebuild_vat_checkbox? %>
<%= render "spree/admin/shared/rebuild_vat_prices_checkbox", form: f, model_name: "variant" %>
<% end %>
</div>

<% if show_rebuild_vat_checkbox? %>
<div class="col-3">
<%= render "spree/admin/shared/rebuild_vat_prices_checkbox", form: f, model_name: "variant", wrapper_class: "field" %>
</div>
<% end %>

<div class="col-3">
<div class="field" data-hook="cost_price">
<%= f.label :cost_price %>
Expand All @@ -97,6 +94,19 @@
{ class: 'custom-select fullwidth' } %>
</div>
</div>

<div class="col-3">
<div class="field" data-hook="shipping_category">
<%= f.label :shipping_category %>
<%= f.field_hint :shipping_category %>
<%= f.collection_select :shipping_category_id,
@shipping_categories,
:id,
:name,
{ include_blank: t('.use_product_shipping_category') },
Comment thread
tvdeyen marked this conversation as resolved.
{ class: 'custom-select fullwidth' } %>
</div>
</div>
</div>
</fieldset>
</div>
Expand Down
1 change: 1 addition & 0 deletions backend/spec/features/admin/products/variant_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
expect(page).to have_field('variant_width', with: "1.00")
expect(page).to have_field('variant_depth', with: "1.50")
expect(page).to have_select('variant[tax_category_id]')
expect(page).to have_select('variant[shipping_category_id]')
end
end

Expand Down
22 changes: 21 additions & 1 deletion core/app/models/spree/variant.rb
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,14 @@ class Variant < Spree::Base

belongs_to :product, -> { with_discarded }, touch: true, class_name: 'Spree::Product', inverse_of: :variants_including_master, optional: false
belongs_to :tax_category, class_name: 'Spree::TaxCategory', optional: true
belongs_to :shipping_category, class_name: "Spree::ShippingCategory", optional: true

delegate :name, :description, :slug, :available_on, :discontinue_on, :discontinued?,
:shipping_category_id, :meta_description, :meta_keywords, :shipping_category,
:meta_description, :meta_keywords,
to: :product
delegate :tax_category, to: :product, prefix: true
delegate :shipping_category, :shipping_category_id,
to: :product, prefix: true
delegate :tax_rates, to: :tax_category

has_many :inventory_units, inverse_of: :variant
Expand Down Expand Up @@ -142,6 +145,23 @@ def tax_category
super || product_tax_category
end

# @return [Spree::ShippingCategory] the variant's shipping category
#
# This returns the product's shipping category if the shipping category ID on the variant is nil. It looks
# like an association, but really is an override.
#
def shipping_category
super || product_shipping_category
end

# @return [Integer] the variant's shipping category id
#
# This returns the product's shipping category if if the shipping category ID on the variant is nil.
#
def shipping_category_id
super || product_shipping_category_id
end

# Sets the cost_price for the variant.
#
# @param price [Any] the price to set
Expand Down
3 changes: 3 additions & 0 deletions core/config/locales/en.yml
Original file line number Diff line number Diff line change
Expand Up @@ -415,6 +415,7 @@ en:
depth: Depth
height: Height
price: Price
shipping_category: Variant Shipping Category
sku: SKU
tax_category: Variant Tax Category
weight: Weight
Expand Down Expand Up @@ -993,6 +994,7 @@ en:
pricing: Pricing
pricing_hint: These values are populated from the product details page and can be overridden below
properties: Properties
use_product_shipping_category: Use Product Shipping Category
use_product_tax_category: Use Product Tax Category
new:
new_variant: New Variant
Expand Down Expand Up @@ -1641,6 +1643,7 @@ en:
deleted: Deleted Variant
deleted_explanation: This variant was deleted on %{date}.
deleted_explanation_with_replacement: This variant was deleted on %{date}. It has since been replaced by another with the same SKU.
shipping_category: 'This determines what kind of shipping this variant requires.<br/> Default: Use shipping category of the product associated with this variant'
tax_category: 'This determines what kind of taxation is applied to this variant.<br/> Default: Use tax category of the product associated with this variant'
home: Home
i18n:
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
class AddShippingCategoryToSpreeVariants < ActiveRecord::Migration[5.2]
def change
add_reference :spree_variants, :shipping_category, index: true
Comment thread
tvdeyen marked this conversation as resolved.
end
end
5 changes: 4 additions & 1 deletion core/lib/spree/permitted_attributes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,10 @@ module PermittedAttributes
:name, :presentation, :cost_price, :lock_version,
:position, :track_inventory,
:product_id, :product, :price,
:weight, :height, :width, :depth, :sku, :cost_currency, :tax_category_id, option_value_ids: [], options: [:name, :value]
:weight, :height, :width, :depth, :sku, :cost_currency,
:tax_category_id, :shipping_category_id,
option_value_ids: [],
options: [:name, :value]
]

@@checkout_address_attributes = [
Expand Down
38 changes: 38 additions & 0 deletions core/spec/models/spree/variant_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -773,6 +773,44 @@
end
end

describe '#shipping_category' do
context 'when shipping_category is nil' do
let(:shipping_category) { build(:shipping_category) }
let(:product) { build(:product, shipping_category: shipping_category) }
let(:variant) { build(:variant, product: product, shipping_category_id: nil) }
it 'returns the parent products shipping_category' do
expect(variant.shipping_category).to eq(shipping_category)
end
end

context 'when shipping_category is set' do
let(:shipping_category) { create(:shipping_category) }
let(:variant) { build(:variant, shipping_category: shipping_category) }
it 'returns the shipping_category set on itself' do
expect(variant.shipping_category).to eq(shipping_category)
end
end
end

describe '#shipping_category_id' do
context 'when shipping_category_id is nil' do
let(:shipping_category) { build(:shipping_category) }
let(:product) { build(:product, shipping_category: shipping_category) }
let(:variant) { build(:variant, product: product, shipping_category_id: nil) }
it 'returns the parent products shipping_category_id' do
expect(variant.shipping_category_id).to eq(shipping_category.id)
end
end

context 'when shipping_category_id is set' do
let(:shipping_category) { create(:shipping_category) }
let(:variant) { build(:variant, shipping_category_id: shipping_category.id) }
it 'returns the shipping_category_id set on itself' do
expect(variant.shipping_category_id).to eq(shipping_category.id)
end
end
end

describe "touching" do
it "updates a product" do
variant.product.update_column(:updated_at, 1.day.ago)
Expand Down