spree_multi_vendor 2.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (124) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +21 -0
  3. data/.rspec +3 -0
  4. data/.travis.yml +44 -0
  5. data/Appraisals +11 -0
  6. data/Gemfile +7 -0
  7. data/LICENSE +26 -0
  8. data/README.md +166 -0
  9. data/Rakefile +21 -0
  10. data/app/controllers/spree/admin/vendor_settings_controller.rb +34 -0
  11. data/app/controllers/spree/admin/vendors_controller.rb +60 -0
  12. data/app/controllers/spree/api/v2/storefront/vendors_controller.rb +28 -0
  13. data/app/controllers/spree_multi_vendor/spree/admin/base_controller_decorator.rb +10 -0
  14. data/app/controllers/spree_multi_vendor/spree/admin/option_types_controller_decorator.rb +7 -0
  15. data/app/controllers/spree_multi_vendor/spree/admin/products_controller_decorator.rb +24 -0
  16. data/app/controllers/spree_multi_vendor/spree/admin/properties_controller_decorator.rb +7 -0
  17. data/app/controllers/spree_multi_vendor/spree/admin/resource_controller_decorator.rb +8 -0
  18. data/app/controllers/spree_multi_vendor/spree/admin/shipping_methods_controller_decorator.rb +7 -0
  19. data/app/controllers/spree_multi_vendor/spree/admin/stock_locations_controller_decorator.rb +7 -0
  20. data/app/controllers/spree_multi_vendor/spree/admin/users_controller_decorator.rb +13 -0
  21. data/app/controllers/spree_multi_vendor/spree/admin/variants_controller_decorator.rb +7 -0
  22. data/app/controllers/spree_multi_vendor/spree/api/v1/variants_controller_decorator.rb +22 -0
  23. data/app/finders/spree_multi_vendor/products_finder_decorator.rb +31 -0
  24. data/app/helpers/spree/admin/vendor_helper.rb +15 -0
  25. data/app/mailers/spree/vendor_mailer.rb +15 -0
  26. data/app/models/concerns/spree/vendor_concern.rb +11 -0
  27. data/app/models/spree/order_commission.rb +11 -0
  28. data/app/models/spree/vendor.rb +77 -0
  29. data/app/models/spree/vendor_ability.rb +140 -0
  30. data/app/models/spree/vendor_image.rb +18 -0
  31. data/app/models/spree/vendor_order_totals.rb +28 -0
  32. data/app/models/spree/vendor_user.rb +16 -0
  33. data/app/models/spree_multi_vendor/configuration.rb +10 -0
  34. data/app/models/spree_multi_vendor/spree/ability_decorator.rb +9 -0
  35. data/app/models/spree_multi_vendor/spree/base_decorator.rb +13 -0
  36. data/app/models/spree_multi_vendor/spree/line_item_decorator.rb +48 -0
  37. data/app/models/spree_multi_vendor/spree/order_decorator.rb +105 -0
  38. data/app/models/spree_multi_vendor/spree/shipment_decorator.rb +8 -0
  39. data/app/models/spree_multi_vendor/spree/stock/package_decorator.rb +14 -0
  40. data/app/models/spree_multi_vendor/spree/user_decorator.rb +8 -0
  41. data/app/models/spree_multi_vendor/spree/variant_decorator.rb +41 -0
  42. data/app/overrides/spree/admin/orders/_form.rb +13 -0
  43. data/app/overrides/spree/admin/orders/_line_items.rb +6 -0
  44. data/app/overrides/spree/admin/orders/_line_items_edit_form.rb +6 -0
  45. data/app/overrides/spree/admin/orders/index.rb +6 -0
  46. data/app/overrides/spree/admin/products/form.rb +29 -0
  47. data/app/overrides/spree/admin/products/new.rb +16 -0
  48. data/app/overrides/spree/admin/shared/_main_menu.rb +23 -0
  49. data/app/overrides/spree/admin/shared/_order_summary.rb +35 -0
  50. data/app/overrides/spree/admin/users/_form.rb +13 -0
  51. data/app/serializers/spree/v2/storefront/vendor_image_serializer.rb +11 -0
  52. data/app/serializers/spree/v2/storefront/vendor_order_totals_serializer.rb +18 -0
  53. data/app/serializers/spree/v2/storefront/vendor_serializer.rb +14 -0
  54. data/app/serializers/spree_multi_vendor/cart_serializer_decorator.rb +19 -0
  55. data/app/serializers/spree_multi_vendor/serializer_decorator.rb +23 -0
  56. data/app/services/spree/orders/generate_commissions.rb +34 -0
  57. data/app/views/spree/admin/translations/vendor.html.erb +21 -0
  58. data/app/views/spree/admin/vendor_settings/edit.html.erb +47 -0
  59. data/app/views/spree/admin/vendors/_form.html.erb +36 -0
  60. data/app/views/spree/admin/vendors/edit.html.erb +11 -0
  61. data/app/views/spree/admin/vendors/index.html.erb +83 -0
  62. data/app/views/spree/admin/vendors/new.html.erb +11 -0
  63. data/app/views/spree/vendor_mailer/vendor_notification_email.html.erb +81 -0
  64. data/app/views/spree/vendor_mailer/vendor_notification_email.text.erb +36 -0
  65. data/bin/rails +7 -0
  66. data/config/initializers/spree_permitted_attributes.rb +10 -0
  67. data/config/locales/en.yml +34 -0
  68. data/config/locales/es.yml +33 -0
  69. data/config/locales/fr.yml +33 -0
  70. data/config/routes.rb +19 -0
  71. data/db/default/vendors.rb +13 -0
  72. data/db/migrate/20170406102250_create_spree_vendors.rb +9 -0
  73. data/db/migrate/20170406102944_add_vendor_id_to_spree_models.rb +10 -0
  74. data/db/migrate/20170410111150_add_state_to_vendors.rb +6 -0
  75. data/db/migrate/20170412124925_add_deleted_at_to_spree_vendors.rb +6 -0
  76. data/db/migrate/20170413094447_create_spree_vendor_users.rb +11 -0
  77. data/db/migrate/20190212161426_add_slug_to_spree_vendors.rb +6 -0
  78. data/db/migrate/20190214120226_add_about_us_to_spree_vendors.rb +5 -0
  79. data/db/migrate/20190214142526_add_contact_us_to_spree_vendors.rb +5 -0
  80. data/db/migrate/20190305120337_add_commission_to_spree_vendors.rb +5 -0
  81. data/db/migrate/20190308091546_add_priority_to_vendor.rb +8 -0
  82. data/db/migrate/20190312130754_create_spree_order_commissions.rb +14 -0
  83. data/db/migrate/20190322133128_add_notification_email_to_vendors.rb +5 -0
  84. data/db/migrate/20200416030721_add_translations_to_vendor.rb +19 -0
  85. data/gemfiles/spree_4_2.gemfile +9 -0
  86. data/gemfiles/spree_master.gemfile +9 -0
  87. data/lib/generators/spree_multi_vendor/install/install_generator.rb +21 -0
  88. data/lib/generators/spree_multi_vendor/mailers_preview/mailers_preview_generator.rb +22 -0
  89. data/lib/generators/spree_multi_vendor/mailers_preview/templates/mailers/previews/vendor_notification_preview.rb +5 -0
  90. data/lib/spree_multi_vendor.rb +14 -0
  91. data/lib/spree_multi_vendor/engine.rb +24 -0
  92. data/lib/spree_multi_vendor/factories.rb +7 -0
  93. data/lib/spree_multi_vendor/version.rb +11 -0
  94. data/lib/tasks/vendors.rake +8 -0
  95. data/spec/factories/spree/vendor_factory.rb +22 -0
  96. data/spec/factories/spree/vendor_image_factory.rb +5 -0
  97. data/spec/factories/spree/vendor_user_factory.rb +6 -0
  98. data/spec/features/spree/admin/orders_spec.rb +36 -0
  99. data/spec/features/spree/admin/product_spec.rb +177 -0
  100. data/spec/features/spree/admin/shipping_method_spec.rb +72 -0
  101. data/spec/features/spree/admin/stock_location_spec.rb +90 -0
  102. data/spec/features/spree/admin/vendor_settings_spec.rb +76 -0
  103. data/spec/features/spree/admin/vendor_spec.rb +125 -0
  104. data/spec/fixtures/thinking-cat.jpg +0 -0
  105. data/spec/mailers/vendor_mailer_spec.rb +45 -0
  106. data/spec/models/spree/line_item_spec.rb +32 -0
  107. data/spec/models/spree/order_commission_spec.rb +8 -0
  108. data/spec/models/spree/order_spec.rb +179 -0
  109. data/spec/models/spree/product_spec.rb +19 -0
  110. data/spec/models/spree/variant_spec.rb +104 -0
  111. data/spec/models/spree/vendor_order_totals_spec.rb +33 -0
  112. data/spec/models/spree/vendor_spec.rb +57 -0
  113. data/spec/models/spree/vendor_user_spec.rb +12 -0
  114. data/spec/requests/spree/api/v2/storefront/cart_spec.rb +67 -0
  115. data/spec/requests/spree/api/v2/storefront/products_spec.rb +93 -0
  116. data/spec/requests/spree/api/v2/storefront/vendors_spec.rb +52 -0
  117. data/spec/serializers/spree/v2/storefront/stock_location_serializer_spec.rb +32 -0
  118. data/spec/serializers/spree/v2/storefront/vendor_image_serializer_spec.rb +18 -0
  119. data/spec/serializers/spree/v2/storefront/vendor_order_totals_serializer_spec.rb +54 -0
  120. data/spec/serializers/spree/v2/storefront/vendor_serializer_spec.rb +34 -0
  121. data/spec/spec_helper.rb +11 -0
  122. data/spec/support/shoulda_matchers.rb +6 -0
  123. data/spree_multi_vendor.gemspec +41 -0
  124. metadata +313 -0
@@ -0,0 +1,76 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.feature 'Admin Vendor Settings', :js do
4
+ let(:vendor) { create(:active_vendor) }
5
+ let(:blocked_vendor) { create(:blocked_vendor)}
6
+ let!(:user) { create(:user, vendors: [vendor]) }
7
+ let!(:user_with_blocked_vendor) { create(:user, vendors: [blocked_vendor]) }
8
+
9
+ context 'edit' do
10
+ background do
11
+ login_as(user, scope: :spree_user)
12
+ visit spree.admin_vendor_settings_path
13
+ end
14
+
15
+ scenario 'can update current vendor' do
16
+ fill_in 'vendor_name', with: 'Testing edit'
17
+ fill_in 'vendor_about_us', with: 'Testing about us edit'
18
+ fill_in 'vendor_contact_us', with: 'Testing contact us edit'
19
+ expect {
20
+ click_button 'Update'
21
+ }.to change { vendor.reload.slug }.from('active-vendor').to('testing-edit')
22
+ expect(page).to have_text 'Testing edit'
23
+ expect(page).to have_text 'Testing about us edit'
24
+ expect(page).to have_text 'Testing contact us edit'
25
+ end
26
+
27
+ scenario 'shows validation error with blank name' do
28
+ fill_in 'vendor_name', with: ''
29
+ click_button 'Update'
30
+ expect(page).to have_text 'name can\'t be blank'
31
+ end
32
+
33
+ scenario 'does not show validation error with blank about_us' do
34
+ fill_in 'vendor_about_us', with: ''
35
+ click_button 'Update'
36
+ expect(page).not_to have_text 'about_us can\'t be blank'
37
+ end
38
+
39
+ scenario 'does not show validation error with blank contact_us' do
40
+ fill_in 'vendor_contact_us', with: ''
41
+ click_button 'Update'
42
+ expect(page).not_to have_text 'contact_us can\'t be blank'
43
+ end
44
+
45
+ if Spree.version.to_f >= 3.6
46
+ scenario 'can update an existing vendor image' do
47
+ create(:vendor, name: 'New vendor')
48
+ page.attach_file("vendor_image", Spree::Core::Engine.root + 'spec/fixtures' + 'thinking-cat.jpg')
49
+ click_button 'Update'
50
+ expect(page).to have_css("img[src*='thinking-cat.jpg']")
51
+ end
52
+ end
53
+ end
54
+
55
+ context 'no vendor present' do
56
+ before do
57
+ vendor.destroy!
58
+ end
59
+
60
+ it 'renders page without errors' do
61
+ visit spree.admin_vendor_settings_path
62
+ expect(page).to have_current_path('/admin/login')
63
+ end
64
+ end
65
+
66
+ context 'blocked vendor present' do
67
+ background do
68
+ login_as(user_with_blocked_vendor, scope: :spree_user)
69
+ end
70
+
71
+ it 'renders forbidden page' do
72
+ visit spree.admin_vendor_settings_path
73
+ expect(current_path).to eq spree.forbidden_path
74
+ end
75
+ end
76
+ end
@@ -0,0 +1,125 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.feature 'Admin Vendors', :js do
4
+ let!(:admin) { create(:admin_user) }
5
+ let!(:vendor_user) { create(:user) }
6
+
7
+ background do
8
+ login_as(admin, scope: :spree_user)
9
+ create(:active_vendor, users: [vendor_user]) if Spree::Vendor.find_by(name: 'Active vendor').nil?
10
+ create(:pending_vendor)
11
+ create(:blocked_vendor)
12
+ visit spree.admin_vendors_path
13
+ end
14
+
15
+ context 'index' do
16
+ scenario 'displays existing vendors' do
17
+ within_row(1) do
18
+ expect(column_text(1)).to eq vendor_user.email
19
+ expect(column_text(2)).to eq 'Active vendor'
20
+ expect(column_text(3)).to eq 'active'
21
+ end
22
+ end
23
+
24
+ scenario 'filter by multiple states' do
25
+ click_button 'Filter'
26
+ select2 'Active', from: 'State'
27
+ select2 'Pending', from: 'State'
28
+
29
+ click_button 'Filter Results'
30
+
31
+ expect(page).to have_content('active')
32
+ expect(page).to have_content('pending')
33
+ expect(page).not_to have_content('blocked')
34
+ end
35
+ end
36
+
37
+ context 'create' do
38
+ scenario 'can create a new vendor' do
39
+ click_link 'New Vendor'
40
+ expect(current_path).to eq spree.new_admin_vendor_path
41
+
42
+ fill_in 'vendor_name', with: 'Test'
43
+ fill_in 'vendor_about_us', with: 'About...'
44
+ fill_in 'vendor_contact_us', with: 'Contact...'
45
+ expect(find_field('vendor_commission_rate').value).to eq '5.0'
46
+ select 'Blocked'
47
+
48
+ click_button 'Create'
49
+
50
+ expect(page).to have_text 'successfully created!'
51
+ expect(current_path).to eq spree.admin_vendors_path
52
+ end
53
+
54
+ scenario 'shows validation error with blank name' do
55
+ click_link 'New Vendor'
56
+ expect(current_path).to eq spree.new_admin_vendor_path
57
+
58
+ fill_in 'vendor_name', with: ''
59
+ click_button 'Create'
60
+
61
+ expect(page).to have_text 'name can\'t be blank'
62
+ end
63
+
64
+ scenario 'shows validation error with repeated name' do
65
+ click_link 'New Vendor'
66
+ expect(current_path).to eq spree.new_admin_vendor_path
67
+
68
+ fill_in 'vendor_name', with: 'Active vendor'
69
+ click_button 'Create'
70
+
71
+ expect(page).to have_text 'name has already been taken'
72
+ end
73
+ end
74
+
75
+ context 'edit' do
76
+ background do
77
+ within_row(1) { click_icon :edit }
78
+ expect(current_path).to eq spree.edit_admin_vendor_path('active-vendor')
79
+ end
80
+
81
+ scenario 'can update an existing vendor' do
82
+ fill_in 'vendor_name', with: 'Testing edit'
83
+ fill_in 'vendor_about_us', with: 'Testing about us'
84
+ fill_in 'vendor_contact_us', with: 'Testing contact us'
85
+ fill_in 'vendor_commission_rate', with: '5.5'
86
+ click_button 'Update'
87
+ expect(page).to have_text 'successfully updated!'
88
+ expect(page).to have_text 'Testing edit'
89
+ end
90
+
91
+ if Spree.version.to_f >= 3.6
92
+ scenario 'can update an existing vendor image' do
93
+ page.attach_file("vendor_image", Spree::Core::Engine.root + 'spec/fixtures' + 'thinking-cat.jpg')
94
+ expect { click_button 'Update' }.to change(Spree::VendorImage, :count).by(1)
95
+ expect(page).to have_text 'successfully updated!'
96
+ end
97
+ end
98
+
99
+ scenario 'shows validation error with blank name' do
100
+ fill_in 'vendor_name', with: ''
101
+ click_button 'Update'
102
+ expect(page).to have_text 'name can\'t be blank'
103
+ end
104
+
105
+ scenario 'does not show validation error with blank about_us' do
106
+ fill_in 'vendor_about_us', with: ''
107
+ click_button 'Update'
108
+ expect(page).not_to have_text 'about_us can\'t be blank'
109
+ end
110
+
111
+ scenario 'does not show validation error with blank contact_us' do
112
+ fill_in 'vendor_contact_us', with: ''
113
+ click_button 'Update'
114
+ expect(page).not_to have_text 'contact_us can\'t be blank'
115
+ end
116
+
117
+ scenario 'shows validation error with repeated name' do
118
+ create(:vendor, name: 'New vendor')
119
+
120
+ fill_in 'vendor_name', with: 'New vendor'
121
+ click_button 'Update'
122
+ expect(page).to have_text 'name has already been taken'
123
+ end
124
+ end
125
+ end
Binary file
@@ -0,0 +1,45 @@
1
+ require 'spec_helper'
2
+
3
+ describe Spree::VendorMailer, type: :mailer do
4
+ let(:store) { create(:store)}
5
+ let(:vendor) { Spree::Vendor.new(id: 1, name: 'Test vendor', state: 'active', notification_email: 'test-vendor@example.com') }
6
+ let(:other_vendor) { Spree::Vendor.new(id: 2, name: 'Other vendor', state: 'active', notification_email: 'other-vendor@example.com') }
7
+ let(:order) { create(:completed_order_with_totals, line_items_count: 5) }
8
+
9
+ context 'vendor notification email' do
10
+ before do
11
+ order.line_items.first.product.update(vendor: vendor)
12
+ order.line_items.last.product.update(vendor: other_vendor)
13
+ end
14
+
15
+ it 'is sent from current store email address' do
16
+ notification_email = Spree::VendorMailer.vendor_notification_email(order.id, vendor.id)
17
+ expect(notification_email.from).to have_content(Spree::Store.current.mail_from_address)
18
+ end
19
+
20
+ it 'is sent to vendors email address' do
21
+ notification_email = Spree::VendorMailer.vendor_notification_email(order.id, vendor.id)
22
+ expect(notification_email.to).to have_content(vendor.contact_us)
23
+ end
24
+
25
+ it 'subject contains order number' do
26
+ notification_email = Spree::VendorMailer.vendor_notification_email(order.id, vendor.id)
27
+ expect(notification_email.subject).to have_content(order.number)
28
+ end
29
+
30
+ it 'body contains vendors items' do
31
+ notification_email = Spree::VendorMailer.vendor_notification_email(order.id, vendor.id)
32
+ vendors_item = order.line_items.select { |line_item| line_item.product.vendor == vendor }.first
33
+ expect(notification_email.body.parts.first).to have_text(vendors_item.product.name)
34
+ expect(notification_email.body.parts.last).to have_text(vendors_item.product.name)
35
+ end
36
+
37
+ it 'body does not contain other vendors items' do
38
+ notification_email = Spree::VendorMailer.vendor_notification_email(order.id, vendor.id)
39
+ other_vendors_item = order.line_items.select { |line_item| line_item.product.vendor != vendor }.first
40
+ expect(notification_email.body.parts.first).not_to have_text(other_vendors_item.product.name)
41
+ expect(notification_email.body.parts.last).not_to have_text(other_vendors_item.product.name)
42
+ end
43
+ end
44
+
45
+ end
@@ -0,0 +1,32 @@
1
+ require 'spec_helper'
2
+
3
+ describe Spree::LineItem do
4
+ let(:vendor) { create(:vendor) }
5
+
6
+ describe '#vendor' do
7
+ context 'vendorized product' do
8
+ let(:product) { create(:product, vendor: vendor) }
9
+ let(:line_item) { build(:line_item, product: product, variant: product.default_variant) }
10
+
11
+ it { expect(line_item.vendor).not_to be_nil }
12
+ it { expect(line_item.vendor).to eq(product.vendor) }
13
+ end
14
+
15
+ context 'vendorized variant' do
16
+ let(:product) { create(:product) }
17
+ let(:variant) { create(:variant, vendor: vendor, product: product) }
18
+ let(:line_item) { build(:line_item, product: product, variant: variant) }
19
+
20
+ before do
21
+ SpreeMultiVendor::Config[:vendorized_models] = ['variant']
22
+ end
23
+
24
+ after do
25
+ SpreeMultiVendor::Config[:vendorized_models] = SpreeMultiVendor::Configuration::DEFAULT_VENDORIZED_MODELS
26
+ end
27
+
28
+ it { expect(line_item.vendor).not_to be_nil }
29
+ it { expect(line_item.vendor).to eq(variant.vendor) }
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,8 @@
1
+ require 'spec_helper'
2
+
3
+ describe Spree::OrderCommission do
4
+ describe 'associations' do
5
+ it { is_expected.to belong_to(:order) }
6
+ it { is_expected.to belong_to(:vendor) }
7
+ end
8
+ end
@@ -0,0 +1,179 @@
1
+ require 'spec_helper'
2
+
3
+ describe Spree::Order do
4
+ let(:vendor) { create(:vendor, name: 'Vendor 1') }
5
+ let(:vendor_2) { create(:vendor, name: 'Vendor 2') }
6
+
7
+ let(:order) { create(:order_with_line_items, state: 'payment', line_items_count: 6, line_items_price: 100, shipment_cost: 50) }
8
+
9
+ before do
10
+ order.line_items.each_with_index do |li, idx|
11
+ product = li.product
12
+ product.vendor = idx.odd? ? vendor : vendor_2
13
+ product.save
14
+ end
15
+ end
16
+
17
+ context 'associations' do
18
+ it { is_expected.to have_many(:commissions) }
19
+ end
20
+
21
+ context 'complete with spree_multi_vendor' do
22
+ before { allow(order).to receive_messages payment_required?: false }
23
+
24
+ it 'generates commission records' do
25
+ expect do
26
+ order.next!
27
+ order.reload
28
+ end.to change { Spree::OrderCommission.count }.by(2).and change { vendor.commissions.count }.by(1)
29
+ .and change { vendor_2.commissions.count }.by(1)
30
+
31
+ order.line_items.includes(product: :vendor).group_by { |li| li.product.vendor }.each do |v, line_items|
32
+ commission_ammount = v.commission_rate * line_items.pluck(:pre_tax_amount).sum.to_f / 100
33
+
34
+ expect(v.commissions.sum(:amount)).to eq(commission_ammount)
35
+ end
36
+ end
37
+ end
38
+
39
+ context 'vendor methods' do
40
+ let!(:shipment) { create(:shipment, order: order, cost: 20, pre_tax_amount: 20, stock_location: vendor.stock_locations.first) }
41
+ let!(:promotion) { create(:promotion_with_item_adjustment, adjustment_rate: 10, code: '10off') }
42
+
43
+ before do
44
+ order.coupon_code = '10off'
45
+ Spree::PromotionHandler::Coupon.new(order).apply
46
+ order.reload
47
+ end
48
+
49
+ describe '#vendor_line_items' do
50
+ it { expect(order.vendor_line_items(vendor)).to eq(order.line_items.for_vendor(vendor)) }
51
+ it { expect(order.vendor_line_items(vendor).count).to eq(3) }
52
+ end
53
+
54
+ describe '#vendor_shipments' do
55
+ it { expect(order.vendor_shipments(vendor).to_a).to eq([shipment]) }
56
+ it { expect(order.vendor_shipments(vendor).count).to eq(1) }
57
+ end
58
+
59
+ describe '#vendor_subtotal' do
60
+ it { expect(order.vendor_subtotal(vendor)).to eq(270) }
61
+ end
62
+
63
+ describe '#display_subtotal' do
64
+ it { expect(order.display_vendor_subtotal(vendor).to_s).to eq('$270.00') }
65
+ end
66
+
67
+ describe '#vendor_pre_tax_item_amount' do
68
+ it { expect(order.vendor_pre_tax_item_amount(vendor)).to eq(300) }
69
+ end
70
+
71
+ describe '#displayvendor_pre_tax_item_amount' do
72
+ it { expect(order.display_vendor_pre_tax_item_amount(vendor).to_s).to eq('$300.00') }
73
+ end
74
+
75
+ describe '#vendor_pre_tax_total' do
76
+ it { expect(order.vendor_pre_tax_total(vendor)).to eq(320) }
77
+ end
78
+
79
+ describe '#displayvendor_pre_tax_total' do
80
+ it { expect(order.display_vendor_pre_tax_total(vendor).to_s).to eq('$320.00') }
81
+ end
82
+
83
+ context 'ship total' do
84
+ before do
85
+ order.vendor_shipments(vendor).update_all(adjustment_total: 5)
86
+ end
87
+
88
+ describe '#vendor_ship_total' do
89
+ it { expect(order.vendor_ship_total(vendor)).to eq(25) }
90
+ end
91
+
92
+ describe '#display_vendor_ship_total' do
93
+ it { expect(order.display_vendor_ship_total(vendor).to_s).to eq('$25.00') }
94
+ end
95
+
96
+ describe '#vendor_pre_tax_ship_amount' do
97
+ it { expect(order.vendor_pre_tax_ship_amount(vendor)).to eq(20) }
98
+ end
99
+
100
+ describe '#display_vendor_pre_tax_ship_amount' do
101
+ it { expect(order.display_vendor_pre_tax_ship_amount(vendor).to_s).to eq('$20.00') }
102
+ end
103
+ end
104
+
105
+ describe '#vendor_promo_total' do
106
+ it { expect(order.vendor_promo_total(vendor)).to eq(-30) }
107
+ end
108
+
109
+ describe '#display_vendor_promo_total' do
110
+ it { expect(order.display_vendor_promo_total(vendor).to_s).to eq('-$30.00') }
111
+ end
112
+
113
+ context 'additional tax' do
114
+ before do
115
+ order.vendor_line_items(vendor).update_all(additional_tax_total: 10)
116
+ order.vendor_shipments(vendor).update_all(additional_tax_total: 1)
117
+ end
118
+
119
+ describe '#vendor_additional_tax_total' do
120
+ it { expect(order.vendor_additional_tax_total(vendor)).to eq(31) }
121
+ end
122
+
123
+ describe '#display_vendor_additional_tax_total' do
124
+ it { expect(order.display_vendor_additional_tax_total(vendor).to_s).to eq('$31.00') }
125
+ end
126
+ end
127
+
128
+ context 'included tax' do
129
+ before do
130
+ order.vendor_line_items(vendor).update_all(included_tax_total: 5)
131
+ order.vendor_shipments(vendor).update_all(included_tax_total: 1)
132
+ end
133
+
134
+ describe '#vendor_included_tax_total' do
135
+ it { expect(order.vendor_included_tax_total(vendor)).to eq(16) }
136
+ end
137
+
138
+ describe '#display_vendor_included_tax_total' do
139
+ it { expect(order.display_vendor_included_tax_total(vendor).to_s).to eq('$16.00') }
140
+ end
141
+ end
142
+
143
+ describe '#vendor_total' do
144
+ it { expect(order.vendor_total(vendor)).to eq(290) }
145
+ end
146
+
147
+ describe '#display_vendor_total' do
148
+ it { expect(order.display_vendor_total(vendor).to_s).to eq('$290.00') }
149
+
150
+ context 'respects currency' do
151
+ before { order.currency = 'GBP' }
152
+
153
+ it { expect(order.display_vendor_total(vendor).to_s).to eq('£290.00') }
154
+ end
155
+ end
156
+
157
+ describe '#vendor_item_count' do
158
+ before { order.vendor_line_items(vendor).last.update(quantity: 2) }
159
+
160
+ it { expect(order.vendor_item_count(vendor)).to eq(4) }
161
+ end
162
+
163
+ describe '#vendor_ids' do
164
+ it { expect(order.vendor_ids).to match_array([vendor.id, vendor_2.id]) }
165
+
166
+ context 'when a line item does not belong to any vendor' do
167
+ before { order.vendor_line_items(vendor_2).each { |li| li.product.update_columns(vendor_id: nil) } }
168
+ it { expect(order.vendor_ids).to match_array([vendor.id]) }
169
+ end
170
+ end
171
+
172
+ describe '#vendor_totals' do
173
+ it { expect(order.vendor_totals).to be_kind_of(Array) }
174
+ it { expect(order.vendor_totals).not_to be_empty }
175
+ it { expect(order.vendor_totals.first.order).to eq(order) }
176
+ it { expect(order.vendor_totals.map(&:vendor)).to match_array([vendor, vendor_2]) }
177
+ end
178
+ end
179
+ end