solidus_importer 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (100) hide show
  1. checksums.yaml +7 -0
  2. data/.circleci/config.yml +35 -0
  3. data/.gem_release.yml +5 -0
  4. data/.github/stale.yml +17 -0
  5. data/.gitignore +20 -0
  6. data/.hound.yml +8 -0
  7. data/.rspec +2 -0
  8. data/.rubocop.yml +2 -0
  9. data/Gemfile +33 -0
  10. data/LICENSE +26 -0
  11. data/README.md +170 -0
  12. data/Rakefile +6 -0
  13. data/app/assets/javascripts/spree/backend/solidus_importer.js +2 -0
  14. data/app/assets/javascripts/spree/frontend/solidus_importer.js +2 -0
  15. data/app/assets/stylesheets/spree/backend/solidus_importer.css +16 -0
  16. data/app/assets/stylesheets/spree/frontend/solidus_importer.css +4 -0
  17. data/app/controllers/spree/admin/solidus_importer/import_rows_controller.rb +24 -0
  18. data/app/controllers/spree/admin/solidus_importer/imports_controller.rb +44 -0
  19. data/app/jobs/solidus_importer/import_job.rb +30 -0
  20. data/app/models/solidus_importer/import.rb +48 -0
  21. data/app/models/solidus_importer/row.rb +26 -0
  22. data/app/views/spree/admin/solidus_importer/import_rows/show.html.erb +46 -0
  23. data/app/views/spree/admin/solidus_importer/imports/_form.html.erb +14 -0
  24. data/app/views/spree/admin/solidus_importer/imports/index.html.erb +80 -0
  25. data/app/views/spree/admin/solidus_importer/imports/new.html.erb +13 -0
  26. data/app/views/spree/admin/solidus_importer/imports/show.html.erb +87 -0
  27. data/bin/console +17 -0
  28. data/bin/rails +7 -0
  29. data/bin/rails-engine +13 -0
  30. data/bin/rails-sandbox +16 -0
  31. data/bin/rake +7 -0
  32. data/bin/sandbox +84 -0
  33. data/bin/setup +8 -0
  34. data/config/initializers/spree.rb +11 -0
  35. data/config/locales/en.yml +28 -0
  36. data/config/routes.rb +11 -0
  37. data/db/migrate/20191216101011_create_solidus_importer_imports.rb +19 -0
  38. data/db/migrate/20191216101012_create_solidus_importer_rows.rb +14 -0
  39. data/examples/importers/custom_importer.rb +20 -0
  40. data/examples/processors/notify_on_failure.rb +22 -0
  41. data/lib/generators/solidus_importer/install/install_generator.rb +22 -0
  42. data/lib/solidus_importer.rb +25 -0
  43. data/lib/solidus_importer/base_importer.rb +26 -0
  44. data/lib/solidus_importer/configuration.rb +39 -0
  45. data/lib/solidus_importer/engine.rb +23 -0
  46. data/lib/solidus_importer/exception.rb +5 -0
  47. data/lib/solidus_importer/factories.rb +4 -0
  48. data/lib/solidus_importer/process_import.rb +88 -0
  49. data/lib/solidus_importer/process_row.rb +46 -0
  50. data/lib/solidus_importer/processors/address.rb +47 -0
  51. data/lib/solidus_importer/processors/base.rb +15 -0
  52. data/lib/solidus_importer/processors/customer.rb +41 -0
  53. data/lib/solidus_importer/processors/log.rb +15 -0
  54. data/lib/solidus_importer/processors/option_types.rb +43 -0
  55. data/lib/solidus_importer/processors/option_values.rb +49 -0
  56. data/lib/solidus_importer/processors/order.rb +40 -0
  57. data/lib/solidus_importer/processors/product.rb +51 -0
  58. data/lib/solidus_importer/processors/product_images.rb +30 -0
  59. data/lib/solidus_importer/processors/taxon.rb +52 -0
  60. data/lib/solidus_importer/processors/variant.rb +51 -0
  61. data/lib/solidus_importer/processors/variant_images.rb +30 -0
  62. data/lib/solidus_importer/version.rb +5 -0
  63. data/solidus_importer.gemspec +36 -0
  64. data/spec/factories/solidus_importer_imports.rb +27 -0
  65. data/spec/factories/solidus_importer_rows.rb +82 -0
  66. data/spec/features/admin/solidus_importer/import_rows_spec.rb +30 -0
  67. data/spec/features/admin/solidus_importer/imports_spec.rb +121 -0
  68. data/spec/features/solidus_importer/import_spec.rb +138 -0
  69. data/spec/features/solidus_importer/processors_spec.rb +53 -0
  70. data/spec/fixtures/solidus_importer/apparel.csv +23 -0
  71. data/spec/fixtures/solidus_importer/customers.csv +3 -0
  72. data/spec/fixtures/solidus_importer/home-and-garden.csv +22 -0
  73. data/spec/fixtures/solidus_importer/invalid_headers.csv +3 -0
  74. data/spec/fixtures/solidus_importer/invalid_product.csv +2 -0
  75. data/spec/fixtures/solidus_importer/jewelery.csv +55 -0
  76. data/spec/fixtures/solidus_importer/orders.csv +5 -0
  77. data/spec/fixtures/solidus_importer/products.csv +8 -0
  78. data/spec/fixtures/solidus_importer/thinking-cat.jpg +0 -0
  79. data/spec/jobs/solidus_importer/import_job_spec.rb +54 -0
  80. data/spec/lib/solidus_importer/base_importer_spec.rb +23 -0
  81. data/spec/lib/solidus_importer/process_import_spec.rb +74 -0
  82. data/spec/lib/solidus_importer/process_row_spec.rb +24 -0
  83. data/spec/lib/solidus_importer/processors/address_spec.rb +18 -0
  84. data/spec/lib/solidus_importer/processors/base_spec.rb +9 -0
  85. data/spec/lib/solidus_importer/processors/customer_spec.rb +65 -0
  86. data/spec/lib/solidus_importer/processors/log_spec.rb +18 -0
  87. data/spec/lib/solidus_importer/processors/option_types_spec.rb +38 -0
  88. data/spec/lib/solidus_importer/processors/option_values_spec.rb +43 -0
  89. data/spec/lib/solidus_importer/processors/order_spec.rb +56 -0
  90. data/spec/lib/solidus_importer/processors/product_images_spec.rb +42 -0
  91. data/spec/lib/solidus_importer/processors/product_spec.rb +66 -0
  92. data/spec/lib/solidus_importer/processors/taxon_spec.rb +33 -0
  93. data/spec/lib/solidus_importer/processors/variant_images_spec.rb +44 -0
  94. data/spec/lib/solidus_importer/processors/variant_spec.rb +86 -0
  95. data/spec/lib/solidus_importer_spec.rb +14 -0
  96. data/spec/models/solidus_importer/import_spec.rb +60 -0
  97. data/spec/models/solidus_importer/row_spec.rb +18 -0
  98. data/spec/spec_helper.rb +27 -0
  99. data/spec/support/solidus_importer_helpers.rb +13 -0
  100. metadata +227 -0
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 3c368dcdb23d45c02c54cd01f247debce0e9083119bda2dc1f358a0718e3b7d8
4
+ data.tar.gz: 4336a3ad45dc07ba7e6aa5d0e12a953242439a8698c3b8c6a0b36a175e38384d
5
+ SHA512:
6
+ metadata.gz: 0a3de867687407c132ffe9444a4a1e3b5913dcde1cedabc3b28353bac061f9822bd87ce66fba277904ca20a9c63cfeb8854edadcc37cbff3a9852b80092066c2
7
+ data.tar.gz: e32d1dc88ccc3db3a234223d0149514aa8173b163f940ada667e43e128a74802d4e2331ec41a7773694ba0cc744051390756c76f22eb2cad7c09504e3fc9c4cd
@@ -0,0 +1,35 @@
1
+ version: 2.1
2
+
3
+ orbs:
4
+ # Always take the latest version of the orb, this allows us to
5
+ # run specs against Solidus supported versions only without the need
6
+ # to change this configuration every time a Solidus version is released
7
+ # or goes EOL.
8
+ solidusio_extensions: solidusio/extensions@volatile
9
+
10
+ jobs:
11
+ run-specs-with-postgres:
12
+ executor: solidusio_extensions/postgres
13
+ steps:
14
+ - solidusio_extensions/run-tests
15
+ run-specs-with-mysql:
16
+ executor: solidusio_extensions/mysql
17
+ steps:
18
+ - solidusio_extensions/run-tests
19
+
20
+ workflows:
21
+ "Run specs on supported Solidus versions":
22
+ jobs:
23
+ - run-specs-with-postgres
24
+ - run-specs-with-mysql
25
+ "Weekly run specs against master":
26
+ triggers:
27
+ - schedule:
28
+ cron: "0 0 * * 4" # every Thursday
29
+ filters:
30
+ branches:
31
+ only:
32
+ - master
33
+ jobs:
34
+ - run-specs-with-postgres
35
+ - run-specs-with-mysql
@@ -0,0 +1,5 @@
1
+ bump:
2
+ recurse: false
3
+ file: 'lib/solidus_importer/version.rb'
4
+ message: Bump SolidusImporter to %{version}
5
+ tag: true
@@ -0,0 +1,17 @@
1
+ # Number of days of inactivity before an issue becomes stale
2
+ daysUntilStale: 60
3
+ # Number of days of inactivity before a stale issue is closed
4
+ daysUntilClose: 7
5
+ # Issues with these labels will never be considered stale
6
+ exemptLabels:
7
+ - pinned
8
+ - security
9
+ # Label to use when marking an issue as stale
10
+ staleLabel: wontfix
11
+ # Comment to post when marking an issue as stale. Set to `false` to disable
12
+ markComment: >
13
+ This issue has been automatically marked as stale because it has not had
14
+ recent activity. It will be closed if no further activity occurs. Thank you
15
+ for your contributions.
16
+ # Comment to post when closing a stale issue. Set to `false` to disable
17
+ closeComment: false
@@ -0,0 +1,20 @@
1
+ *.gem
2
+ \#*
3
+ *~
4
+ .#*
5
+ .DS_Store
6
+ .idea
7
+ .project
8
+ .sass-cache
9
+ coverage
10
+ Gemfile.lock
11
+ tmp
12
+ nbproject
13
+ pkg
14
+ *.swp
15
+ spec/dummy
16
+ spec/examples.txt
17
+ /sandbox
18
+ .rvmrc
19
+ .ruby-version
20
+ .ruby-gemset
@@ -0,0 +1,8 @@
1
+ fail_on_violations: true
2
+
3
+ rubocop:
4
+ config_file: .rubocop.yml
5
+ version: 0.75.0
6
+
7
+ scss:
8
+ enabled: false
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --require spec_helper
@@ -0,0 +1,2 @@
1
+ require:
2
+ - solidus_dev_support/rubocop
data/Gemfile ADDED
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ source 'https://rubygems.org'
4
+ git_source(:github) { |repo| "https://github.com/#{repo}.git" }
5
+
6
+ branch = ENV.fetch('SOLIDUS_BRANCH', 'master')
7
+ gem 'solidus', github: 'solidusio/solidus', branch: branch
8
+
9
+ # Needed to help Bundler figure out how to resolve dependencies,
10
+ # otherwise it takes forever to resolve them.
11
+ # See https://github.com/bundler/bundler/issues/6677
12
+ gem 'rails', '>0.a'
13
+
14
+ # Provides basic authentication functionality for testing parts of your engine
15
+ gem 'solidus_auth_devise'
16
+
17
+ case ENV['DB']
18
+ when 'mysql'
19
+ gem 'mysql2'
20
+ when 'postgresql'
21
+ gem 'pg'
22
+ else
23
+ gem 'sqlite3'
24
+ end
25
+
26
+ gemspec
27
+
28
+ # Use a local Gemfile to include development dependencies that might not be
29
+ # relevant for the project or for other contributors, e.g. pry-byebug.
30
+ #
31
+ # We use `send` instead of calling `eval_gemfile` to work around an issue with
32
+ # how Dependabot parses projects: https://github.com/dependabot/dependabot-core/issues/1658.
33
+ send(:eval_gemfile, 'Gemfile-local') if File.exist? 'Gemfile-local'
data/LICENSE ADDED
@@ -0,0 +1,26 @@
1
+ Copyright (c) 2020 Nebulab SRLs and other contributors
2
+ All rights reserved.
3
+
4
+ Redistribution and use in source and binary forms, with or without modification,
5
+ are permitted provided that the following conditions are met:
6
+
7
+ * Redistributions of source code must retain the above copyright notice,
8
+ this list of conditions and the following disclaimer.
9
+ * Redistributions in binary form must reproduce the above copyright notice,
10
+ this list of conditions and the following disclaimer in the documentation
11
+ and/or other materials provided with the distribution.
12
+ * Neither the name Solidus nor the names of its contributors may be used to
13
+ endorse or promote products derived from this software without specific
14
+ prior written permission.
15
+
16
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
20
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
21
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
22
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
23
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
24
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
25
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
@@ -0,0 +1,170 @@
1
+ # Solidus Importer
2
+
3
+ This extension aims to create a component to import data from other popular
4
+ e-commerce solutions to Solidus.
5
+
6
+ ## Installation
7
+
8
+ Add solidus_importer to your Gemfile:
9
+
10
+ ```ruby
11
+ gem 'solidus_importer'
12
+ ```
13
+
14
+ Bundle your dependencies and run the installation generator:
15
+
16
+ ```shell
17
+ bundle
18
+ bundle exec rails g solidus_importer:install
19
+ ```
20
+
21
+ ## Usage
22
+
23
+ Sample code to import some products:
24
+
25
+ ```ruby
26
+ SolidusImporter.import! 'some_path/sample_products.csv', type: :products
27
+ ```
28
+
29
+ ### Accepted Format
30
+
31
+ The accepted format is the [Shopify CSV](https://help.shopify.com/en/manual/products/import-export/using-csv) for which is also relatively easy to find exporters for every major platform (e.g. [shopify_transporter](https://github.com/Shopify/shopify_transporter)).
32
+
33
+ There are three supported CSV types:
34
+
35
+ 1. [Product](https://help.shopify.com/en/manual/migrating-to-shopify/transporter-app/csv-products)
36
+ 2. [Order](https://help.shopify.com/en/manual/migrating-to-shopify/transporter-app/csv-orders)
37
+ 3. [Customer](https://help.shopify.com/en/manual/migrating-to-shopify/transporter-app/csv-customers)
38
+
39
+ ### The Processors
40
+
41
+ The importing is managed by a list of processors for each CSV type, the default processors are:
42
+
43
+ ```rb
44
+ customers: {
45
+ importer: SolidusImporter::BaseImporter,
46
+ processors: [
47
+ SolidusImporter::Processors::Address,
48
+ SolidusImporter::Processors::Customer,
49
+ SolidusImporter::Processors::Log
50
+ ]
51
+ },
52
+ orders: {
53
+ importer: SolidusImporter::BaseImporter,
54
+ processors: [
55
+ SolidusImporter::Processors::Order,
56
+ SolidusImporter::Processors::Log
57
+ ]
58
+ },
59
+ products: {
60
+ importer: SolidusImporter::BaseImporter,
61
+ processors: [
62
+ SolidusImporter::Processors::Product,
63
+ SolidusImporter::Processors::Variant,
64
+ SolidusImporter::Processors::OptionTypes,
65
+ SolidusImporter::Processors::OptionValues,
66
+ SolidusImporter::Processors::ProductImages,
67
+ SolidusImporter::Processors::VariantImages,
68
+ SolidusImporter::Processors::Log
69
+ ]
70
+ }
71
+ ```
72
+
73
+ Each processor is a callable that will accept a context Hash. It will perform its function within the `#call(context)` method and will return an equally valid context Hash. The returned context can be augmented with additional data.
74
+
75
+ Example:
76
+
77
+ ```rb
78
+ CUSTOM_LOGGER = Logger.new(Rails.root.join('log/importer.log'))
79
+ CustomLoggerProcessor = ->(context) {
80
+ context.merge(logger: CUSTOM_LOGGER)
81
+ }
82
+ # Replace the original Log processor with CustomLoggerProcessor
83
+ SolidusImporter::Config.solidus_importer[:customers][:processors].map! do |processor|
84
+ if processor == 'SolidusImporter::Processors::Log'
85
+ 'CustomLoggerProcessor'
86
+ else
87
+ processors
88
+ end
89
+ end
90
+ ```
91
+
92
+ Each list of processors can be configured to add, remove, or replace any of the default processors.
93
+
94
+ ### Advanced Configuration
95
+
96
+ To define your own processors (in this example for products), add to the spree
97
+ initializer:
98
+
99
+ ```ruby
100
+ SolidusImporter::Config[:solidus_importer] = {
101
+ products: {
102
+ importer: SolidusImporter::Importers::Products,
103
+ processors: [
104
+ SolidusImporter::Processors::Product,
105
+ SolidusImporter::Processors::Variant,
106
+ SolidusImporter::Processors::Log
107
+ ]
108
+ }
109
+ }
110
+ ```
111
+
112
+ The `importer` class is responsible of the whole import process of a single
113
+ source file. The `processors` classes are responsible of the import of a single
114
+ row of the source file; every processor has a `call` method (with an input
115
+ `context`) which makes a specific action and updates the context if needed.
116
+
117
+ ## Development
118
+
119
+ ### Testing the extension
120
+
121
+ First bundle your dependencies, then run `bin/rake`. `bin/rake` will default to building the dummy
122
+ app if it does not exist, then it will run specs. The dummy app can be regenerated by using
123
+ `bin/rake extension:test_app`.
124
+
125
+ ```shell
126
+ bin/setup
127
+ bin/rake
128
+ ```
129
+
130
+ To run [Rubocop](https://github.com/bbatsov/rubocop) static code analysis run
131
+
132
+ ```shell
133
+ bundle exec rubocop
134
+ ```
135
+
136
+ When testing your application's integration with this extension you may use its factories.
137
+ Simply add this require statement to your spec_helper:
138
+
139
+ ```ruby
140
+ require 'solidus_importer/factories'
141
+
142
+ ```
143
+
144
+ ### Running the sandbox
145
+
146
+ To run this extension in a sandboxed Solidus application, you can run `bin/sandbox`. The path for
147
+ the sandbox app is `./sandbox` and `bin/rails` will forward any Rails commands to
148
+ `sandbox/bin/rails`.
149
+
150
+ Here's an example:
151
+
152
+ ```shell
153
+ $ bin/rails server
154
+ => Booting Puma
155
+ => Rails 6.0.2.1 application starting in development
156
+ * Listening on tcp://127.0.0.1:3000
157
+ Use Ctrl-C to stop
158
+ ```
159
+
160
+ ### Releasing new versions
161
+
162
+ Your new extension version can be released using `gem-release` like this:
163
+
164
+ ```shell
165
+ bundle exec gem bump -v VERSION --tag --push --remote upstream && gem release
166
+ ```
167
+
168
+ ## License
169
+
170
+ Copyright (c) 2020 Nebulab SRLs, released under the New BSD License
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'solidus_dev_support/rake_tasks'
4
+ SolidusDevSupport::RakeTasks.install
5
+
6
+ task default: 'extension:specs'
@@ -0,0 +1,2 @@
1
+ // Placeholder manifest file.
2
+ // the installer will append this file to the app vendored assets here: vendor/assets/javascripts/spree/backend/all.js'
@@ -0,0 +1,2 @@
1
+ // Placeholder manifest file.
2
+ // the installer will append this file to the app vendored assets here: vendor/assets/javascripts/spree/frontend/all.js'
@@ -0,0 +1,16 @@
1
+ /*
2
+ Placeholder manifest file.
3
+ the installer will append this file to the app vendored assets here: 'vendor/assets/stylesheets/spree/backend/all.css'
4
+ */
5
+
6
+ .solidus_importer.state-failed {
7
+ color: #d00;
8
+ }
9
+
10
+ .solidus_importer.state-processing {
11
+ color: #fb1;
12
+ }
13
+
14
+ .solidus_importer.state-completed {
15
+ color: #0a0;
16
+ }
@@ -0,0 +1,4 @@
1
+ /*
2
+ Placeholder manifest file.
3
+ the installer will append this file to the app vendored assets here: 'vendor/assets/stylesheets/spree/frontend/all.css'
4
+ */
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Spree
4
+ module Admin
5
+ module SolidusImporter
6
+ class ImportRowsController < BaseController
7
+ before_action :load_data, only: %i[show]
8
+
9
+ def show; end
10
+
11
+ private
12
+
13
+ def load_data
14
+ @import_row = ::SolidusImporter::Row.find_by!(id: params[:id], import_id: params[:import_id])
15
+ return unless (@log_entry = ::Spree::LogEntry.find_by(source: @import_row))
16
+
17
+ @log_details = JSON.parse(@log_entry.details)
18
+ target_class = @log_details['class_name']&.constantize
19
+ @target_entity = target_class.find_by(id: @log_details['id']) if target_class
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,44 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Spree
4
+ module Admin
5
+ module SolidusImporter
6
+ class ImportsController < ResourceController
7
+ before_action :assigns_import_types
8
+ after_action :import!, if: -> { @import.valid? }, only: :create
9
+
10
+ def index
11
+ @search = ::SolidusImporter::Import.ransack(params[:q])
12
+ @imports = @search.result(distinct: true)
13
+ .page(params[:page])
14
+ .per(params[:per_page] || Spree::Config[:orders_per_page])
15
+ .order(id: :desc)
16
+ end
17
+
18
+ def show
19
+ @import = ::SolidusImporter::Import.find(params[:id])
20
+ @search = @import.rows.ransack(params[:q])
21
+ @import_rows = @search.result(distinct: true).page(params[:page]).per(params[:per_page]).order(id: :desc)
22
+ end
23
+
24
+ private
25
+
26
+ def import!
27
+ ::SolidusImporter::ImportJob.perform_later(@import.id)
28
+ end
29
+
30
+ def model_class
31
+ ::SolidusImporter::Import
32
+ end
33
+
34
+ def permitted_resource_params
35
+ params.require(:solidus_importer_import).permit(:file, :import_type)
36
+ end
37
+
38
+ def assigns_import_types
39
+ @import_types = ::SolidusImporter::Config.available_types
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end