shopify_transporter 2.0.1 → 2.2.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.
- checksums.yaml +4 -4
- data/lib/shopify_transporter/exporters/magento/customer_exporter.rb +20 -1
- data/lib/shopify_transporter/exporters/magento/order_exporter.rb +20 -1
- data/lib/shopify_transporter/exporters/magento/product_exporter.rb +20 -1
- data/lib/shopify_transporter/exporters/magento/soap.rb +13 -4
- data/lib/shopify_transporter/pipeline/magento/order/addresses_attribute.rb +8 -0
- data/lib/shopify_transporter/pipeline/magento/order/line_items.rb +5 -0
- data/lib/shopify_transporter/pipeline/magento/order/top_level_attributes.rb +105 -0
- data/lib/shopify_transporter/pipeline/magento/order/transactions.rb +47 -0
- data/lib/shopify_transporter/shopify/order.rb +20 -2
- data/lib/shopify_transporter/version.rb +1 -1
- data/lib/templates/magento/config.tt +1 -0
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6eda8c759a40e474719373d41d3554e10d43f5bf
|
4
|
+
data.tar.gz: baca1185566a388a56a725e80e641066b91a8b05
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6589791c84651519d8b184ff6bb1dd077d08711fab9abd522884c8a74a677d57b034d7b23d9f809bc782142e3845825eefcd3f20e6d362669e166dcd6374ac00
|
7
|
+
data.tar.gz: db735a4ed6eba567b4e4a3ec65f8d2182a34bbe8371ec901ccd56252b3b84485bc6ddf5606d249e6577545cdcc1d5bbc8533e2cade66f59167cd1d8b603b24ef
|
@@ -15,7 +15,12 @@ module ShopifyTransporter
|
|
15
15
|
|
16
16
|
def export
|
17
17
|
base_customers.each do |customer|
|
18
|
-
|
18
|
+
begin
|
19
|
+
yield with_attributes(customer)
|
20
|
+
rescue Savon::Error => e
|
21
|
+
print_customer_details_error(customer, e)
|
22
|
+
yield customer
|
23
|
+
end
|
19
24
|
end
|
20
25
|
end
|
21
26
|
|
@@ -38,6 +43,20 @@ module ShopifyTransporter
|
|
38
43
|
def customer_address_list(customer_id)
|
39
44
|
@client.call(:customer_address_list, customer_id: customer_id).body
|
40
45
|
end
|
46
|
+
|
47
|
+
def print_customer_details_error(customer, e)
|
48
|
+
$stderr.puts '***'
|
49
|
+
$stderr.puts 'Warning:'
|
50
|
+
$stderr.puts "Encountered an error with fetching details for customer with id: #{customer[:customer_id]}"
|
51
|
+
$stderr.puts JSON.pretty_generate(customer)
|
52
|
+
$stderr.puts 'The exact error was:'
|
53
|
+
$stderr.puts "#{e.class}: "
|
54
|
+
$stderr.puts e.message
|
55
|
+
$stderr.puts '-'
|
56
|
+
$stderr.puts "Exporting the customer (#{customer[:customer_id]}) without its details."
|
57
|
+
$stderr.puts 'Continuing with the next customer.'
|
58
|
+
$stderr.puts '***'
|
59
|
+
end
|
41
60
|
end
|
42
61
|
end
|
43
62
|
end
|
@@ -15,7 +15,12 @@ module ShopifyTransporter
|
|
15
15
|
|
16
16
|
def export
|
17
17
|
base_orders.each do |order|
|
18
|
-
|
18
|
+
begin
|
19
|
+
yield with_attributes(order)
|
20
|
+
rescue Savon::Error => e
|
21
|
+
print_order_details_error(order, e)
|
22
|
+
yield order
|
23
|
+
end
|
19
24
|
end
|
20
25
|
end
|
21
26
|
|
@@ -40,6 +45,20 @@ module ShopifyTransporter
|
|
40
45
|
.call(:sales_order_info, order_increment_id: order_increment_id)
|
41
46
|
.body[:sales_order_info_response]
|
42
47
|
end
|
48
|
+
|
49
|
+
def print_order_details_error(order, e)
|
50
|
+
$stderr.puts '***'
|
51
|
+
$stderr.puts 'Warning:'
|
52
|
+
$stderr.puts "Encountered an error with fetching details for order with id: #{order[:order_id]}"
|
53
|
+
$stderr.puts JSON.pretty_generate(order)
|
54
|
+
$stderr.puts 'The exact error was:'
|
55
|
+
$stderr.puts "#{e.class}: "
|
56
|
+
$stderr.puts e.message
|
57
|
+
$stderr.puts '-'
|
58
|
+
$stderr.puts "Exporting the order (#{order[:order_id]}) without its details."
|
59
|
+
$stderr.puts 'Continuing with the next order.'
|
60
|
+
$stderr.puts '***'
|
61
|
+
end
|
43
62
|
end
|
44
63
|
end
|
45
64
|
end
|
@@ -21,7 +21,12 @@ module ShopifyTransporter
|
|
21
21
|
|
22
22
|
def export
|
23
23
|
base_products.each do |product|
|
24
|
-
|
24
|
+
begin
|
25
|
+
yield with_attributes(product)
|
26
|
+
rescue Savon::Error => e
|
27
|
+
print_product_details_error(product, e)
|
28
|
+
yield product
|
29
|
+
end
|
25
30
|
end
|
26
31
|
end
|
27
32
|
|
@@ -123,6 +128,20 @@ module ShopifyTransporter
|
|
123
128
|
.call(:catalog_product_tag_list, product_id: product_id.to_i)
|
124
129
|
.body[:catalog_product_tag_list_response][:result][:item]
|
125
130
|
end
|
131
|
+
|
132
|
+
def print_product_details_error(product, e)
|
133
|
+
$stderr.puts '***'
|
134
|
+
$stderr.puts 'Warning:'
|
135
|
+
$stderr.puts "Encountered an error with fetching details for product with id: #{product[:product_id]}"
|
136
|
+
$stderr.puts JSON.pretty_generate(product)
|
137
|
+
$stderr.puts 'The exact error was:'
|
138
|
+
$stderr.puts "#{e.class}: "
|
139
|
+
$stderr.puts e.message
|
140
|
+
$stderr.puts '-'
|
141
|
+
$stderr.puts "Exporting the product (#{product[:product_id]}) without its details."
|
142
|
+
$stderr.puts 'Continuing with the next product.'
|
143
|
+
$stderr.puts '***'
|
144
|
+
end
|
126
145
|
end
|
127
146
|
end
|
128
147
|
end
|
@@ -33,10 +33,19 @@ module ShopifyTransporter
|
|
33
33
|
|
34
34
|
$stderr.puts "Processing batch: #{current_id}..#{end_of_range}"
|
35
35
|
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
36
|
+
begin
|
37
|
+
enumerator << call(
|
38
|
+
method,
|
39
|
+
params.merge(batching_filter(current_id, end_of_range, batch_index_column)),
|
40
|
+
)
|
41
|
+
rescue Savon::Error => e
|
42
|
+
output = 'Skipping batch: '\
|
43
|
+
"#{current_id}..#{end_of_range} after #{MAX_RETRIES} retries because of an error."
|
44
|
+
$stderr.puts output
|
45
|
+
$stderr.puts 'The exact error was:'
|
46
|
+
$stderr.puts "#{e.class}: "
|
47
|
+
$stderr.puts e.message
|
48
|
+
end
|
40
49
|
|
41
50
|
current_id += batch_size
|
42
51
|
end
|
@@ -31,14 +31,22 @@ module ShopifyTransporter
|
|
31
31
|
{
|
32
32
|
first_name: address_attrs['firstname'],
|
33
33
|
last_name: address_attrs['lastname'],
|
34
|
+
name: name(address_attrs),
|
34
35
|
phone: address_attrs['telephone'],
|
35
36
|
address1: address_attrs['street'],
|
36
37
|
city: address_attrs['city'],
|
37
38
|
province_code: address_attrs['region'],
|
38
39
|
zip: address_attrs['postcode'],
|
39
40
|
country_code: address_attrs['country_id'],
|
41
|
+
company: address_attrs['company'],
|
40
42
|
}
|
41
43
|
end
|
44
|
+
|
45
|
+
def name(address_attrs)
|
46
|
+
if address_attrs['firstname'].present? && address_attrs['lastname'].present?
|
47
|
+
address_attrs['firstname'] + ' ' + address_attrs['lastname']
|
48
|
+
end
|
49
|
+
end
|
42
50
|
end
|
43
51
|
end
|
44
52
|
end
|
@@ -42,6 +42,7 @@ module ShopifyTransporter
|
|
42
42
|
end
|
43
43
|
|
44
44
|
def tax_lines(item)
|
45
|
+
return unless tax_applied?(item)
|
45
46
|
[
|
46
47
|
{
|
47
48
|
title: 'Tax',
|
@@ -50,6 +51,10 @@ module ShopifyTransporter
|
|
50
51
|
}.stringify_keys,
|
51
52
|
]
|
52
53
|
end
|
54
|
+
|
55
|
+
def tax_applied?(item)
|
56
|
+
item['tax_percent'].to_f > 0 && item['tax_amount'].to_f > 0
|
57
|
+
end
|
53
58
|
end
|
54
59
|
end
|
55
60
|
end
|
@@ -12,10 +12,17 @@ module ShopifyTransporter
|
|
12
12
|
{
|
13
13
|
name: hash['increment_id'],
|
14
14
|
email: hash['customer_email'],
|
15
|
+
currency: hash['order_currency_code'],
|
16
|
+
cancelled_at: cancelled_at(hash),
|
17
|
+
closed_at: closed_at(hash),
|
15
18
|
processed_at: hash['created_at'],
|
16
19
|
subtotal_price: hash['subtotal'],
|
17
20
|
total_tax: hash['tax_amount'],
|
18
21
|
total_price: hash['grand_total'],
|
22
|
+
source_name: ORDER_ORIGINATED_FROM,
|
23
|
+
total_weight: hash['weight'],
|
24
|
+
financial_status: financial_status(hash),
|
25
|
+
fulfillment_status: fulfillment_status(hash),
|
19
26
|
}.stringify_keys
|
20
27
|
)
|
21
28
|
customer = build_customer(hash)
|
@@ -25,6 +32,8 @@ module ShopifyTransporter
|
|
25
32
|
|
26
33
|
private
|
27
34
|
|
35
|
+
ORDER_ORIGINATED_FROM = 'Magento'
|
36
|
+
|
28
37
|
def build_customer(hash)
|
29
38
|
{
|
30
39
|
email: hash['customer_email'],
|
@@ -32,6 +41,102 @@ module ShopifyTransporter
|
|
32
41
|
last_name: hash['customer_lastname'],
|
33
42
|
}.stringify_keys
|
34
43
|
end
|
44
|
+
|
45
|
+
def financial_status(hash)
|
46
|
+
order_state = hash['state']
|
47
|
+
status = nil
|
48
|
+
|
49
|
+
if order_state == 'Pending Payment'
|
50
|
+
status = 'pending'
|
51
|
+
elsif paid?(hash)
|
52
|
+
status = 'paid'
|
53
|
+
elsif partially_paid?(hash)
|
54
|
+
status = 'partially_paid'
|
55
|
+
elsif partially_refunded?(hash)
|
56
|
+
status = 'partially_refunded'
|
57
|
+
elsif refunded?(hash)
|
58
|
+
status = 'refunded'
|
59
|
+
end
|
60
|
+
status
|
61
|
+
end
|
62
|
+
|
63
|
+
def fulfillment_status(hash)
|
64
|
+
total_qty_ordered = hash['total_qty_ordered'].to_i
|
65
|
+
total_qty_shipped = total_qty_shipped(hash)
|
66
|
+
status = nil
|
67
|
+
|
68
|
+
if total_qty_shipped == total_qty_ordered
|
69
|
+
status = 'fulfilled'
|
70
|
+
elsif total_qty_shipped > 0 && total_qty_shipped < total_qty_ordered
|
71
|
+
status = 'partial'
|
72
|
+
end
|
73
|
+
status
|
74
|
+
end
|
75
|
+
|
76
|
+
def cancelled_at(hash)
|
77
|
+
timestamp(hash, 'canceled') if cancelled?(hash)
|
78
|
+
end
|
79
|
+
|
80
|
+
def closed_at(hash)
|
81
|
+
timestamp(hash, 'closed') if closed?(hash)
|
82
|
+
end
|
83
|
+
|
84
|
+
def cancelled?(hash)
|
85
|
+
hash['state'] == 'canceled'
|
86
|
+
end
|
87
|
+
|
88
|
+
def closed?(hash)
|
89
|
+
hash['state'] == 'closed'
|
90
|
+
end
|
91
|
+
|
92
|
+
def total_price(hash)
|
93
|
+
hash['grand_total'].to_i
|
94
|
+
end
|
95
|
+
|
96
|
+
def total_paid(hash)
|
97
|
+
return hash['total_paid'].to_i if hash['total_paid'].present?
|
98
|
+
0
|
99
|
+
end
|
100
|
+
|
101
|
+
def total_refunded(hash)
|
102
|
+
return hash['total_refunded'].to_i if hash['total_refunded'].present?
|
103
|
+
0
|
104
|
+
end
|
105
|
+
|
106
|
+
def paid?(hash)
|
107
|
+
total_price(hash) == total_paid(hash) && total_refunded(hash) == 0
|
108
|
+
end
|
109
|
+
|
110
|
+
def partially_paid?(hash)
|
111
|
+
total_paid(hash) > 0 && total_paid(hash) < total_price(hash) && total_refunded(hash) == 0
|
112
|
+
end
|
113
|
+
|
114
|
+
def partially_refunded?(hash)
|
115
|
+
total_refunded(hash) > 0 && total_refunded(hash) < total_paid(hash)
|
116
|
+
end
|
117
|
+
|
118
|
+
def refunded?(hash)
|
119
|
+
total_refunded(hash) == total_paid(hash) && total_refunded(hash) != 0
|
120
|
+
end
|
121
|
+
|
122
|
+
def total_qty_shipped(hash)
|
123
|
+
return 0 unless hash.dig('items', 'result', 'items', 'item').present?
|
124
|
+
line_items = hash['items']['result']['items']['item']
|
125
|
+
return line_items['qty_shipped'].to_i if line_items.is_a?(Hash)
|
126
|
+
line_items.map { |line_item| line_item['qty_shipped'].to_i }.sum
|
127
|
+
end
|
128
|
+
|
129
|
+
def timestamp(hash, status)
|
130
|
+
return unless hash.dig('items', 'result', 'status_history', 'item').present?
|
131
|
+
|
132
|
+
history_items = hash['items']['result']['status_history']['item']
|
133
|
+
return history_items['created_at'] if history_items.is_a?(Hash) && history_items['status'] == status
|
134
|
+
|
135
|
+
last_applicable_history_item = history_items.select do |history|
|
136
|
+
history['status'] == status
|
137
|
+
end.last
|
138
|
+
last_applicable_history_item['created_at'] if last_applicable_history_item.present?
|
139
|
+
end
|
35
140
|
end
|
36
141
|
end
|
37
142
|
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require 'shopify_transporter/pipeline/stage'
|
3
|
+
require 'shopify_transporter/shopify'
|
4
|
+
module ShopifyTransporter
|
5
|
+
module Pipeline
|
6
|
+
module Magento
|
7
|
+
module Order
|
8
|
+
class Transactions < Pipeline::Stage
|
9
|
+
def convert(input, record)
|
10
|
+
record.merge!(
|
11
|
+
{
|
12
|
+
transactions: transactions(input),
|
13
|
+
}.stringify_keys
|
14
|
+
)
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
def transactions(input)
|
20
|
+
[
|
21
|
+
sale_transaction(input),
|
22
|
+
refund_transaction(input),
|
23
|
+
].compact
|
24
|
+
end
|
25
|
+
|
26
|
+
def sale_transaction(input)
|
27
|
+
return unless input['total_paid'].present?
|
28
|
+
{
|
29
|
+
amount: input['total_paid'].to_f,
|
30
|
+
kind: 'sale',
|
31
|
+
status: 'success',
|
32
|
+
}.stringify_keys
|
33
|
+
end
|
34
|
+
|
35
|
+
def refund_transaction(input)
|
36
|
+
return unless input['total_refunded'].present?
|
37
|
+
{
|
38
|
+
amount: input['total_refunded'].to_f,
|
39
|
+
kind: 'refund',
|
40
|
+
status: 'success',
|
41
|
+
}.stringify_keys
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -25,8 +25,8 @@ module ShopifyTransporter
|
|
25
25
|
'Lineitem price', 'Lineitem discount', 'Lineitem compare at price', 'Lineitem sku',
|
26
26
|
'Lineitem requires shipping', 'Lineitem taxable', 'Lineitem fulfillment status',
|
27
27
|
'Tax 1 Title', 'Tax 1 Price', 'Tax 1 Rate', 'Tax 2 Title', 'Tax 2 Price', 'Tax 2 Rate',
|
28
|
-
'Tax 3 Title', 'Tax 3 Price', 'Tax 3 Rate', '
|
29
|
-
'Metafield Value', 'Metafield Value Type'
|
28
|
+
'Tax 3 Title', 'Tax 3 Price', 'Tax 3 Rate', 'Transaction amount', 'Transaction kind', 'Transaction status',
|
29
|
+
'Metafield Namespace', 'Metafield Key', 'Metafield Value', 'Metafield Value Type'
|
30
30
|
].to_csv
|
31
31
|
end
|
32
32
|
|
@@ -45,6 +45,7 @@ module ShopifyTransporter
|
|
45
45
|
CSV.generate do |csv|
|
46
46
|
csv << top_level_row_values
|
47
47
|
line_item_row_values.each { |row| csv << row }
|
48
|
+
transaction_row_values.each { |row| csv << row }
|
48
49
|
metafield_row_values.each { |row| csv << row }
|
49
50
|
end
|
50
51
|
end
|
@@ -67,6 +68,12 @@ module ShopifyTransporter
|
|
67
68
|
name quantity price discount compare_at_price sku requires_shipping taxable fulfillment_status
|
68
69
|
)
|
69
70
|
|
71
|
+
TRANSACTION_PREFIX = 'transaction_'
|
72
|
+
|
73
|
+
TRANSACTION_ATTRIBUTES = %w(
|
74
|
+
amount kind status
|
75
|
+
)
|
76
|
+
|
70
77
|
def address_hash_for(address_hash, prefix)
|
71
78
|
return {} if address_hash.blank?
|
72
79
|
|
@@ -102,6 +109,17 @@ module ShopifyTransporter
|
|
102
109
|
row_values_from(line_item) if self.class.has_values?(line_item)
|
103
110
|
end.compact
|
104
111
|
end
|
112
|
+
|
113
|
+
def transaction_row_values
|
114
|
+
return [] unless record_hash['transactions']
|
115
|
+
|
116
|
+
record_hash['transactions'].map do |transaction_hash|
|
117
|
+
transaction = transaction_hash.slice(*TRANSACTION_ATTRIBUTES)
|
118
|
+
.transform_keys! { |k| "#{TRANSACTION_PREFIX}#{k}" }
|
119
|
+
|
120
|
+
row_values_from(transaction) if self.class.has_values?(transaction)
|
121
|
+
end.compact
|
122
|
+
end
|
105
123
|
end
|
106
124
|
end
|
107
125
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: shopify_transporter
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.0
|
4
|
+
version: 2.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Shopify
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-10-
|
11
|
+
date: 2018-10-15 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -163,6 +163,7 @@ files:
|
|
163
163
|
- lib/shopify_transporter/pipeline/magento/order/addresses_attribute.rb
|
164
164
|
- lib/shopify_transporter/pipeline/magento/order/line_items.rb
|
165
165
|
- lib/shopify_transporter/pipeline/magento/order/top_level_attributes.rb
|
166
|
+
- lib/shopify_transporter/pipeline/magento/order/transactions.rb
|
166
167
|
- lib/shopify_transporter/pipeline/magento/product/top_level_attributes.rb
|
167
168
|
- lib/shopify_transporter/pipeline/magento/product/top_level_variant_attributes.rb
|
168
169
|
- lib/shopify_transporter/pipeline/magento/product/variant_attributes.rb
|