spree_winkelstraat 3.1.0.20

Sign up to get free protection for your applications and to get access to all the features.
Files changed (47) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +19 -0
  3. data/.rspec +1 -0
  4. data/Gemfile +7 -0
  5. data/LICENSE +26 -0
  6. data/README.md +53 -0
  7. data/Rakefile +21 -0
  8. data/app/assets/javascripts/spree/backend/spree_winkelstraat.js +2 -0
  9. data/app/assets/javascripts/spree/frontend/spree_winkelstraat.js +2 -0
  10. data/app/assets/stylesheets/spree/backend/spree_winkelstraat.css +4 -0
  11. data/app/assets/stylesheets/spree/frontend/spree_winkelstraat.css +4 -0
  12. data/app/controllers/api/v1/orders_controller_decorator.rb +15 -0
  13. data/app/controllers/api/v1/products_controller_decorator.rb +13 -0
  14. data/app/models/spree/order/mail_defuser.rb +15 -0
  15. data/app/models/spree/order_decorator.rb +180 -0
  16. data/app/models/spree/product_decorator.rb +110 -0
  17. data/app/models/spree/promotion/rules/not_winkelstraat_order.rb +18 -0
  18. data/app/models/spree/reimbursement/mail_defuser.rb +9 -0
  19. data/app/models/spree/reimbursement_decorator.rb +5 -0
  20. data/app/models/spree/shipment_handler/mail_defuser.rb +7 -0
  21. data/app/models/spree/shipment_handler_decorator.rb +5 -0
  22. data/app/models/spree/variant_decorator.rb +51 -0
  23. data/app/overrides/option_value_fields.rb +13 -0
  24. data/app/overrides/order_index.rb +13 -0
  25. data/app/overrides/product_form.rb +6 -0
  26. data/app/views/spree/admin/option_types/_extra_option_value_fields.html.erb +1 -0
  27. data/app/views/spree/admin/option_types/_extra_option_value_headers.html.erb +1 -0
  28. data/app/views/spree/admin/orders/_index_tradebyte_state_override.html.erb +7 -0
  29. data/app/views/spree/admin/orders/_index_tradebyte_state_override_head.html.erb +1 -0
  30. data/app/views/spree/admin/products/_sell_on_winkelstraat.html.erb +7 -0
  31. data/app/views/spree/admin/promotions/rules/_not_winkelstraat_order.html.erb +0 -0
  32. data/bin/rails +7 -0
  33. data/config/locales/en.yml +9 -0
  34. data/config/routes.rb +18 -0
  35. data/db/migrate/20190424140108_add_winkelstraat_data.rb +5 -0
  36. data/db/migrate/20190429134248_add_ws_code_to_option_values.rb +5 -0
  37. data/db/migrate/20190501101657_add_winkelstraat_taxons.rb +24 -0
  38. data/db/migrate/20190501122837_add_winkelstraat_payment_method_and_shipping_method.rb +11 -0
  39. data/db/migrate/20190507114902_add_active_on_winkelstraat_to_spree_products.rb +5 -0
  40. data/lib/generators/spree_winkelstraat/install/install_generator.rb +31 -0
  41. data/lib/spree_winkelstraat/engine.rb +26 -0
  42. data/lib/spree_winkelstraat/factories.rb +6 -0
  43. data/lib/spree_winkelstraat/order_importer.rb +65 -0
  44. data/lib/spree_winkelstraat.rb +3 -0
  45. data/spec/spec_helper.rb +93 -0
  46. data/spree_winkelstraat.gemspec +33 -0
  47. metadata +257 -0
@@ -0,0 +1,18 @@
1
+ class Spree::Promotion::Rules::NotWinkelstraatOrder < Spree::PromotionRule
2
+
3
+ def description
4
+ 'Order is not a winkelstraat order'
5
+ end
6
+
7
+ def applicable?(promotable)
8
+ promotable.is_a?(Spree::Order)
9
+ end
10
+
11
+ def eligible?(order, options = {})
12
+ !order.is_winkelstraat_order?
13
+ end
14
+
15
+ def actionable?(line_item)
16
+ !line_item.order.is_winkelstraat_order?
17
+ end
18
+ end
@@ -0,0 +1,9 @@
1
+ module Spree
2
+ module Reimbursement::MailDefuser
3
+
4
+ def send_reimbursement_email
5
+ super unless order.is_winkelstraat_order?
6
+ end
7
+
8
+ end
9
+ end
@@ -0,0 +1,5 @@
1
+ Spree::Reimbursement.class_eval do
2
+
3
+ self.prepend(Spree::Reimbursement::MailDefuser)
4
+
5
+ end
@@ -0,0 +1,7 @@
1
+ module Spree
2
+ module ShipmentHandler::MailDefuser
3
+ def send_shipped_email
4
+ super unless @shipment.order.is_winkelstraat_order?
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,5 @@
1
+ Spree::ShipmentHandler.class_eval do
2
+
3
+ self.prepend(Spree::ShipmentHandler::MailDefuser)
4
+
5
+ end
@@ -0,0 +1,51 @@
1
+ Spree::Variant.class_eval do
2
+
3
+ scope :active_on_winkelstraat, -> {joins(:product).where(spree_products: {sell_on_winkelstraat: true})}
4
+
5
+ delegate :sell_on_winkelstraat, to: :product
6
+
7
+ def self.winkelstraat_stock_csv(stock_location_name = :all)
8
+ stock_location = Spree::StockLocation.find_by_admin_name(stock_location_name) || Spree::StockLocation.find_by_name!(stock_location_name) if stock_location_name != :all
9
+ CSV.generate(headers: false) do |csv|
10
+ size_option_type = Spree::OptionType.includes(:translations).where(spree_option_type_translations: {name: 'size'}).first
11
+ size_option_values = size_option_type.option_values.map do |ov|
12
+ {
13
+ option_value_id: ov.id,
14
+ presentation: ov.presentation
15
+ }
16
+ end
17
+ Spree::Variant.active_on_winkelstraat.active.each do |variant|
18
+ next unless variant.product.available?
19
+ size = size_option_values.detect {|ov| variant.option_values.ids.include?(ov[:option_value_id])}
20
+ csv << [
21
+ variant.sku, #sku
22
+ size.present? ? size.fetch(:presentation) : nil, #maat
23
+ variant.stock_for_stock_location(stock_location) #stock
24
+ ]
25
+ end
26
+ end
27
+ end
28
+
29
+ def in_taxon?(taxon)
30
+ return false if taxon.blank?
31
+ product.taxon_ids.include?(taxon.id)
32
+ end
33
+
34
+ # pass :all for all stock locations
35
+ def stock_for_stock_location(stock_location)
36
+ begin
37
+ if stock_location == :all
38
+ total_on_hand
39
+ else
40
+ stock_items.where(stock_location: stock_location).first.try(:count_on_hand) || 0
41
+ end
42
+ rescue
43
+ 0
44
+ end
45
+ end
46
+
47
+ def kassa_reference
48
+ nil
49
+ end
50
+
51
+ end
@@ -0,0 +1,13 @@
1
+ Deface::Override.new(
2
+ virtual_path: 'spree/admin/option_types/_option_value_fields',
3
+ name: 'add_ws_code_to_option_values',
4
+ insert_before: '[data-hook="option_value"] .actions',
5
+ partial: 'spree/admin/option_types/extra_option_value_fields'
6
+ )
7
+
8
+ Deface::Override.new(
9
+ virtual_path: 'spree/admin/option_types/edit',
10
+ name: 'add_ws_code_to_option_values_headers',
11
+ insert_before: '[data-hook="option_header"] th.actions',
12
+ partial: 'spree/admin/option_types/extra_option_value_headers'
13
+ )
@@ -0,0 +1,13 @@
1
+ Deface::Override.new(
2
+ virtual_path: 'spree/admin/orders/index',
3
+ name: 'add tradebyte order info header',
4
+ insert_after: '#listing_orders thead th:nth-last-child(3)',
5
+ partial: 'spree/admin/orders/index_tradebyte_state_override_head'
6
+ )
7
+
8
+ Deface::Override.new(
9
+ virtual_path: 'spree/admin/orders/index',
10
+ name: 'add tradebyte order info',
11
+ insert_after: '#listing_orders tbody td:nth-last-child(3)',
12
+ partial: 'spree/admin/orders/index_tradebyte_state_override'
13
+ )
@@ -0,0 +1,6 @@
1
+ Deface::Override.new(
2
+ virtual_path: 'spree/admin/products/_form',
3
+ name: 'sell on winkelstraat checkbox',
4
+ insert_after: '[data-hook="admin_product_form_promotionable"]',
5
+ partial: 'spree/admin/products/sell_on_winkelstraat'
6
+ )
@@ -0,0 +1 @@
1
+ <td class="ws_code"><%= f.text_field :ws_code, class: "form-control" %></td>
@@ -0,0 +1 @@
1
+ <th>Winkelstraat code</th>
@@ -0,0 +1,7 @@
1
+ <td>
2
+ <% if order.is_winkelstraat_order? %>
3
+ <span class="label label-success">Winkelstraat order (<%= order.winkelstraat_order_id %>)</span>
4
+ <% else %>
5
+ <span class="label label-success">Regular order</span>
6
+ <% end %>
7
+ </td>
@@ -0,0 +1 @@
1
+ <th><%= sort_link @search, :is_winkelstraat_order?, 'Type' %></th>
@@ -0,0 +1,7 @@
1
+ <div data-hook="admin_product_form_sell_on_winkelstraat">
2
+ <%= f.field_container :sell_on_winkelstraat, class: ['form-group'] do %>
3
+ <%= f.label :sell_on_winkelstraat, 'Sell on winkelstraat' %>
4
+ <%= f.error_message_on :sell_on_winkelstraat %>
5
+ <%= f.check_box :sell_on_winkelstraat, class: 'form-control' %>
6
+ <% end %>
7
+ </div>
data/bin/rails ADDED
@@ -0,0 +1,7 @@
1
+ # This command will automatically be run when you run "rails" with Rails 3 gems installed from the root of your application.
2
+
3
+ ENGINE_ROOT = File.expand_path('../..', __FILE__)
4
+ ENGINE_PATH = File.expand_path('../../lib/spree_winkelstraat/engine', __FILE__)
5
+
6
+ require 'rails/all'
7
+ require 'rails/engine/commands'
@@ -0,0 +1,9 @@
1
+ # Sample localization file for English. Add more files in this directory for other locales.
2
+ # See https://github.com/svenfuchs/rails-i18n/tree/master/rails%2Flocale for starting points.
3
+
4
+ en:
5
+ spree:
6
+ promotion_rule_types:
7
+ not_winkelstraat_order:
8
+ name: "Order is not from winkelstraat"
9
+ description: "The order does not originate from winkelstraat"
data/config/routes.rb ADDED
@@ -0,0 +1,18 @@
1
+ Spree::Core::Engine.routes.draw do
2
+ # Add your extension routes here
3
+
4
+ namespace :api do
5
+ namespace :v1 do
6
+
7
+ resources :products, path: '/ws_product', only: [] do
8
+ get :winkelstraat_stock, on: :collection
9
+ get :winkelstraat_article, on: :collection
10
+ end
11
+
12
+ resources :orders, path: '/ws_order',only: [] do
13
+ post :import, on: :collection
14
+ end
15
+
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,5 @@
1
+ class AddWinkelstraatData < ActiveRecord::Migration
2
+ def change
3
+ add_column :spree_orders, :winkelstraat_order_id, :string
4
+ end
5
+ end
@@ -0,0 +1,5 @@
1
+ class AddWsCodeToOptionValues < ActiveRecord::Migration
2
+ def change
3
+ add_column :spree_option_values, :ws_code, :string
4
+ end
5
+ end
@@ -0,0 +1,24 @@
1
+ class AddWinkelstraatTaxons < ActiveRecord::Migration
2
+
3
+ WOMEN_CATEGORIES = ["Accessoires", "Badmode", "Blazers & Gilets", "Blouses", "Broeken", "Jassen", "Jeans",
4
+ "Jumpsuits", "Jurken", "Lingerie", "Nachtmode", "Rokken", "Schoenen", "Sport", "Tassen", "Tops", "Truien & Vesten"]
5
+ MEN_CATEGORIES = ["Accessoires", "Badmode", "Broeken", "Colberts & Gilets", "Jassen", "Jeans", "Ondergoed",
6
+ "Overhemden", "Schoenen", "Shirts", "Sport", "Truien", "Vesten"]
7
+ KIDS_CATEGORIES = ["Jongens", "Meisjes"]
8
+
9
+ def change
10
+ taxonomy = Spree::Taxonomy.find_or_create_by(name: 'Winkelstraat Category')
11
+
12
+ WOMEN_CATEGORIES.each do |taxon|
13
+ Spree::Taxon.find_or_create_by(name: taxon, taxonomy: taxonomy)
14
+ end
15
+
16
+ MEN_CATEGORIES.each do |taxon|
17
+ Spree::Taxon.find_or_create_by(name: taxon, taxonomy: taxonomy)
18
+ end
19
+
20
+ KIDS_CATEGORIES.each do |taxon|
21
+ Spree::Taxon.find_or_create_by(name: taxon, taxonomy: taxonomy)
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,11 @@
1
+ class AddWinkelstraatPaymentMethodAndShippingMethod < ActiveRecord::Migration
2
+ def change
3
+ Spree::PaymentMethod.find_or_create_by(name: 'Paid at winkelstraat', display_on: :back_end, type: 'Spree::PaymentMethod::Check', active: true)
4
+
5
+ sm = Spree::ShippingMethod.find_or_create_by(name: 'Shipped by winkelstraat', display_on: :back_end, admin_name: 'Winkelstraat shipping')
6
+ sm.zones = Spree::Zone.all
7
+ sm.shipping_categories = [Spree::ShippingCategory.first]
8
+ sm.calculator = Spree::Calculator::Shipping::FlatRate.create(calculable: sm) unless sm.calculator.present?
9
+ sm.save!
10
+ end
11
+ end
@@ -0,0 +1,5 @@
1
+ class AddActiveOnWinkelstraatToSpreeProducts < ActiveRecord::Migration
2
+ def change
3
+ add_column :spree_products, :sell_on_winkelstraat, :boolean, default: false
4
+ end
5
+ end
@@ -0,0 +1,31 @@
1
+ module SpreeWinkelstraat
2
+ module Generators
3
+ class InstallGenerator < Rails::Generators::Base
4
+
5
+ class_option :auto_run_migrations, :type => :boolean, :default => false
6
+
7
+ def add_javascripts
8
+ append_file 'vendor/assets/javascripts/spree/frontend/all.js', "//= require spree/frontend/spree_winkelstraat\n"
9
+ append_file 'vendor/assets/javascripts/spree/backend/all.js', "//= require spree/backend/spree_winkelstraat\n"
10
+ end
11
+
12
+ def add_stylesheets
13
+ inject_into_file 'vendor/assets/stylesheets/spree/frontend/all.css', " *= require spree/frontend/spree_winkelstraat\n", :before => /\*\//, :verbose => true
14
+ inject_into_file 'vendor/assets/stylesheets/spree/backend/all.css', " *= require spree/backend/spree_winkelstraat\n", :before => /\*\//, :verbose => true
15
+ end
16
+
17
+ def add_migrations
18
+ run 'bundle exec rake railties:install:migrations FROM=spree_winkelstraat'
19
+ end
20
+
21
+ def run_migrations
22
+ run_migrations = options[:auto_run_migrations] || ['', 'y', 'Y'].include?(ask 'Would you like to run the migrations now? [Y/n]')
23
+ if run_migrations
24
+ run 'bundle exec rake db:migrate'
25
+ else
26
+ puts 'Skipping rake db:migrate, don\'t forget to run it!'
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,26 @@
1
+ module SpreeWinkelstraat
2
+ class Engine < Rails::Engine
3
+ require 'spree/core'
4
+ isolate_namespace Spree
5
+ engine_name 'spree_winkelstraat'
6
+
7
+ # use rspec for tests
8
+ config.generators do |g|
9
+ g.test_framework :rspec
10
+ end
11
+
12
+ def self.activate
13
+ Dir.glob(File.join(File.dirname(__FILE__), '../../app/**/*_decorator*.rb')) do |c|
14
+ Rails.configuration.cache_classes ? require(c) : load(c)
15
+ end
16
+
17
+ Rails.application.config.spree.promotions.rules << Spree::Promotion::Rules::NotWinkelstraatOrder
18
+ end
19
+
20
+ Spree::PermittedAttributes.option_value_attributes << :ws_code
21
+ Spree::PermittedAttributes.product_attributes << :sell_on_winkelstraat
22
+
23
+
24
+ config.to_prepare &method(:activate).to_proc
25
+ end
26
+ end
@@ -0,0 +1,6 @@
1
+ FactoryGirl.define do
2
+ # Define your Spree extensions Factories within this file to enable applications, and other extensions to use and override them.
3
+ #
4
+ # Example adding this to your spec_helper will load these Factories for use:
5
+ # require 'spree_winkelstraat/factories'
6
+ end
@@ -0,0 +1,65 @@
1
+ class SpreeWinkelstraat::OrderImporter < Spree::Core::Importer::Order
2
+
3
+ def self.import(user, params)
4
+ begin
5
+ ensure_country_id_from_params params[:ship_address_attributes]
6
+ ensure_state_id_from_params params[:ship_address_attributes]
7
+ ensure_country_id_from_params params[:bill_address_attributes]
8
+ ensure_state_id_from_params params[:bill_address_attributes]
9
+
10
+ create_params = params.slice :currency
11
+ order = Spree::Order.create! create_params
12
+ order.associate_user!(user) if user.present?
13
+
14
+ shipments_attrs = params.delete(:shipments_attributes)
15
+
16
+ create_line_items_from_params(params.delete(:line_items_attributes),order)
17
+ create_shipments_from_params(shipments_attrs, order)
18
+ create_adjustments_from_params(params.delete(:adjustments_attributes), order)
19
+ create_payments_from_params(params.delete(:payments_attributes), order)
20
+
21
+ if completed_at = params.delete(:completed_at)
22
+ order.completed_at = completed_at
23
+ order.state = 'complete'
24
+ end
25
+
26
+ params.delete(:user_id) unless user.present? && user.try(:has_spree_role?, "admin") && params.key?(:user_id)
27
+
28
+ order.update_attributes!(params)
29
+
30
+ order.create_proposed_shipments unless shipments_attrs.present?
31
+
32
+ # Really ensure that the order totals & states are correct
33
+ order.updater.update
34
+ if shipments_attrs.present?
35
+ order.shipments.each_with_index do |shipment, index|
36
+ shipment.update_columns(cost: shipments_attrs[index][:cost].to_f) if shipments_attrs[index][:cost].present?
37
+ end
38
+ end
39
+ order.reload
40
+ rescue Exception => e
41
+ order.destroy if order && order.persisted?
42
+ raise e.message
43
+ end
44
+ end
45
+
46
+ def self.create_payments_from_params(payments_hash, order)
47
+ return [] unless payments_hash
48
+ payments_hash.each do |p|
49
+ begin
50
+ payment = order.payments.build order: order
51
+ payment.amount = p.fetch(:amount, order.total)
52
+ # Order API should be using state as that's the normal payment field.
53
+ # spree_wombat serializes payment state as status so imported orders should fall back to status field.
54
+ payment.state = p[:state] || p[:status] || 'completed'
55
+ payment.created_at = p[:created_at] if p[:created_at]
56
+ payment.payment_method = Spree::PaymentMethod.find_by_name!(p[:payment_method])
57
+ payment.source = create_source_payment_from_params(p[:source], payment) if p[:source]
58
+ payment.save!
59
+ rescue Exception => e
60
+ raise "Order import payments: #{e.message} #{p}"
61
+ end
62
+ end
63
+ end
64
+
65
+ end
@@ -0,0 +1,3 @@
1
+ require 'spree_core'
2
+ require 'spree_winkelstraat/engine'
3
+ require 'spree_winkelstraat/order_importer'
@@ -0,0 +1,93 @@
1
+ # Run Coverage report
2
+ require 'simplecov'
3
+ SimpleCov.start do
4
+ add_filter 'spec/dummy'
5
+ add_group 'Controllers', 'app/controllers'
6
+ add_group 'Helpers', 'app/helpers'
7
+ add_group 'Mailers', 'app/mailers'
8
+ add_group 'Models', 'app/models'
9
+ add_group 'Views', 'app/views'
10
+ add_group 'Libraries', 'lib'
11
+ end
12
+
13
+ # Configure Rails Environment
14
+ ENV['RAILS_ENV'] = 'test'
15
+
16
+ require File.expand_path('../dummy/config/environment.rb', __FILE__)
17
+
18
+ require 'rspec/rails'
19
+ require 'database_cleaner'
20
+ require 'ffaker'
21
+
22
+ # Requires supporting ruby files with custom matchers and macros, etc,
23
+ # in spec/support/ and its subdirectories.
24
+ Dir[File.join(File.dirname(__FILE__), 'support/**/*.rb')].each { |f| require f }
25
+
26
+ # Requires factories and other useful helpers defined in spree_core.
27
+ require 'spree/testing_support/authorization_helpers'
28
+ require 'spree/testing_support/capybara_ext'
29
+ require 'spree/testing_support/controller_requests'
30
+ require 'spree/testing_support/factories'
31
+ require 'spree/testing_support/url_helpers'
32
+
33
+ # Requires factories defined in lib/spree_winkelstraat/factories.rb
34
+ require 'spree_winkelstraat/factories'
35
+
36
+ RSpec.configure do |config|
37
+ config.include FactoryGirl::Syntax::Methods
38
+
39
+ # Infer an example group's spec type from the file location.
40
+ config.infer_spec_type_from_file_location!
41
+
42
+ # == URL Helpers
43
+ #
44
+ # Allows access to Spree's routes in specs:
45
+ #
46
+ # visit spree.admin_path
47
+ # current_path.should eql(spree.products_path)
48
+ config.include Spree::TestingSupport::UrlHelpers
49
+
50
+ # == Requests support
51
+ #
52
+ # Adds convenient methods to request Spree's controllers
53
+ # spree_get :index
54
+ config.include Spree::TestingSupport::ControllerRequests, type: :controller
55
+
56
+ # == Mock Framework
57
+ #
58
+ # If you prefer to use mocha, flexmock or RR, uncomment the appropriate line:
59
+ #
60
+ # config.mock_with :mocha
61
+ # config.mock_with :flexmock
62
+ # config.mock_with :rr
63
+ config.mock_with :rspec
64
+ config.color = true
65
+
66
+ # Remove this line if you're not using ActiveRecord or ActiveRecord fixtures
67
+ config.fixture_path = "#{::Rails.root}/spec/fixtures"
68
+
69
+ # Capybara javascript drivers require transactional fixtures set to false, and we use DatabaseCleaner
70
+ # to cleanup after each test instead. Without transactional fixtures set to false the records created
71
+ # to setup a test will be unavailable to the browser, which runs under a separate server instance.
72
+ config.use_transactional_fixtures = false
73
+
74
+ # Ensure Suite is set to use transactions for speed.
75
+ config.before :suite do
76
+ DatabaseCleaner.strategy = :transaction
77
+ DatabaseCleaner.clean_with :truncation
78
+ end
79
+
80
+ # Before each spec check if it is a Javascript test and switch between using database transactions or not where necessary.
81
+ config.before :each do
82
+ DatabaseCleaner.strategy = RSpec.current_example.metadata[:js] ? :truncation : :transaction
83
+ DatabaseCleaner.start
84
+ end
85
+
86
+ # After each spec clean the database.
87
+ config.after :each do
88
+ DatabaseCleaner.clean
89
+ end
90
+
91
+ config.fail_fast = ENV['FAIL_FAST'] || false
92
+ config.order = "random"
93
+ end