solidus_product_assembly 1.0.0 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/.circleci/config.yml +35 -0
- data/.gem_release.yml +5 -0
- data/.github/dependabot.yml +7 -0
- data/.github/stale.yml +17 -0
- data/.gitignore +14 -2
- data/.rspec +2 -2
- data/.rubocop.yml +4 -0
- data/.rubocop_todo.yml +192 -0
- data/CHANGELOG.md +19 -0
- data/Gemfile +21 -9
- data/LICENSE +26 -0
- data/README.md +52 -18
- data/Rakefile +4 -19
- data/app/controllers/spree/admin/parts_controller.rb +13 -11
- data/app/decorators/controllers/solidus_product_assembly/spree/checkout_controller_decorator.rb +13 -0
- data/app/decorators/helpers/solidus_product_assembly/spree/admin/orders_helper_decorator.rb +19 -0
- data/app/decorators/models/solidus_product_assembly/spree/inventory_unit_decorator.rb +19 -0
- data/app/decorators/models/solidus_product_assembly/spree/line_item_decorator.rb +52 -0
- data/app/decorators/models/solidus_product_assembly/spree/product_decorator.rb +70 -0
- data/app/decorators/models/solidus_product_assembly/spree/return_item_decorator.rb +15 -0
- data/app/decorators/models/solidus_product_assembly/spree/shipment_decorator.rb +55 -0
- data/app/decorators/models/solidus_product_assembly/spree/stock/availability_validator_decorator.rb +37 -0
- data/app/decorators/models/solidus_product_assembly/spree/stock/inventory_unit_builder_decorator.rb +39 -0
- data/app/decorators/models/solidus_product_assembly/spree/stock/inventory_units_finalizer_decorator.rb +33 -0
- data/app/decorators/models/solidus_product_assembly/spree/stock/inventory_validator_decorator.rb +22 -0
- data/app/decorators/models/solidus_product_assembly/spree/variant_decorator.rb +26 -0
- data/app/models/spree/assemblies_part.rb +6 -4
- data/app/models/spree/calculator/returns/assemblies_default_refund_amount.rb +17 -0
- data/app/models/spree/order_inventory_assembly.rb +11 -2
- data/app/overrides/add_admin_product_form_fields.rb +7 -5
- data/app/overrides/add_admin_tabs.rb +7 -5
- data/app/overrides/add_line_item_description.rb +7 -5
- data/app/overrides/spree/admin/orders/_carton_manifest/_assembly_parts_price.html.erb.deface +9 -0
- data/app/overrides/spree/admin/orders/_carton_manifest/_assembly_parts_total_price.html.erb.deface +9 -0
- data/app/overrides/spree/admin/orders/_shipment/stock_contents.html.erb.deface +7 -1
- data/app/overrides/spree/products/show/add_links_to_parts.html.erb.deface +2 -2
- data/app/views/spree/admin/orders/_assemblies.html.erb +8 -17
- data/app/views/spree/admin/orders/_stock_contents.html.erb +2 -62
- data/app/views/spree/admin/orders/_stock_contents_2_3.html.erb +69 -0
- data/app/views/spree/admin/orders/_stock_contents_2_4.html.erb +70 -0
- data/app/views/spree/admin/orders/_stock_item.html.erb +13 -10
- data/app/views/spree/admin/parts/_parts_table.html.erb +17 -11
- data/app/views/spree/admin/parts/available.html.erb +10 -8
- data/app/views/spree/admin/parts/available.js.erb +9 -7
- data/app/views/spree/admin/parts/index.html.erb +1 -1
- data/app/views/spree/admin/products/_product_assembly_fields.html.erb +2 -2
- data/app/views/spree/admin/shared/_product_assembly_product_tabs.html.erb +1 -1
- data/app/views/spree/api/line_items/show.v1.rabl +27 -0
- data/app/views/spree/checkout/_line_item_manifest.html.erb +3 -1
- data/bin/console +17 -0
- data/bin/rails +12 -4
- data/bin/setup +8 -0
- data/config/routes.rb +2 -2
- data/db/migrate/20091028152124_add_many_to_many_relation_to_products.rb +7 -5
- data/db/migrate/20091029165620_add_parts_fields_to_products.rb +18 -16
- data/db/migrate/20120316141830_namespace_product_assembly_for_spree_one.rb +3 -1
- data/db/migrate/20140620223938_add_id_to_spree_assemblies_parts.rb +4 -2
- data/lib/generators/solidus_product_assembly/install/install_generator.rb +13 -8
- data/lib/solidus_product_assembly/engine.rb +11 -8
- data/lib/solidus_product_assembly/testing_support/factories.rb +4 -0
- data/lib/solidus_product_assembly/version.rb +3 -1
- data/lib/solidus_product_assembly.rb +5 -1
- data/lib/tasks/spree2_upgrade.rake +12 -12
- data/solidus_product_assembly.gemspec +25 -20
- data/spec/features/admin/orders_spec.rb +114 -16
- data/spec/features/admin/parts_spec.rb +5 -3
- data/spec/features/admin/return_items_spec.rb +151 -0
- data/spec/features/checkout_spec.rb +103 -21
- data/spec/models/spree/assemblies_part_spec.rb +3 -1
- data/spec/models/spree/inventory_unit_spec.rb +15 -6
- data/spec/models/spree/line_item_spec.rb +6 -4
- data/spec/models/spree/order_contents_spec.rb +6 -5
- data/spec/models/spree/order_inventory_assembly_spec.rb +8 -6
- data/spec/models/spree/order_inventory_spec.rb +7 -3
- data/spec/models/spree/product_spec.rb +15 -14
- data/spec/models/spree/shipment_spec.rb +20 -13
- data/spec/models/spree/stock/availability_validator_spec.rb +22 -33
- data/spec/models/spree/stock/coordinator_spec.rb +11 -3
- data/spec/models/spree/stock/inventory_unit_builder_spec.rb +5 -7
- data/spec/models/spree/variant_spec.rb +3 -1
- data/spec/spec_helper.rb +18 -47
- data/spec/support/shared_contexts/order_with_bundle.rb +2 -0
- metadata +80 -102
- data/.travis.yml +0 -21
- data/LICENSE.md +0 -13
- data/app/controllers/spree/checkout_controller_decorator.rb +0 -9
- data/app/helpers/spree/admin/orders_helper_decorator.rb +0 -9
- data/app/models/spree/inventory_unit_decorator.rb +0 -13
- data/app/models/spree/line_item_decorator.rb +0 -44
- data/app/models/spree/product_decorator.rb +0 -56
- data/app/models/spree/shipment_decorator.rb +0 -50
- data/app/models/spree/stock/availability_validator.rb +0 -28
- data/app/models/spree/stock/inventory_unit_builder_decorator.rb +0 -30
- data/app/models/spree/stock/inventory_validator_decorator.rb +0 -12
- data/app/models/spree/variant_decorator.rb +0 -13
@@ -1,27 +1,27 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
namespace :solidus_product_assembly do
|
2
4
|
desc 'Link legacy inventory units to an order line item'
|
3
|
-
task :
|
5
|
+
task upgrade: :environment do
|
4
6
|
shipments = Spree::Shipment.includes(:inventory_units).where("spree_inventory_units.line_item_id IS NULL")
|
5
7
|
|
6
8
|
shipments.each do |shipment|
|
7
9
|
shipment.inventory_units.includes(:variant).group_by(&:variant).each do |variant, units|
|
8
|
-
|
9
10
|
line_item = shipment.order.line_items.detect { |line_item| line_item.variant_id == variant.id }
|
10
11
|
|
11
|
-
|
12
|
+
next if line_item
|
12
13
|
|
13
|
-
|
14
|
-
|
15
|
-
|
14
|
+
begin
|
15
|
+
master = shipment.order.products.detect { |p| variant.assemblies.include? p }.master
|
16
|
+
supposed_line_item = shipment.order.line_items.detect { |line_item| line_item.variant_id == master.id }
|
16
17
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
puts "Couldn't find a matching line item for #{variant.name}"
|
21
|
-
end
|
22
|
-
rescue
|
18
|
+
if supposed_line_item
|
19
|
+
Spree::InventoryUnit.where(id: units.map(&:id)).update_all "line_item_id = #{supposed_line_item.id}"
|
20
|
+
else
|
23
21
|
puts "Couldn't find a matching line item for #{variant.name}"
|
24
22
|
end
|
23
|
+
rescue StandardError
|
24
|
+
puts "Couldn't find a matching line item for #{variant.name}"
|
25
25
|
end
|
26
26
|
end
|
27
27
|
end
|
@@ -1,8 +1,6 @@
|
|
1
|
-
#
|
2
|
-
|
3
|
-
lib = File.expand_path('../lib/', __FILE__)
|
4
|
-
$:.unshift lib unless $:.include?(lib)
|
1
|
+
# frozen_string_literal: true
|
5
2
|
|
3
|
+
$:.push File.expand_path('lib', __dir__)
|
6
4
|
require 'solidus_product_assembly/version'
|
7
5
|
|
8
6
|
Gem::Specification.new do |s|
|
@@ -11,25 +9,32 @@ Gem::Specification.new do |s|
|
|
11
9
|
s.version = SolidusProductAssembly::VERSION
|
12
10
|
s.summary = 'Adds oportunity to make bundle of products to your Spree store'
|
13
11
|
s.description = s.summary
|
14
|
-
s.
|
12
|
+
s.license = 'BSD-3-Clause'
|
13
|
+
|
14
|
+
s.required_ruby_version = '>= 2.4'
|
15
15
|
|
16
16
|
s.author = 'Roman Smirnov'
|
17
17
|
s.email = 'roman@railsdog.com'
|
18
18
|
s.homepage = 'https://solidus.io'
|
19
19
|
|
20
|
-
s.files
|
21
|
-
|
22
|
-
|
23
|
-
s.
|
24
|
-
|
25
|
-
s.
|
26
|
-
|
27
|
-
|
28
|
-
s.
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
s.
|
34
|
-
s.
|
20
|
+
s.files = Dir.chdir(File.expand_path(__dir__)) do
|
21
|
+
`git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
22
|
+
end
|
23
|
+
s.test_files = Dir['spec/**/*']
|
24
|
+
s.bindir = "exe"
|
25
|
+
s.executables = s.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
26
|
+
s.require_paths = ["lib"]
|
27
|
+
|
28
|
+
if s.respond_to?(:metadata)
|
29
|
+
s.metadata["homepage_uri"] = s.homepage if s.homepage
|
30
|
+
s.metadata["source_code_uri"] = "https://github.com/solidusio-contrib/solidus_product_assembly"
|
31
|
+
end
|
32
|
+
|
33
|
+
s.add_dependency 'deface'
|
34
|
+
s.add_dependency 'solidus_core', ['>= 1.0', '< 4']
|
35
|
+
s.add_dependency 'solidus_support', '~> 0.8'
|
36
|
+
|
37
|
+
s.add_development_dependency 'github_changelog_generator'
|
38
|
+
s.add_development_dependency 'selenium-webdriver'
|
39
|
+
s.add_development_dependency 'solidus_dev_support'
|
35
40
|
end
|
@@ -1,29 +1,127 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'spec_helper'
|
2
4
|
|
3
5
|
describe "Orders", type: :feature, js: true do
|
4
6
|
stub_authorization!
|
5
7
|
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
8
|
+
context 'when the order product is a bundle' do
|
9
|
+
let(:order) { create(:order_with_line_items) }
|
10
|
+
let(:line_item) { order.line_items.first }
|
11
|
+
let(:bundle) { line_item.product }
|
12
|
+
let(:parts) { (1..3).map { create(:variant) } }
|
13
|
+
|
14
|
+
before do
|
15
|
+
bundle.parts << [parts]
|
16
|
+
line_item.update!(quantity: 3)
|
17
|
+
order.reload.create_proposed_shipments
|
18
|
+
order.finalize!
|
19
|
+
end
|
20
|
+
|
21
|
+
if Spree.solidus_gem_version < Gem::Version.new('2.5')
|
22
|
+
context 'Adding tracking number' do
|
23
|
+
let(:tracking_number) { 'AA123' }
|
24
|
+
|
25
|
+
before { visit spree.edit_admin_order_path(order) }
|
26
|
+
|
27
|
+
it 'allows admin to edit tracking' do
|
28
|
+
expect(page).not_to have_content tracking_number
|
29
|
+
within '.show-tracking' do
|
30
|
+
find('.fa-edit').click
|
31
|
+
end
|
32
|
+
within '.edit-tracking' do
|
33
|
+
expect(page).to have_selector 'input[name="tracking"]'
|
34
|
+
fill_in :tracking, with: tracking_number
|
35
|
+
find('.fa-ok').click
|
36
|
+
expect(page).not_to have_selector 'input[name="tracking"]'
|
37
|
+
end
|
38
|
+
expect(page).to have_content tracking_number
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
context 'Changing carrier/shipping costs' do
|
43
|
+
before do
|
44
|
+
visit spree.edit_admin_order_path(order)
|
45
|
+
end
|
10
46
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
47
|
+
it 'allows admin to edit shipping costs' do
|
48
|
+
expect(page).not_to have_content 'UPS Ground $100.00'
|
49
|
+
within '.show-method' do
|
50
|
+
find('.fa-edit').click
|
51
|
+
end
|
52
|
+
within '.edit-method' do
|
53
|
+
find('.fa-ok').click
|
54
|
+
end
|
55
|
+
expect(page).to have_content 'UPS Ground $100.00'
|
56
|
+
end
|
57
|
+
end
|
58
|
+
else
|
59
|
+
context 'Adding tracking number' do
|
60
|
+
let(:tracking_number) { 'AA123' }
|
61
|
+
|
62
|
+
before { visit spree.edit_admin_order_path(order) }
|
63
|
+
|
64
|
+
it 'allows admin to edit tracking' do
|
65
|
+
within '.edit-tracking' do
|
66
|
+
expect(page).not_to have_content tracking_number
|
67
|
+
find('.js-edit').click
|
68
|
+
expect(page).to have_selector 'input[name="tracking"]'
|
69
|
+
fill_in :tracking, with: tracking_number
|
70
|
+
find('.js-save').click
|
71
|
+
expect(page).not_to have_selector 'input[name="tracking"]'
|
72
|
+
expect(page).to have_content tracking_number
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
context 'Changing carrier/shipping costs' do
|
78
|
+
let(:carrier_name) { 'Fedex' }
|
79
|
+
let(:select_name) { 'selected_shipping_method_id' }
|
80
|
+
|
81
|
+
before do
|
82
|
+
create :shipping_method, name: carrier_name
|
83
|
+
visit spree.edit_admin_order_path(order)
|
84
|
+
end
|
85
|
+
|
86
|
+
it 'allows admin to edit shipping costs' do
|
87
|
+
within '.edit-shipping-method' do
|
88
|
+
expect(page).not_to have_content carrier_name
|
89
|
+
find('.js-edit').click
|
90
|
+
expect(page).to have_selector "select[name='#{select_name}']"
|
91
|
+
select "#{carrier_name} $10.00", from: select_name
|
92
|
+
find('.js-save').click
|
93
|
+
expect(page).not_to have_selector "select[name='#{select_name}']"
|
94
|
+
expect(page).to have_content carrier_name
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
16
99
|
end
|
17
100
|
|
18
|
-
|
19
|
-
|
101
|
+
context 'when the order product is not a bundle' do
|
102
|
+
let(:order) { create(:order_ready_to_ship, state: 'complete', line_items_count: 1) }
|
103
|
+
let(:product) { order.products.first }
|
104
|
+
let(:location_name) { 'Foobar warehouse' }
|
105
|
+
|
106
|
+
before { create :stock_location, name: location_name }
|
20
107
|
|
21
|
-
|
22
|
-
|
23
|
-
fill_in "quantity", :with => "2"
|
24
|
-
find(".save-line-item").click
|
108
|
+
context 'Splitting items' do
|
109
|
+
before { visit spree.edit_admin_order_path(order) }
|
25
110
|
|
26
|
-
|
111
|
+
it 'allows admin to split items to another stock location' do
|
112
|
+
find('.split-item').click
|
113
|
+
within '.stock-item-split' do
|
114
|
+
expect(page).to have_content "Move #{product.name} to"
|
115
|
+
find('.save-split').click
|
116
|
+
alert_text = page.driver.browser.switch_to.alert.text
|
117
|
+
expect(alert_text).to include 'Please select the split destination'
|
118
|
+
page.driver.browser.switch_to.alert.accept
|
119
|
+
find('.select2-container').click
|
120
|
+
find(:xpath, '//body').all('.select2-drop li.select2-result', text: "#{location_name} (0 on hand)")[0].click
|
121
|
+
find('.save-split').click
|
122
|
+
end
|
123
|
+
expect(page).to have_content /Pending package from '#{location_name}'/i
|
124
|
+
end
|
27
125
|
end
|
28
126
|
end
|
29
127
|
end
|
@@ -1,10 +1,12 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'spec_helper'
|
2
4
|
|
3
5
|
describe "Parts", type: :feature, js: true do
|
4
6
|
stub_authorization!
|
5
7
|
|
6
|
-
let!(:tshirt) { create(:product, :
|
7
|
-
let!(:mug) { create(:product, :
|
8
|
+
let!(:tshirt) { create(:product, name: "T-Shirt") }
|
9
|
+
let!(:mug) { create(:product, name: "Mug") }
|
8
10
|
|
9
11
|
before do
|
10
12
|
visit spree.admin_product_path(mug)
|
@@ -19,7 +21,7 @@ describe "Parts", type: :feature, js: true do
|
|
19
21
|
click_on "Search"
|
20
22
|
|
21
23
|
within("#search_hits") { click_on "Select" }
|
22
|
-
page.
|
24
|
+
expect(page).to have_content(mug.sku)
|
23
25
|
|
24
26
|
within("#product_parts") do
|
25
27
|
find(".remove_admin_product_part_link").click
|
@@ -0,0 +1,151 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
describe "Return Items", type: :feature, js: true do
|
6
|
+
stub_authorization!
|
7
|
+
|
8
|
+
let(:line_item) { order.line_items.first }
|
9
|
+
|
10
|
+
before do
|
11
|
+
allow_any_instance_of(Spree::Admin::ReimbursementsController).to receive(:try_spree_current_user) { Spree.user_class.new }
|
12
|
+
end
|
13
|
+
|
14
|
+
context 'when the order product is a bundle' do
|
15
|
+
let(:bundle) { line_item.product }
|
16
|
+
let(:parts) { (1..3).map { create(:variant) } }
|
17
|
+
|
18
|
+
before do
|
19
|
+
create :refund_reason, name: Spree::RefundReason::RETURN_PROCESSING_REASON, mutable: false
|
20
|
+
bundle.parts << [parts]
|
21
|
+
bundle.set_part_count(parts.first, 2)
|
22
|
+
parts.each { |p| p.stock_items.first.set_count_on_hand 4 }
|
23
|
+
3.times { order.next }
|
24
|
+
create :payment, order: order, amount: order.amount
|
25
|
+
order.next
|
26
|
+
order.complete
|
27
|
+
order.payments.each(&:capture!)
|
28
|
+
order.shipments.each { |s| s.update state: :ready }
|
29
|
+
order.shipments.each(&:ship!)
|
30
|
+
end
|
31
|
+
|
32
|
+
context 'with a single item cart' do
|
33
|
+
let(:order) { create(:order_with_line_items) }
|
34
|
+
|
35
|
+
it 'successfully generates a RMA, a reimbursement and a refund' do
|
36
|
+
visit spree.edit_admin_order_path(order)
|
37
|
+
|
38
|
+
expect(page).to have_selector '.line-item-total', text: '$10.00'
|
39
|
+
|
40
|
+
click_link 'RMA'
|
41
|
+
click_link 'New RMA'
|
42
|
+
|
43
|
+
expect(page).to have_selector '.return-item-charged', text: '$2.50', count: 4
|
44
|
+
|
45
|
+
find('#select-all').click
|
46
|
+
select Spree::StockLocation.first.name, from: 'Stock Location'
|
47
|
+
click_button 'Create'
|
48
|
+
|
49
|
+
expect(page).to have_content 'Return Authorization has been successfully created!'
|
50
|
+
|
51
|
+
click_link 'Customer Returns'
|
52
|
+
click_link 'New Customer Return'
|
53
|
+
find('#select-all').click
|
54
|
+
page.execute_script %{$('option[value="receive"]').attr('selected', 'selected')}
|
55
|
+
select Spree::StockLocation.first.name, from: 'Stock Location'
|
56
|
+
click_button 'Create'
|
57
|
+
|
58
|
+
expect(page).to have_content 'Customer Return has been successfully created!'
|
59
|
+
|
60
|
+
click_button 'Create reimbursement'
|
61
|
+
click_button 'Reimburse'
|
62
|
+
|
63
|
+
within 'table.reimbursement-refunds' do
|
64
|
+
expect(page).to have_content '$10.00'
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
context 'with a multiple items cart' do
|
70
|
+
let(:order) { create(:order_with_line_items, line_items_attributes: [{ quantity: 2 }]) }
|
71
|
+
|
72
|
+
it 'successfully generates a RMA, a reimbursement and a refund' do
|
73
|
+
visit spree.edit_admin_order_path(order)
|
74
|
+
|
75
|
+
expect(page).to have_selector '.line-item-total', text: '$20.00'
|
76
|
+
|
77
|
+
click_link 'RMA'
|
78
|
+
click_link 'New RMA'
|
79
|
+
|
80
|
+
expect(page).to have_selector '.return-item-charged', text: '$2.50', count: 8
|
81
|
+
|
82
|
+
find('#select-all').click
|
83
|
+
select Spree::StockLocation.first.name, from: 'Stock Location'
|
84
|
+
click_button 'Create'
|
85
|
+
|
86
|
+
expect(page).to have_content 'Return Authorization has been successfully created!'
|
87
|
+
|
88
|
+
click_link 'Customer Returns'
|
89
|
+
click_link 'New Customer Return'
|
90
|
+
find('#select-all').click
|
91
|
+
page.execute_script %{$('option[value="receive"]').attr('selected', 'selected')}
|
92
|
+
select Spree::StockLocation.first.name, from: 'Stock Location'
|
93
|
+
click_button 'Create'
|
94
|
+
|
95
|
+
expect(page).to have_content 'Customer Return has been successfully created!'
|
96
|
+
|
97
|
+
click_button 'Create reimbursement'
|
98
|
+
click_button 'Reimburse'
|
99
|
+
|
100
|
+
within 'table.reimbursement-refunds' do
|
101
|
+
expect(page).to have_content '$20.00'
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
context 'when the product is not a bundle' do
|
108
|
+
before do
|
109
|
+
order.reload.create_proposed_shipments
|
110
|
+
order.finalize!
|
111
|
+
order.update state: :complete
|
112
|
+
order.shipments.update_all state: :shipped
|
113
|
+
end
|
114
|
+
|
115
|
+
context 'with a single item cart' do
|
116
|
+
let(:order) { create(:order_with_line_items) }
|
117
|
+
|
118
|
+
it 'builds one return item for each product' do
|
119
|
+
visit spree.edit_admin_order_path(order)
|
120
|
+
|
121
|
+
expect(page).to have_selector '.item-total', text: '$10.00'
|
122
|
+
|
123
|
+
click_link 'RMA'
|
124
|
+
click_link 'New RMA'
|
125
|
+
|
126
|
+
within '.return-items-table tbody' do
|
127
|
+
expect(page).to have_selector 'tr', count: 1
|
128
|
+
expect(page).to have_selector '.return-item-pre-tax-refund-amount', text: '$10.00', count: 1
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
context 'with a multiple items cart' do
|
134
|
+
let(:order) { create(:order_with_line_items, line_items_attributes: [{ quantity: 2 }]) }
|
135
|
+
|
136
|
+
it 'builds one return item for each product' do
|
137
|
+
visit spree.edit_admin_order_path(order)
|
138
|
+
|
139
|
+
expect(page).to have_selector '.item-total', text: '$20.00'
|
140
|
+
|
141
|
+
click_link 'RMA'
|
142
|
+
click_link 'New RMA'
|
143
|
+
|
144
|
+
within '.return-items-table tbody' do
|
145
|
+
expect(page).to have_selector 'tr', count: 2
|
146
|
+
expect(page).to have_selector '.return-item-pre-tax-refund-amount', text: '$10.00', count: 2
|
147
|
+
end
|
148
|
+
end
|
149
|
+
end
|
150
|
+
end
|
151
|
+
end
|
@@ -1,48 +1,51 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'spec_helper'
|
2
4
|
|
3
5
|
describe "Checkout", type: :feature do
|
4
6
|
let!(:store) { create :store, default: true }
|
5
|
-
let!(:country) { create(:country, :
|
6
|
-
let!(:state) { create(:state, :
|
7
|
+
let!(:country) { create(:country, name: "United States", states_required: true) }
|
8
|
+
let!(:state) { create(:state, name: "Ohio", country: country) }
|
7
9
|
let!(:shipping_method) { create(:shipping_method) }
|
8
10
|
let!(:stock_location) { create(:stock_location) }
|
9
11
|
let!(:payment_method) { create(:check_payment_method) }
|
10
12
|
let!(:zone) { create(:zone) }
|
11
13
|
|
12
|
-
let(:product) { create(:product, :
|
14
|
+
let(:product) { create(:product, name: "RoR Mug") }
|
13
15
|
let(:variant) { create(:variant) }
|
16
|
+
let(:other_variant) { create(:variant) }
|
14
17
|
|
15
18
|
stub_authorization!
|
16
19
|
|
17
|
-
before { product.parts << variant <<
|
20
|
+
before { product.parts << variant << other_variant }
|
18
21
|
|
19
22
|
shared_context "purchases product with part included" do
|
20
23
|
before do
|
24
|
+
visit spree.root_path
|
21
25
|
add_product_to_cart
|
22
26
|
click_button "Checkout"
|
23
27
|
|
24
|
-
fill_in "order_email", :
|
28
|
+
fill_in "order_email", with: "ryan@spreecommerce.com"
|
25
29
|
click_button "Continue"
|
26
30
|
fill_in_address
|
27
31
|
|
28
32
|
click_button "Save and Continue"
|
29
33
|
expect(current_path).to eql(spree.checkout_state_path("delivery"))
|
30
|
-
page.
|
34
|
+
expect(page).to have_content(variant.product.name)
|
31
35
|
|
32
36
|
click_button "Save and Continue"
|
33
37
|
expect(current_path).to eql(spree.checkout_state_path("payment"))
|
34
38
|
|
35
39
|
click_button "Save and Continue"
|
36
|
-
expect(
|
37
|
-
page.
|
40
|
+
expect(page).to have_current_path spree.checkout_state_path('confirm'), ignore_query: true
|
41
|
+
expect(page).to have_content(variant.product.name)
|
38
42
|
|
39
43
|
click_button "Place Order"
|
40
|
-
page.
|
44
|
+
expect(page).to have_content('Your order has been processed successfully')
|
41
45
|
end
|
42
46
|
end
|
43
47
|
|
44
|
-
|
45
|
-
|
48
|
+
shared_examples 'purchasable assembly' do
|
46
49
|
context "ordering only the product assembly" do
|
47
50
|
include_context "purchases product with part included"
|
48
51
|
|
@@ -50,7 +53,7 @@ describe "Checkout", type: :feature do
|
|
50
53
|
visit spree.admin_orders_path
|
51
54
|
click_on Spree::Order.last.number
|
52
55
|
|
53
|
-
page.
|
56
|
+
expect(page).to have_content(variant.product.name)
|
54
57
|
end
|
55
58
|
end
|
56
59
|
|
@@ -60,28 +63,107 @@ describe "Checkout", type: :feature do
|
|
60
63
|
click_link variant.product.name
|
61
64
|
click_button "add-to-cart-button"
|
62
65
|
end
|
66
|
+
|
63
67
|
include_context "purchases product with part included"
|
64
68
|
|
65
69
|
it "views parts bundled and not" do
|
66
70
|
visit spree.admin_orders_path
|
67
71
|
click_on Spree::Order.last.number
|
68
72
|
|
69
|
-
page.
|
73
|
+
expect(page).to have_content(variant.product.name)
|
70
74
|
end
|
71
75
|
end
|
72
|
-
|
73
76
|
end
|
74
77
|
|
78
|
+
context "backend order shipments UI", js: true do
|
79
|
+
context 'when the product and parts are backorderable' do
|
80
|
+
it_behaves_like 'purchasable assembly'
|
81
|
+
end
|
82
|
+
|
83
|
+
context 'when the product and parts are not backorderable' do
|
84
|
+
context 'when there is enough quantity available' do
|
85
|
+
before do
|
86
|
+
Spree::StockItem.update_all backorderable: false
|
87
|
+
variant.stock_items.each { |stock_item| stock_item.set_count_on_hand 2 }
|
88
|
+
other_variant.stock_items.each { |stock_item| stock_item.set_count_on_hand 1 }
|
89
|
+
product.stock_items.each { |stock_item| stock_item.set_count_on_hand 1 }
|
90
|
+
end
|
91
|
+
|
92
|
+
it_behaves_like 'purchasable assembly'
|
93
|
+
|
94
|
+
context 'when the order can be processed' do
|
95
|
+
include_context "purchases product with part included"
|
96
|
+
|
97
|
+
before do
|
98
|
+
visit spree.admin_orders_path
|
99
|
+
click_on Spree::Order.last.number
|
100
|
+
end
|
101
|
+
|
102
|
+
it 'marks the order as paid and shipped showing proper parts information' do
|
103
|
+
within '#order_tab_summary' do
|
104
|
+
expect(page).to have_selector '#shipment_status', text: 'Pending'
|
105
|
+
expect(page).to have_selector '#payment_status', text: 'Balance due'
|
106
|
+
end
|
107
|
+
|
108
|
+
click_link 'Payments'
|
109
|
+
find('.fa-capture').click
|
110
|
+
|
111
|
+
within '#order_tab_summary' do
|
112
|
+
expect(page).to have_selector '#shipment_status', text: 'Ready'
|
113
|
+
expect(page).to have_selector '#payment_status', text: 'Paid'
|
114
|
+
end
|
115
|
+
|
116
|
+
click_link 'Shipments'
|
117
|
+
|
118
|
+
within '.stock-contents' do
|
119
|
+
expect(page).to have_selector '.item-price', text: '---'
|
120
|
+
expect(page).to have_selector '.item-total', text: '---'
|
121
|
+
expect(page).to have_selector '.item-qty-show', count: 2, text: '1 x on hand'
|
122
|
+
end
|
123
|
+
|
124
|
+
expect(page).not_to have_selector '.stock-contents.carton'
|
125
|
+
|
126
|
+
click_button 'Ship'
|
127
|
+
|
128
|
+
within '.stock-contents' do
|
129
|
+
expect(page).to have_selector '.item-qty-show', count: 2, text: '1 x Shipped'
|
130
|
+
end
|
131
|
+
|
132
|
+
within '.stock-contents.carton' do
|
133
|
+
expect(page).to have_selector '.item-qty-show', count: 2, text: '1 x Shipped'
|
134
|
+
expect(page).to have_selector '.item-price', text: '---'
|
135
|
+
expect(page).to have_selector '.item-total', text: '---'
|
136
|
+
end
|
137
|
+
|
138
|
+
within '#order_tab_summary' do
|
139
|
+
expect(page).to have_selector '#shipment_status', text: 'Shipped'
|
140
|
+
expect(page).to have_selector '#payment_status', text: 'Paid'
|
141
|
+
end
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end
|
145
|
+
end
|
146
|
+
end
|
75
147
|
|
76
148
|
def fill_in_address
|
77
149
|
address = "order_bill_address_attributes"
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
150
|
+
|
151
|
+
if use_address_full_name?
|
152
|
+
fill_in "#{address}_name", with: "Ryan Bigg"
|
153
|
+
else
|
154
|
+
fill_in "#{address}_firstname", with: "Ryan"
|
155
|
+
fill_in "#{address}_lastname", with: "Bigg"
|
156
|
+
end
|
157
|
+
|
158
|
+
fill_in "#{address}_address1", with: "143 Swan Street"
|
159
|
+
fill_in "#{address}_city", with: "Richmond"
|
160
|
+
select "Ohio", from: "#{address}_state_id"
|
161
|
+
fill_in "#{address}_zipcode", with: "12345"
|
162
|
+
fill_in "#{address}_phone", with: "(555) 555-5555"
|
163
|
+
end
|
164
|
+
|
165
|
+
def use_address_full_name?
|
166
|
+
SolidusSupport.combined_first_and_last_name_in_address?
|
85
167
|
end
|
86
168
|
|
87
169
|
def add_product_to_cart
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'spec_helper'
|
2
4
|
|
3
5
|
module Spree
|
@@ -11,7 +13,7 @@ module Spree
|
|
11
13
|
|
12
14
|
context "get" do
|
13
15
|
it "brings part by product and variant id" do
|
14
|
-
subject.class.get(product.id, variant.id).part.
|
16
|
+
expect(subject.class.get(product.id, variant.id).part).to eq variant
|
15
17
|
end
|
16
18
|
end
|
17
19
|
end
|
@@ -1,16 +1,25 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'spec_helper'
|
2
4
|
|
3
5
|
module Spree
|
4
6
|
describe InventoryUnit do
|
7
|
+
subject { described_class.create!(attributes) }
|
8
|
+
|
5
9
|
let!(:order) { create(:order_with_line_items) }
|
6
10
|
let(:line_item) { order.line_items.first }
|
7
11
|
let(:product) { line_item.product }
|
12
|
+
let(:shipment) { create(:shipment, order: order) }
|
8
13
|
|
9
|
-
|
14
|
+
if Spree.solidus_gem_version < Gem::Version.new('2.5.x')
|
15
|
+
let(:attributes) { { shipment: shipment, line_item: line_item, variant: line_item.variant, order: order } }
|
16
|
+
else
|
17
|
+
let(:attributes) { { shipment: shipment, line_item: line_item, variant: line_item.variant } }
|
18
|
+
end
|
10
19
|
|
11
|
-
context 'if the unit is not part of an assembly' do
|
12
|
-
it '
|
13
|
-
expect(subject.percentage_of_line_item).to eql(BigDecimal
|
20
|
+
context 'if the unit is not part of an assembly' do
|
21
|
+
it 'will return the percentage of a line item' do
|
22
|
+
expect(subject.percentage_of_line_item).to eql(BigDecimal(1))
|
14
23
|
end
|
15
24
|
end
|
16
25
|
|
@@ -23,9 +32,9 @@ module Spree
|
|
23
32
|
order.finalize!
|
24
33
|
end
|
25
34
|
|
26
|
-
it '
|
35
|
+
it 'will return the percentage of a line item' do
|
27
36
|
subject.line_item = line_item
|
28
|
-
|
37
|
+
expect(subject.percentage_of_line_item).to eql(BigDecimal(0.5, 2))
|
29
38
|
end
|
30
39
|
end
|
31
40
|
end
|