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

Added GTIN and Condition to variant for structured data use #6097

Merged
merged 2 commits into from
Feb 19, 2025
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
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,14 @@
<%= render component("ui/forms/field").text_field(f, :meta_title) %>
<%= render component("ui/forms/field").text_field(f, :meta_description) %>
<%= render component("ui/forms/field").text_area(f, :meta_keywords) %>
<%= render component("ui/forms/field").text_field(f, :gtin) %>
<%= render component("ui/forms/field").select(
f,
:condition,
condition_options,
include_blank: t('spree.unset'),
) %>
<% end %>

<%= render component('ui/panel').new(title: "Media") do |panel| %>
<% panel.with_action(
name: t(".manage_images"),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,10 @@ def option_type_options
["#{_1} (#{_2})", _3]
end
end

def condition_options
@condition_options ||= Spree::Variant.conditions.map do |key, value|
[t("spree.condition.#{key}"), value]
end
end
end
2 changes: 1 addition & 1 deletion api/lib/spree/api_configuration.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ class ApiConfiguration < Preferences::Configuration
preference :product_property_attributes, :array, default: [:id, :product_id, :property_id, :value, :property_name]

preference :variant_attributes, :array, default: [
:id, :name, :sku, :weight, :height, :width, :depth, :is_master,
:id, :name, :sku, :gtin, :condition, :weight, :height, :width, :depth, :is_master,
:slug, :description, :track_inventory
]

Expand Down
4 changes: 4 additions & 0 deletions api/openapi/solidus-api.oas.yml
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,8 @@ paths:
product:
name: The Majestic Product
price: '19.99'
gtin: 12345678
condition: new
shipping_category_id: 8
product_properties_attributes:
- property_name: fabric
Expand All @@ -86,6 +88,8 @@ paths:
- price: 19.99
cost_price: 17
sku: SKU-3
gtin: 12345678
condition: new
track_inventory: true
options:
- name: size
Expand Down
18 changes: 18 additions & 0 deletions backend/app/views/spree/admin/products/_form.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,24 @@
</div>
</div>
<% else %>
<div data-hook="admin_product_form_gtin">
<%= f.field_container :gtin do %>
<%= f.label :gtin %>
<%= f.text_field :gtin %>
<% end %>
</div>

<div data-hook="admin_product_form_condition">
<%= f.field_container :condition do %>
<%= f.label :condition %>
<%= f.select :condition,
Spree::Variant.conditions.map { |key, value| [t("spree.condition.#{key}"), value] },
{ include_blank: t('spree.unset') },
class: 'custom-select'
%>
<% end %>
</div>

<div id="shipping_specs" class="row">
<% [:height, :width, :depth, :weight].each_with_index do |field, index| %>
<div id="shipping_specs_<%= field %>_field" class="col-6">
Expand Down
17 changes: 17 additions & 0 deletions backend/app/views/spree/admin/variants/_form.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,23 @@
<%= f.text_field :sku, class: 'fullwidth' %>
</div>
</div>

<div class="col-3">
<div class="field" data-hook="gtin">
<%= f.label :gtin %>
<%= f.text_field :gtin, class: 'fullwidth' %>
</div>
</div>

<div class="col-3">
<div class="field" data-hook="condition">
<%= f.label :condition %>
<%= f.select :condition,
Spree::Variant.conditions.map { |key, value| [t("spree.condition.#{key}"), value] },
{ include_blank: t('spree.unset') },
class: 'custom-select fullwidth' %>
</div>
</div>
<div class="col-3">
<div class="field checkbox" data-hook="track_inventory">
<label>
Expand Down
2 changes: 2 additions & 0 deletions core/app/models/spree/product.rb
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,8 @@ def find_or_build_master
:track_inventory,
:weight,
:width,
:gtin,
:condition
]
MASTER_ATTRIBUTES.each do |attr|
delegate :"#{attr}", :"#{attr}=", to: :find_or_build_master
Expand Down
4 changes: 4 additions & 0 deletions core/app/models/spree/variant.rb
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,10 @@ class Variant < Spree::Base
attr_writer :rebuild_vat_prices
include Spree::DefaultPrice

# Consider that not all platforms digest structured data in the same way,
# you might have to modify the output on the frontend or in feeds accordingly.
enum :condition, { damaged: "damaged", new: "new", refurbished: "refurbished", used: "used" }, prefix: true

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
Expand Down
10 changes: 10 additions & 0 deletions core/config/locales/en.yml
Original file line number Diff line number Diff line change
Expand Up @@ -166,11 +166,13 @@ en:
variant: Variant
spree/product:
available_on: Available On
condition: Master Condition
cost_currency: Cost Currency
cost_price: Cost Price
depth: Depth
description: Description
discontinue_on: Discontinue on
gtin: Master GTIN
height: Height
master_price: Master Price
meta_description: Meta Description
Expand Down Expand Up @@ -418,9 +420,11 @@ en:
password_confirmation: Password Confirmation
spree_roles: Roles
spree/variant:
condition: Condition
cost_currency: Cost Currency
cost_price: Cost Price
depth: Depth
gtin: GTIN
height: Height
price: Price
shipping_category: Variant Shipping Category
Expand Down Expand Up @@ -1134,6 +1138,11 @@ en:
company: Company
complete: complete
complete_order: Complete Order
condition:
damaged: Damaged
new: New
refurbished: Refurbished
used: Used
configuration: Configuration
configurations: Configurations
confirm: Confirm
Expand Down Expand Up @@ -2315,6 +2324,7 @@ en:
unfinalize_all_adjustments: Unfinalize All Adjustments
unlock: Unlock
unrecognized_card_type: Unrecognized Card Type
unset: Unset
unshippable_items: Unshippable Items
update: Update
updated_successfully: Updated Successfully
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
class AddGtinAndConditionToSpreeVariant < ActiveRecord::Migration[7.0]
def change
add_column :spree_variants, :gtin, :string
add_column :spree_variants, :condition, :string
end
end
3 changes: 2 additions & 1 deletion core/lib/spree/permitted_attributes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,8 @@ module PermittedAttributes
:meta_keywords, :price, :sku, :deleted_at,
:option_values_hash, :weight, :height, :width, :depth,
:shipping_category_id, :tax_category_id,
:taxon_ids, :option_type_ids, :cost_currency, :cost_price, :primary_taxon_id
:taxon_ids, :option_type_ids, :cost_currency, :cost_price, :primary_taxon_id,
:gtin, :condition
]

@@property_attributes = [:name, :presentation]
Expand Down
15 changes: 15 additions & 0 deletions core/spec/models/spree/product_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,21 @@ class Extension < Spree::Base
expect(product.reload.master.default_price.price).to eq 12
end
end

context "when master variant attributes change" do
before do
product.master.gtin = "1234567890123"
product.master.condition = "new"
end

it_behaves_like "a change occurred"

it "saves the master with updated gtin and condition" do
product.save!
expect(product.reload.master.gtin).to eq "1234567890123"
expect(product.reload.master.condition).to eq "new"
end
end
end

context "product has no variants" do
Expand Down
32 changes: 32 additions & 0 deletions core/spec/models/spree/variant_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,38 @@
end
end

describe 'enums' do
it 'has the correct enum values' do
expect(described_class.conditions).to eq({
"damaged" => "damaged",
"new" => "new",
"refurbished" => "refurbished",
"used" => "used"
})
end

it 'correctly assigns and reads condition values' do
variant = create(:variant, condition: 'new')
expect(variant.reload.condition).to eq('new')
end

it 'does not accept invalid enum values' do
expect { create(:variant, condition: 'invalid_value') }.to raise_error(ArgumentError)
end
end

describe 'gtin and condition attributes' do
let(:variant) { create(:variant, gtin: '1234567890123', condition: 'new') }

it 'has a GTIN' do
expect(variant.gtin).to eq('1234567890123')
end

it 'has a condition' do
expect(variant.condition).to eq('new')
end
end

context "validations" do
it "should validate price is greater than 0" do
variant = build(:variant, price: -1)
Expand Down
24 changes: 24 additions & 0 deletions sample/db/samples/products.rb
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@
shipping_category:,
price: 19.99,
eur_price: 16,
gtin: 12345678,
condition: "new",
weight: 0.5,
height: 20,
width: 10,
Expand All @@ -38,6 +40,8 @@
shipping_category:,
price: 19.99,
eur_price: 16,
gtin: 12345678,
condition: "new",
weight: 0.5,
height: 20,
width: 10,
Expand All @@ -49,6 +53,8 @@
shipping_category:,
price: 29.99,
eur_price: 27,
gtin: 12345678,
condition: "new",
weight: 1,
height: 20,
width: 10,
Expand All @@ -60,6 +66,8 @@
shipping_category:,
price: 19.99,
eur_price: 16,
gtin: 12345678,
condition: "new",
weight: 0.5,
height: 20,
width: 10,
Expand All @@ -71,6 +79,8 @@
shipping_category:,
price: 29.99,
eur_price: 27,
gtin: 12345678,
condition: "new",
weight: 1,
height: 20,
width: 10,
Expand All @@ -82,6 +92,8 @@
shipping_category:,
price: 29.99,
eur_price: 27,
gtin: 12345678,
condition: "new",
weight: 0.8,
height: 20,
width: 10,
Expand All @@ -93,6 +105,8 @@
shipping_category:,
price: 26.99,
eur_price: 23,
gtin: 12345678,
condition: "new",
weight: 0.5,
height: 20,
width: 10,
Expand All @@ -104,6 +118,8 @@
shipping_category:,
price: 9.99,
eur_price: 7,
gtin: 12345678,
condition: "new",
weight: 1,
height: 5,
width: 5,
Expand All @@ -115,6 +131,8 @@
shipping_category:,
price: 15.99,
eur_price: 14,
gtin: 12345678,
condition: "new",
weight: 0.5,
height: 20,
width: 10,
Expand All @@ -126,6 +144,8 @@
shipping_category:,
price: 15.99,
eur_price: 14,
gtin: 12345678,
condition: "new",
weight: 0.5,
height: 20,
width: 10,
Expand All @@ -137,6 +157,8 @@
shipping_category:,
price: 15.99,
eur_price: 14,
gtin: 12345678,
condition: "new",
weight: 0.5,
height: 20,
width: 10,
Expand All @@ -149,6 +171,8 @@
shipping_category:,
price: 24,
eur_price: 22,
gtin: 12345678,
condition: "new",
weight: 0.5,
height: 20,
width: 10,
Expand Down