solidus_backtracs 2.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.bundle/config +2 -0
- data/.circleci/config.yml +41 -0
- data/.gem_release.yml +5 -0
- data/.github/stale.yml +17 -0
- data/.github_changelog_generator +2 -0
- data/.gitignore +20 -0
- data/.rspec +2 -0
- data/.rubocop.yml +14 -0
- data/.rubocop_todo.yml +40 -0
- data/CHANGELOG.md +2 -0
- data/Gemfile +33 -0
- data/LICENSE +26 -0
- data/README.md +208 -0
- data/Rakefile +6 -0
- data/app/assets/javascripts/spree/backend/solidus_backtracs.js +2 -0
- data/app/assets/javascripts/spree/frontend/solidus_backtracs.js +2 -0
- data/app/assets/stylesheets/spree/backend/solidus_backtracs.css +4 -0
- data/app/assets/stylesheets/spree/frontend/solidus_backtracs.css +4 -0
- data/app/controllers/spree/backtracs_controller.rb +46 -0
- data/app/decorators/models/solidus_backtracs/spree/shipment_decorator.rb +33 -0
- data/app/helpers/solidus_backtracs/export_helper.rb +52 -0
- data/app/jobs/solidus_backtracs/api/schedule_shipment_syncs_job.rb +28 -0
- data/app/jobs/solidus_backtracs/api/sync_shipment_job.rb +17 -0
- data/app/jobs/solidus_backtracs/api/sync_shipments_job.rb +41 -0
- data/app/queries/solidus_backtracs/shipment/between_query.rb +14 -0
- data/app/queries/solidus_backtracs/shipment/exportable_query.rb +24 -0
- data/app/queries/solidus_backtracs/shipment/pending_api_sync_query.rb +51 -0
- data/app/views/spree/backtracs/export.xml.builder +58 -0
- data/bin/console +17 -0
- data/bin/rails +7 -0
- data/bin/rails-engine +13 -0
- data/bin/rails-sandbox +16 -0
- data/bin/rake +7 -0
- data/bin/sandbox +86 -0
- data/bin/setup +8 -0
- data/config/locales/en.yml +5 -0
- data/config/routes.rb +6 -0
- data/db/migrate/20210220093010_add_backtracs_api_sync_fields.rb +8 -0
- data/lib/generators/solidus_backtracs/install/install_generator.rb +27 -0
- data/lib/generators/solidus_backtracs/install/templates/initializer.rb +91 -0
- data/lib/solidus_backtracs/api/batch_syncer.rb +45 -0
- data/lib/solidus_backtracs/api/client.rb +36 -0
- data/lib/solidus_backtracs/api/rate_limited_error.rb +23 -0
- data/lib/solidus_backtracs/api/request_error.rb +33 -0
- data/lib/solidus_backtracs/api/request_runner.rb +87 -0
- data/lib/solidus_backtracs/api/shipment_serializer.rb +103 -0
- data/lib/solidus_backtracs/api/threshold_verifier.rb +28 -0
- data/lib/solidus_backtracs/configuration.rb +62 -0
- data/lib/solidus_backtracs/engine.rb +19 -0
- data/lib/solidus_backtracs/errors.rb +23 -0
- data/lib/solidus_backtracs/shipment_notice.rb +58 -0
- data/lib/solidus_backtracs/testing_support/factories.rb +4 -0
- data/lib/solidus_backtracs/version.rb +5 -0
- data/lib/solidus_backtracs.rb +16 -0
- data/solidus_shipstation.gemspec +39 -0
- data/spec/controllers/spree/backtracs_controller_spec.rb +103 -0
- data/spec/fixtures/backtracs_xml_schema.xsd +171 -0
- data/spec/jobs/solidus_backtracs/api/schedule_shipment_syncs_job_spec.rb +32 -0
- data/spec/jobs/solidus_backtracs/api/sync_shipments_job_spec.rb +102 -0
- data/spec/lib/solidus_backtracs/api/batch_syncer_spec.rb +228 -0
- data/spec/lib/solidus_backtracs/api/client_spec.rb +120 -0
- data/spec/lib/solidus_backtracs/api/rate_limited_error_spec.rb +21 -0
- data/spec/lib/solidus_backtracs/api/request_error_spec.rb +20 -0
- data/spec/lib/solidus_backtracs/api/request_runner_spec.rb +65 -0
- data/spec/lib/solidus_backtracs/api/shipment_serializer_spec.rb +25 -0
- data/spec/lib/solidus_backtracs/api/threshold_verifier_spec.rb +61 -0
- data/spec/lib/solidus_backtracs/shipment_notice_spec.rb +111 -0
- data/spec/lib/solidus_backtracs_spec.rb +9 -0
- data/spec/models/spree/shipment_spec.rb +49 -0
- data/spec/queries/solidus_backtracs/shipment/between_query_spec.rb +53 -0
- data/spec/queries/solidus_backtracs/shipment/exportable_query_spec.rb +53 -0
- data/spec/queries/solidus_backtracs/shipment/pending_api_sync_query_spec.rb +37 -0
- data/spec/spec_helper.rb +31 -0
- data/spec/support/configuration_helper.rb +13 -0
- data/spec/support/controllers.rb +1 -0
- data/spec/support/webmock.rb +3 -0
- data/spec/support/xsd.rb +5 -0
- metadata +248 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 7e943693a25b935abcf72d941f4f38c891761c3afae537f108e211041ccdc6e2
|
4
|
+
data.tar.gz: 87c9e1870799e0b007a8e2011a3460086b0aa9ccb39fa8a34bd1942bdf38e3ba
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: c43355431c15e927961f74576d56e80bf7e56f6a14233bdf0ade847e833624c60cdf110c377952014e2007a0cb4d4138e8c5300e3e444a9d77f39c83effda44f
|
7
|
+
data.tar.gz: 95ce5f1c0d8d86a5a07eb884154caeecb9ca3c69a634594964d795aaa80439bb6a0bec00074dcf9151eeb16d02099fbea21a47fdcb560a9e98975e1f69892f1e
|
data/.bundle/config
ADDED
@@ -0,0 +1,41 @@
|
|
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
|
+
lint-code:
|
20
|
+
executor: solidusio_extensions/sqlite-memory
|
21
|
+
steps:
|
22
|
+
- solidusio_extensions/lint-code
|
23
|
+
|
24
|
+
workflows:
|
25
|
+
"Run specs on supported Solidus versions":
|
26
|
+
jobs:
|
27
|
+
- run-specs-with-postgres
|
28
|
+
- run-specs-with-mysql
|
29
|
+
- lint-code
|
30
|
+
|
31
|
+
"Weekly run specs against master":
|
32
|
+
triggers:
|
33
|
+
- schedule:
|
34
|
+
cron: "0 0 * * 4" # every Thursday
|
35
|
+
filters:
|
36
|
+
branches:
|
37
|
+
only:
|
38
|
+
- master
|
39
|
+
jobs:
|
40
|
+
- run-specs-with-postgres
|
41
|
+
- run-specs-with-mysql
|
data/.gem_release.yml
ADDED
data/.github/stale.yml
ADDED
@@ -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: false
|
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: stale
|
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 might 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
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/.rubocop.yml
ADDED
data/.rubocop_todo.yml
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
# This configuration was generated by
|
2
|
+
# `rubocop --auto-gen-config`
|
3
|
+
# on 2020-09-22 09:09:44 UTC using RuboCop version 0.87.1.
|
4
|
+
# The point is for the user to remove these configuration records
|
5
|
+
# one by one as the offenses are removed from the code base.
|
6
|
+
# Note that changes in the inspected code, or installation of new
|
7
|
+
# versions of RuboCop, may require this file to be generated again.
|
8
|
+
|
9
|
+
# Offense count: 1
|
10
|
+
Lint/UselessAssignment:
|
11
|
+
Exclude:
|
12
|
+
- 'app/controllers/spree/backtracs_controller.rb'
|
13
|
+
|
14
|
+
# Offense count: 1
|
15
|
+
RSpec/AnyInstance:
|
16
|
+
Exclude:
|
17
|
+
- 'spec/lib/solidus_backtracs/shipment_notice_spec.rb'
|
18
|
+
|
19
|
+
# Offense count: 5
|
20
|
+
RSpec/MultipleExpectations:
|
21
|
+
Max: 2
|
22
|
+
|
23
|
+
# Offense count: 8
|
24
|
+
RSpec/NestedGroups:
|
25
|
+
Max: 5
|
26
|
+
|
27
|
+
# Offense count: 6
|
28
|
+
# Configuration parameters: ForbiddenMethods, AllowedMethods.
|
29
|
+
# ForbiddenMethods: decrement!, decrement_counter, increment!, increment_counter, insert, insert!, insert_all, insert_all!, toggle!, touch, touch_all, update_all, update_attribute, update_column, update_columns, update_counters, upsert, upsert_all
|
30
|
+
Rails/SkipsModelValidations:
|
31
|
+
Exclude:
|
32
|
+
- 'spec/lib/solidus_backtracs/shipment_notice_spec.rb'
|
33
|
+
- 'spec/models/spree/shipment_spec.rb'
|
34
|
+
- 'spec/support/shipment_helper.rb'
|
35
|
+
|
36
|
+
# Offense count: 1
|
37
|
+
# Configuration parameters: MinBodyLength.
|
38
|
+
Style/GuardClause:
|
39
|
+
Exclude:
|
40
|
+
- 'spec/support/configuration_helper.rb'
|
data/CHANGELOG.md
ADDED
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) 2013 Boomer Digital
|
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.
|
data/README.md
ADDED
@@ -0,0 +1,208 @@
|
|
1
|
+
# Solidus ShipStation — Suvie fork
|
2
|
+
|
3
|
+
[![CircleCI](https://circleci.com/gh/solidusio-contrib/solidus_backtracs.svg?style=shield)](https://circleci.com/gh/solidusio-contrib/solidus_backtracs)
|
4
|
+
[![codecov](https://codecov.io/gh/solidusio-contrib/solidus_backtracs/branch/master/graph/badge.svg)](https://codecov.io/gh/solidusio-contrib/solidus_backtracs)
|
5
|
+
|
6
|
+
This gem integrates [ShipStation](http://www.backtracs.com) with [Solidus](http://solidus.io). It
|
7
|
+
enables ShipStation to pull shipments from the system and update tracking numbers.
|
8
|
+
|
9
|
+
This integration is a fork of [spree_backtracs](https://github.com/DynamoMTL/spree_backtracs)
|
10
|
+
that adds Solidus and Rails 4.2+ compatibility.
|
11
|
+
|
12
|
+
## Installation
|
13
|
+
|
14
|
+
Add solidus_backtracs to your Gemfile:
|
15
|
+
|
16
|
+
```ruby
|
17
|
+
gem 'solidus_backtracs', github: 'solidusio-contrib/solidus_backtracs'
|
18
|
+
```
|
19
|
+
|
20
|
+
Bundle your dependencies and run the installation generator:
|
21
|
+
|
22
|
+
```shell
|
23
|
+
bin/rails generate solidus_backtracs:install
|
24
|
+
```
|
25
|
+
|
26
|
+
The installer will create a configuration initializer that you'll need to customize.
|
27
|
+
|
28
|
+
The installer will also create a migration, which is required by the API integration. If you are
|
29
|
+
going to use the XML integration, feel free to delete the migration file, as those columns won't be
|
30
|
+
used by the extension.
|
31
|
+
|
32
|
+
## Usage
|
33
|
+
|
34
|
+
This extension can integrate with ShipStation in two ways.
|
35
|
+
|
36
|
+
### XML integration
|
37
|
+
|
38
|
+
The [XML integration](https://help.backtracs.com/hc/en-us/articles/360025856192-Custom-Store-Development-Guide)
|
39
|
+
works by exposing a route in your Solidus application that generates an XML feed of all recently
|
40
|
+
created and updated shipments in your Solidus store.
|
41
|
+
|
42
|
+
#### XML integration: Configuration
|
43
|
+
|
44
|
+
In order to enable the XML integration, make sure to configure the relevant section of the
|
45
|
+
configuration initializer, and configure your ShipStation store accordingly:
|
46
|
+
|
47
|
+
- **Username**: the username defined in your configuration.
|
48
|
+
- **Password**: the password defined in your configuration.
|
49
|
+
- **URL to custom page**: `https://yourdomain.com/backtracs.xml`.
|
50
|
+
|
51
|
+
You can also configure your ShipStation store to pull the XML feed automatically on a recurring
|
52
|
+
basis, or manually by clicking the "Refresh stores" button.
|
53
|
+
|
54
|
+
There are five shipment states for an order (= shipment) in ShipStation. These states do not
|
55
|
+
necessarily align with Solidus, but you can configure ShipStation to create a mapping for your
|
56
|
+
specific needs. Here's the recommended mapping:
|
57
|
+
|
58
|
+
ShipStation description | ShipStation status | Solidus status
|
59
|
+
------------------------|--------------------|---------------
|
60
|
+
Awaiting Payment | `unpaid` | `pending`
|
61
|
+
Awaiting Shipment | `paid` | `ready`
|
62
|
+
Shipped | `shipped` | `shipped`
|
63
|
+
Cancelled | `cancelled` | `cancelled`
|
64
|
+
On-Hold | `on-hold` | `pending`
|
65
|
+
|
66
|
+
Once you've configured the XML integration in your app and ShipStation, there's nothing else you
|
67
|
+
need to do. ShipStation will
|
68
|
+
|
69
|
+
#### XML integration: Usage
|
70
|
+
|
71
|
+
There's nothing you need to do. Once properly configured, the integration just works!
|
72
|
+
|
73
|
+
#### XML integration: Gotchas
|
74
|
+
|
75
|
+
There are a few gotchas you need to be aware of:
|
76
|
+
|
77
|
+
- If you change the shipping method of an order in ShipStation, the change will not be reflected in
|
78
|
+
Solidus and the tracking link might not work properly.
|
79
|
+
- When `backtracs_capture_at_notification` is enabled, any errors during payment capture will
|
80
|
+
prevent the update of the shipment's tracking number.
|
81
|
+
|
82
|
+
### API integration
|
83
|
+
|
84
|
+
The [API integration](https://www.backtracs.com/docs/api/) works by calling the ShipStation API
|
85
|
+
to sync all of your shipments continuously.
|
86
|
+
|
87
|
+
Because ShipStation has very low rate limits (i.e., 40 reqs/minute at the time of writing), the
|
88
|
+
API integration does not send an API request for every single shipment update, as you would expect
|
89
|
+
from a traditional API integration.
|
90
|
+
|
91
|
+
Instead, a background job runs on a recurring basis and batches together all the shipments that need
|
92
|
+
to be created or updated in ShipStation. These shipments are then sent in groups of 100 (by default)
|
93
|
+
to ShipStation's [bulk order upsert endpoint](https://www.backtracs.com/docs/api/orders/create-update-multiple-orders/).
|
94
|
+
|
95
|
+
This allows us to work around ShipStation's rate limit and sync up to 4000 shipments/minute.
|
96
|
+
|
97
|
+
As you may imagine, this technique also comes at the expense of some additional complexity in the
|
98
|
+
implementation, but the extension abstracts it all away for you.
|
99
|
+
|
100
|
+
#### API integration: Configuration
|
101
|
+
|
102
|
+
In order to enable the API integration, make sure to configure the relevant section of the
|
103
|
+
configuration initializer. At the very least, the integration needs to know your API credentials
|
104
|
+
and store ID, but there are additional options you can configure — just look at the initializer!
|
105
|
+
|
106
|
+
#### API integration: Usage
|
107
|
+
|
108
|
+
Once you've configured the integration, you will also need to enqueue the `ScheduleShipmentSyncsJob`
|
109
|
+
on a recurring basis, to kick off the synchronization process. Because every app uses a different
|
110
|
+
background processing library, this is left up to the user.
|
111
|
+
|
112
|
+
Here's what an example with [sidekiq-scheduler](https://github.com/moove-it/sidekiq-scheduler) might
|
113
|
+
look like:
|
114
|
+
|
115
|
+
```yaml
|
116
|
+
# config/sidekiq.yml
|
117
|
+
:schedule:
|
118
|
+
schedule_shipment_syncs:
|
119
|
+
every: ['1m', first_in: '0s']
|
120
|
+
class: 'SolidusBacktracs::Api::ScheduleShipmentSyncsJob'
|
121
|
+
```
|
122
|
+
|
123
|
+
This will schedule the job to run every minute. This is generally a good starting point, but feel
|
124
|
+
free to adjust it as needed.
|
125
|
+
|
126
|
+
#### API integration: Gotchas
|
127
|
+
|
128
|
+
There's one possible problem you need to be aware of, when integrating via the API.
|
129
|
+
|
130
|
+
You should make sure the interval between your syncs is, on average, larger than your latency in
|
131
|
+
processing background jobs, or you are going to experience sync overlaps.
|
132
|
+
|
133
|
+
As an example, if it takes your Sidekiq process 10 seconds to execute a job from the time it's
|
134
|
+
scheduled, but you schedule a shipment sync every 5 seconds, your sync jobs will start overlapping,
|
135
|
+
making your latency even worse.
|
136
|
+
|
137
|
+
This is a problem that is faced by all recurring jobs. The solution is two-fold:
|
138
|
+
|
139
|
+
1. Monitor the latency of your background processing queues. Seriously, do it.
|
140
|
+
2. Make sure your sync interval is not too aggressive: unless you really need to, there's no point
|
141
|
+
in syncing your shipments more often than once a minute.
|
142
|
+
|
143
|
+
## Development
|
144
|
+
|
145
|
+
### Testing the extension
|
146
|
+
|
147
|
+
First bundle your dependencies, then run `bin/rake`. `bin/rake` will default to building the dummy
|
148
|
+
app if it does not exist, then it will run specs. The dummy app can be regenerated by using
|
149
|
+
`bin/rake extension:test_app`.
|
150
|
+
|
151
|
+
```shell
|
152
|
+
bin/rake
|
153
|
+
```
|
154
|
+
|
155
|
+
To run [Rubocop](https://github.com/bbatsov/rubocop) static code analysis run
|
156
|
+
|
157
|
+
```shell
|
158
|
+
bundle exec rubocop
|
159
|
+
```
|
160
|
+
|
161
|
+
When testing your application's integration with this extension you may use its factories.
|
162
|
+
Simply add this require statement to your `spec/spec_helper.rb`:
|
163
|
+
|
164
|
+
```ruby
|
165
|
+
require 'solidus_backtracs/testing_support/factories'
|
166
|
+
```
|
167
|
+
|
168
|
+
Or, if you are using `FactoryBot.definition_file_paths`, you can load Solidus core
|
169
|
+
factories along with this extension's factories using this statement:
|
170
|
+
|
171
|
+
```ruby
|
172
|
+
SolidusDevSupport::TestingSupport::Factories.load_for(SolidusBacktracs::Engine)
|
173
|
+
```
|
174
|
+
|
175
|
+
### Running the sandbox
|
176
|
+
|
177
|
+
To run this extension in a sandboxed Solidus application, you can run `bin/sandbox`. The path for
|
178
|
+
the sandbox app is `./sandbox` and `bin/rails` will forward any Rails commands to
|
179
|
+
`sandbox/bin/rails`.
|
180
|
+
|
181
|
+
Here's an example:
|
182
|
+
|
183
|
+
```
|
184
|
+
$ bin/rails server
|
185
|
+
=> Booting Puma
|
186
|
+
=> Rails 6.0.2.1 application starting in development
|
187
|
+
* Listening on tcp://127.0.0.1:3000
|
188
|
+
Use Ctrl-C to stop
|
189
|
+
```
|
190
|
+
|
191
|
+
### Updating the changelog
|
192
|
+
|
193
|
+
Before and after releases the changelog should be updated to reflect the up-to-date status of
|
194
|
+
the project:
|
195
|
+
|
196
|
+
```shell
|
197
|
+
bin/rake changelog
|
198
|
+
git add CHANGELOG.md
|
199
|
+
git commit -m "Update the changelog"
|
200
|
+
```
|
201
|
+
|
202
|
+
### Releasing new versions
|
203
|
+
|
204
|
+
Please refer to the dedicated [page](https://github.com/solidusio/solidus/wiki/How-to-release-extensions) on Solidus wiki.
|
205
|
+
|
206
|
+
## License
|
207
|
+
|
208
|
+
Copyright (c) 2013 Boomer Digital, released under the New BSD License.
|
data/Rakefile
ADDED
@@ -0,0 +1,46 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Spree
|
4
|
+
class BacktracsController < Spree::BaseController
|
5
|
+
protect_from_forgery with: :null_session, only: :shipnotify
|
6
|
+
|
7
|
+
before_action :authenticate_backtracs
|
8
|
+
|
9
|
+
def export
|
10
|
+
@shipments = SolidusBacktracs::Shipment::ExportableQuery.apply(Spree::Shipment.all)
|
11
|
+
@shipments = SolidusBacktracs::Shipment::BetweenQuery.apply(
|
12
|
+
@shipments,
|
13
|
+
from: date_param(:start_date),
|
14
|
+
to: date_param(:end_date),
|
15
|
+
)
|
16
|
+
@shipments = @shipments.page(params[:page]).per(50)
|
17
|
+
|
18
|
+
respond_to do |format|
|
19
|
+
format.xml { render layout: false }
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def shipnotify
|
24
|
+
shipment_notice_class = SolidusBacktracs.configuration.shipment_notice_class.constantize
|
25
|
+
shipment_notice_class.from_payload(params.to_unsafe_h).apply
|
26
|
+
head :ok
|
27
|
+
rescue SolidusBacktracs::Error => e
|
28
|
+
head :bad_request
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
def date_param(name)
|
34
|
+
return if params[name].blank?
|
35
|
+
|
36
|
+
Time.strptime("#{params[name]} UTC", '%m/%d/%Y %H:%M %Z')
|
37
|
+
end
|
38
|
+
|
39
|
+
def authenticate_backtracs
|
40
|
+
authenticate_or_request_with_http_basic do |username, password|
|
41
|
+
username == SolidusBacktracs.configuration.username &&
|
42
|
+
password == SolidusBacktracs.configuration.password
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module SolidusBacktracs
|
4
|
+
module Spree
|
5
|
+
module ShipmentDecorator
|
6
|
+
def self.prepended(base)
|
7
|
+
base.singleton_class.prepend ClassMethods
|
8
|
+
end
|
9
|
+
|
10
|
+
module ClassMethods
|
11
|
+
def exportable
|
12
|
+
::Spree::Deprecation.warn <<~DEPRECATION
|
13
|
+
`Spree::Shipment.exportable` is deprecated and will be removed in a future version
|
14
|
+
of solidus_backtracs. Please use `SolidusBacktracs::Shipment::ExportableQuery.apply`.
|
15
|
+
DEPRECATION
|
16
|
+
|
17
|
+
SolidusBacktracs::Shipment::ExportableQuery.apply(self)
|
18
|
+
end
|
19
|
+
|
20
|
+
def between(from, to)
|
21
|
+
::Spree::Deprecation.warn <<~DEPRECATION
|
22
|
+
`Spree::Shipment.between` is deprecated and will be removed in a future version
|
23
|
+
of solidus_backtracs. Please use `SolidusBacktracs::Shipment::BetweenQuery.apply`.
|
24
|
+
DEPRECATION
|
25
|
+
|
26
|
+
SolidusBacktracs::Shipment::BetweenQuery.apply(self, from: from, to: to)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
::Spree::Shipment.prepend self
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'builder'
|
4
|
+
|
5
|
+
module SolidusBacktracs
|
6
|
+
module ExportHelper
|
7
|
+
DATE_FORMAT = '%m/%d/%Y %H:%M'
|
8
|
+
BACTRACS_DATE_FORMAT = '%Y-%m-%dT%H:%M:%S'
|
9
|
+
|
10
|
+
# rubocop:disable all
|
11
|
+
def self.address(xml, order, type)
|
12
|
+
name = "#{type.to_s.titleize}To"
|
13
|
+
address = order.send("#{type}_address")
|
14
|
+
|
15
|
+
xml.__send__(name) {
|
16
|
+
xml.Name address.respond_to?(:name) ? address.name : address.full_name
|
17
|
+
xml.Company address.company
|
18
|
+
|
19
|
+
if type == :ship
|
20
|
+
xml.Address1 address.address1
|
21
|
+
xml.Address2 address.address2
|
22
|
+
xml.City address.city
|
23
|
+
xml.State address.state ? address.state.abbr : address.state_name
|
24
|
+
xml.PostalCode address.zipcode
|
25
|
+
xml.Country address.country.iso
|
26
|
+
end
|
27
|
+
|
28
|
+
xml.Phone address.phone
|
29
|
+
}
|
30
|
+
end
|
31
|
+
|
32
|
+
def self.backtracs_address(xml, order, type)
|
33
|
+
name = "#{type.to_s.titleize}To"
|
34
|
+
address = order.send("#{type}_address")
|
35
|
+
|
36
|
+
xml.__send__(name) {
|
37
|
+
xml.CompanyName address.company ? address.company : address.name
|
38
|
+
xml.Contact address.name
|
39
|
+
xml.ContactEmail order.email
|
40
|
+
xml.Address1 address.address1
|
41
|
+
xml.Address2 address.address2
|
42
|
+
xml.City address.city
|
43
|
+
xml.State address.state ? address.state.abbr : address.state_name
|
44
|
+
xml.Zip address.zipcode
|
45
|
+
xml.Phone address.phone.present? ? address.phone : "000-000-0000"
|
46
|
+
xml.PhoneAlt address.phone.present? ? address.phone : "000-000-0000"
|
47
|
+
xml.Country address.country.iso
|
48
|
+
}
|
49
|
+
end
|
50
|
+
# rubocop:enable all
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module SolidusBacktracs
|
4
|
+
module Api
|
5
|
+
class ScheduleShipmentSyncsJob < ApplicationJob
|
6
|
+
queue_as :default
|
7
|
+
|
8
|
+
def perform
|
9
|
+
shipments = query_shipments
|
10
|
+
|
11
|
+
shipments.find_in_batches(batch_size: SolidusBacktracs.config.api_batch_size) do |batch|
|
12
|
+
SyncShipmentsJob.perform_later(batch.to_a)
|
13
|
+
end
|
14
|
+
rescue StandardError => e
|
15
|
+
SolidusBacktracs.config.error_handler.call(e, {})
|
16
|
+
end
|
17
|
+
|
18
|
+
def shippable_skus
|
19
|
+
SolidusBacktracs.config.shippable_skus.present? ? SolidusBacktracs.config.shippable_skus : Spree::Variant.pluck(:sku)
|
20
|
+
end
|
21
|
+
|
22
|
+
def query_shipments
|
23
|
+
shipments = SolidusBacktracs::Shipment::PendingApiSyncQuery.apply(::Spree::Shipment.joins(inventory_units: [:variant]).where("spree_variants.sku" => SolidusBacktracs.config.shippable_skus).where("spree_shipments.state" => :ready).where.not(shipstation_order_id: nil).distinct)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module SolidusBacktracs
|
4
|
+
module Api
|
5
|
+
class SyncShipmentJob < ApplicationJob
|
6
|
+
queue_as :default
|
7
|
+
|
8
|
+
def perform(shipment_id: nil, error_handler: nil, shipment_serializer: nil, request_runner: nil)
|
9
|
+
shipment = ::Spree::Shipment.find(shipment_id)
|
10
|
+
request_runner.authenticated_call(method: :post, path: '/webservices/rma/rmaservice.asmx', serializer: shipment_serializer, shipment: shipment)
|
11
|
+
rescue StandardError => e
|
12
|
+
error_handler.call(e, shipment: shipment)
|
13
|
+
nil
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|