spree_cm_commissioner 2.5.13 → 2.5.14.pre.pre1
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/Gemfile.lock +1 -1
- data/app/controllers/spree/admin/classifications_controller.rb +4 -3
- data/app/jobs/spree_cm_commissioner/import_order_job.rb +2 -2
- data/app/models/spree_cm_commissioner/exports/operator_guest_json_gzip.rb +4 -1
- data/app/services/spree_cm_commissioner/imports/orders/base.rb +70 -0
- data/app/services/spree_cm_commissioner/imports/orders/create.rb +134 -0
- data/app/services/spree_cm_commissioner/imports/orders/update.rb +77 -0
- data/lib/spree_cm_commissioner/version.rb +1 -1
- metadata +7 -7
- data/app/services/spree_cm_commissioner/imports/base_import_order_service.rb +0 -55
- data/app/services/spree_cm_commissioner/imports/create_order_service.rb +0 -99
- data/app/services/spree_cm_commissioner/imports/update_order_service.rb +0 -41
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 629ae666350f41be96fbbffc7fca9d392eac8719b6e3de8bdc59d078aca7bc19
|
|
4
|
+
data.tar.gz: c8c92dbab08ee3019c49cc1ca3d13ec85eee50e85e0197bc05da6654f2bd2a90
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 91f9dfb5083aedf8e8d939962bcb190c78c5d7601352a947ddba56dfd18693ef21061a781137f45ec613445889113461f8739dbc5b660935c865a38186e1bdea
|
|
7
|
+
data.tar.gz: 5634021b1f30d8473163aed1dcc78346fb82cebb0f3bdcb469e420755a66c3d0fc62790c393063e5b5d78ce8be3401118fe41ba1e4e3a7cd3887cc5747741712
|
data/Gemfile.lock
CHANGED
|
@@ -7,9 +7,10 @@ module Spree
|
|
|
7
7
|
if @taxon.parent.event?
|
|
8
8
|
SpreeCmCommissioner::MaintenanceTasks::Event.pending.find_or_create_by(
|
|
9
9
|
maintainable_type: 'Spree::Taxon',
|
|
10
|
-
maintainable_id: @taxon.parent.id
|
|
11
|
-
|
|
12
|
-
|
|
10
|
+
maintainable_id: @taxon.parent.id
|
|
11
|
+
) do |task|
|
|
12
|
+
task.manually_triggered = true
|
|
13
|
+
end.async_execute
|
|
13
14
|
|
|
14
15
|
flash[:success] = flash_message_for(@taxon, :successfully_updated)
|
|
15
16
|
else
|
|
@@ -2,12 +2,12 @@ module SpreeCmCommissioner
|
|
|
2
2
|
class ImportOrderJob < ApplicationUniqueJob
|
|
3
3
|
def perform(options = {})
|
|
4
4
|
if options[:import_type] == 'new_order'
|
|
5
|
-
SpreeCmCommissioner::Imports::
|
|
5
|
+
SpreeCmCommissioner::Imports::Orders::Create.new(
|
|
6
6
|
import_order_id: options[:import_order_id],
|
|
7
7
|
import_by_user_id: options[:import_by_user_id]
|
|
8
8
|
).call
|
|
9
9
|
else
|
|
10
|
-
SpreeCmCommissioner::Imports::
|
|
10
|
+
SpreeCmCommissioner::Imports::Orders::Update.new(
|
|
11
11
|
import_order_id: options[:import_order_id]
|
|
12
12
|
).call
|
|
13
13
|
end
|
|
@@ -33,7 +33,8 @@ module SpreeCmCommissioner
|
|
|
33
33
|
output_gz_file = Tempfile.new(['export', '.json.gz'])
|
|
34
34
|
|
|
35
35
|
begin
|
|
36
|
-
stream_export_data_and_includes_to_separate_files(guests_query, guests_file, included_file)
|
|
36
|
+
total_processed = stream_export_data_and_includes_to_separate_files(guests_query, guests_file, included_file)
|
|
37
|
+
self.guests_count = total_processed
|
|
37
38
|
stream_export_merge_and_compress_data_and_includes_to_a_single_file(guests_file, included_file, output_gz_file)
|
|
38
39
|
attach_file_to_record(output_gz_file)
|
|
39
40
|
ensure
|
|
@@ -98,6 +99,8 @@ module SpreeCmCommissioner
|
|
|
98
99
|
update(track_processed_messages: track_processed_messages.last(50))
|
|
99
100
|
end
|
|
100
101
|
end
|
|
102
|
+
|
|
103
|
+
total_processed_guests
|
|
101
104
|
end
|
|
102
105
|
|
|
103
106
|
def stream_export_merge_and_compress_data_and_includes_to_a_single_file(guests_file, included_file, output_gz_file)
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
require 'tempfile'
|
|
2
|
+
|
|
3
|
+
module SpreeCmCommissioner
|
|
4
|
+
module Imports
|
|
5
|
+
module Orders
|
|
6
|
+
class Base
|
|
7
|
+
attr_reader :import_order_id, :fail_row_numbers
|
|
8
|
+
|
|
9
|
+
def initialize(import_order_id:)
|
|
10
|
+
@import_order_id = import_order_id
|
|
11
|
+
@fail_row_numbers = []
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def call
|
|
15
|
+
update_import_status_when_start(:progress)
|
|
16
|
+
import_orders
|
|
17
|
+
save_fail_rows
|
|
18
|
+
update_import_status_when_finish(:done)
|
|
19
|
+
rescue StandardError => e
|
|
20
|
+
update_import_status_when_finish(:failed)
|
|
21
|
+
raise e
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def save_fail_rows
|
|
25
|
+
import_order.update!(preferred_fail_rows: @fail_row_numbers.join(', ')) unless @fail_row_numbers.empty?
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def record_failure(row_number)
|
|
29
|
+
@fail_row_numbers << row_number
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def import_order
|
|
33
|
+
@import_order ||= SpreeCmCommissioner::Imports::ImportOrder.find(import_order_id)
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def update_import_status_when_start(status)
|
|
37
|
+
import_order.update(status: status, started_at: Time.zone.now)
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def update_import_status_when_finish(status)
|
|
41
|
+
import_order.update(status: status, finished_at: Time.zone.now)
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def fetch_content
|
|
45
|
+
url = import_order.imported_file.url
|
|
46
|
+
temp_file = Tempfile.new(['import', '.csv'], binmode: true)
|
|
47
|
+
|
|
48
|
+
begin
|
|
49
|
+
response = Faraday.get(url) do |req|
|
|
50
|
+
req.options.on_data = proc { |chunk| temp_file.write(chunk) }
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
raise "HTTP request failed with status #{response.status}" unless response.success?
|
|
54
|
+
|
|
55
|
+
temp_file.close
|
|
56
|
+
temp_file.path
|
|
57
|
+
rescue StandardError
|
|
58
|
+
temp_file.close
|
|
59
|
+
temp_file.unlink
|
|
60
|
+
raise
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def cleaned_value(value)
|
|
65
|
+
value.to_s.gsub(/\s+/, '')
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
end
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
require 'tempfile'
|
|
2
|
+
|
|
3
|
+
module SpreeCmCommissioner
|
|
4
|
+
module Imports
|
|
5
|
+
module Orders
|
|
6
|
+
class Create < Base
|
|
7
|
+
BATCH_SIZE = 100
|
|
8
|
+
|
|
9
|
+
attr_reader :import_by_user_id
|
|
10
|
+
|
|
11
|
+
def initialize(import_order_id:, import_by_user_id:)
|
|
12
|
+
super(import_order_id: import_order_id)
|
|
13
|
+
@import_by_user_id = import_by_user_id
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def import_orders
|
|
17
|
+
# Processes CSV orders in a memory-efficient streaming manner to handle large files (50k+ rows).
|
|
18
|
+
# Batches rows into groups of 100 for reduced DB transaction overhead and atomicity per batch.
|
|
19
|
+
# Uses CSV.foreach to stream from disk, avoiding memory spikes. Row indices start at 2 (post-header).
|
|
20
|
+
file_path = fetch_content
|
|
21
|
+
batch = []
|
|
22
|
+
|
|
23
|
+
begin
|
|
24
|
+
CSV.foreach(file_path, headers: true).with_index(2) do |row, index|
|
|
25
|
+
batch << [row.to_hash.symbolize_keys, index]
|
|
26
|
+
|
|
27
|
+
if batch.size >= BATCH_SIZE
|
|
28
|
+
process_batch(batch)
|
|
29
|
+
batch = []
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
process_batch(batch) unless batch.empty?
|
|
34
|
+
ensure
|
|
35
|
+
FileUtils.rm_f(file_path)
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def process_batch(batch)
|
|
40
|
+
# Processes a batch of orders with each row in its own transaction for error isolation.
|
|
41
|
+
# Failures record but don't affect other rows, allowing partial batch success.
|
|
42
|
+
batch.each do |order_data, index|
|
|
43
|
+
ActiveRecord::Base.transaction do
|
|
44
|
+
process_order(order_data, index)
|
|
45
|
+
rescue StandardError => e
|
|
46
|
+
CmAppLogger.error(
|
|
47
|
+
label: "#{self.class.name}::process_batch",
|
|
48
|
+
data: { message: e.message, row: index }
|
|
49
|
+
)
|
|
50
|
+
record_failure(index)
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def process_order(order_data, index)
|
|
56
|
+
params = build_order_params(order_data)
|
|
57
|
+
order = create_order(params, index)
|
|
58
|
+
record_failure(index) if order && !complete_order(order)
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
private
|
|
62
|
+
|
|
63
|
+
def build_order_params(order_data)
|
|
64
|
+
guest_attributes = order_data.slice(*SpreeCmCommissioner::Guest.csv_importable_columns)
|
|
65
|
+
channel = construct_channel(
|
|
66
|
+
order_data[:variant_id].present? ? 'google_form' : order_data[:order_channel]
|
|
67
|
+
)
|
|
68
|
+
|
|
69
|
+
common_attrs = {
|
|
70
|
+
channel: channel,
|
|
71
|
+
email: order_data[:email],
|
|
72
|
+
phone_number: order_data[:phone_number]
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
line_item_attrs =
|
|
76
|
+
if order_data[:variant_id].present?
|
|
77
|
+
{
|
|
78
|
+
quantity: 1,
|
|
79
|
+
variant_id: order_data[:variant_id].to_i,
|
|
80
|
+
guests_attributes: Array.new(1, guest_attributes)
|
|
81
|
+
}
|
|
82
|
+
else
|
|
83
|
+
{
|
|
84
|
+
quantity: order_data[:quantity].to_i,
|
|
85
|
+
sku: order_data[:variant_sku],
|
|
86
|
+
guests_attributes: Array.new(order_data[:quantity].to_i, guest_attributes)
|
|
87
|
+
}
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
common_attrs.merge(line_items_attributes: [line_item_attrs])
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
def create_order(params, index)
|
|
94
|
+
order = Spree::Core::Importer::Order.import(import_by, params)
|
|
95
|
+
|
|
96
|
+
unless order
|
|
97
|
+
record_failure(index)
|
|
98
|
+
return nil
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
order
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
def complete_order(order)
|
|
105
|
+
# Wraps order completion and inventory update in a transaction to ensure atomicity.
|
|
106
|
+
# If either the order update or inventory update fails, both operations will be rolled back.
|
|
107
|
+
# This prevents partial updates that could lead to data inconsistency.
|
|
108
|
+
order.unstock_inventory! do
|
|
109
|
+
order.update!(
|
|
110
|
+
completed_at: Time.zone.now,
|
|
111
|
+
state: 'complete',
|
|
112
|
+
payment_total: order.total,
|
|
113
|
+
payment_state: 'paid'
|
|
114
|
+
)
|
|
115
|
+
end
|
|
116
|
+
rescue StandardError => e
|
|
117
|
+
CmAppLogger.error(
|
|
118
|
+
label: "#{self.class.name}::complete_order",
|
|
119
|
+
data: { message: e.message, order_id: order.id }
|
|
120
|
+
)
|
|
121
|
+
false
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
def import_by
|
|
125
|
+
@import_by ||= Spree::User.find(import_by_user_id)
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
def construct_channel(order_channel)
|
|
129
|
+
"#{order_channel}-#{import_order.id}-#{import_order.slug}"
|
|
130
|
+
end
|
|
131
|
+
end
|
|
132
|
+
end
|
|
133
|
+
end
|
|
134
|
+
end
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
module SpreeCmCommissioner
|
|
2
|
+
module Imports
|
|
3
|
+
module Orders
|
|
4
|
+
class Update < Base
|
|
5
|
+
BATCH_SIZE = 100
|
|
6
|
+
|
|
7
|
+
def import_orders
|
|
8
|
+
file_path = fetch_content
|
|
9
|
+
batch = []
|
|
10
|
+
|
|
11
|
+
begin
|
|
12
|
+
CSV.foreach(file_path, headers: true).with_index(2) do |row, index|
|
|
13
|
+
batch << [row, index]
|
|
14
|
+
|
|
15
|
+
if batch.size >= BATCH_SIZE
|
|
16
|
+
process_batch(batch)
|
|
17
|
+
batch = []
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
process_batch(batch) unless batch.empty?
|
|
22
|
+
ensure
|
|
23
|
+
FileUtils.rm_f(file_path)
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def process_batch(batch)
|
|
28
|
+
batch.each do |row, index|
|
|
29
|
+
ActiveRecord::Base.transaction do
|
|
30
|
+
process_row(row, index)
|
|
31
|
+
rescue StandardError
|
|
32
|
+
record_failure(index)
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def process_row(row, index)
|
|
38
|
+
order_number = cleaned_value(row['order_number'])
|
|
39
|
+
order = Spree::Order.find_by(number: order_number)
|
|
40
|
+
|
|
41
|
+
unless order
|
|
42
|
+
record_failure(index)
|
|
43
|
+
return
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
guest_id = cleaned_value(row['guest_id'])
|
|
47
|
+
seat_number = cleaned_value(row['seat_number'])
|
|
48
|
+
|
|
49
|
+
guest =
|
|
50
|
+
order.guests.find_by(seat_number: seat_number) ||
|
|
51
|
+
order.guests.find_by(id: guest_id)
|
|
52
|
+
|
|
53
|
+
unless guest
|
|
54
|
+
record_failure(index)
|
|
55
|
+
return
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
guest_data = row.to_hash
|
|
59
|
+
.symbolize_keys
|
|
60
|
+
.slice(*SpreeCmCommissioner::Guest.csv_importable_columns)
|
|
61
|
+
|
|
62
|
+
guest_data.compact_blank!
|
|
63
|
+
|
|
64
|
+
if guest.update(guest_data)
|
|
65
|
+
recalculate_order(order)
|
|
66
|
+
else
|
|
67
|
+
record_failure(index)
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def recalculate_order(order)
|
|
72
|
+
order.update_with_updater!
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
end
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: spree_cm_commissioner
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 2.5.
|
|
4
|
+
version: 2.5.14.pre.pre1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- You
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-02-
|
|
11
|
+
date: 2026-02-19 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: spree
|
|
@@ -2032,9 +2032,9 @@ files:
|
|
|
2032
2032
|
- app/services/spree_cm_commissioner/guests/preload_check_in_session_ids.rb
|
|
2033
2033
|
- app/services/spree_cm_commissioner/homepage_data.rb
|
|
2034
2034
|
- app/services/spree_cm_commissioner/homepage_data_loader.rb
|
|
2035
|
-
- app/services/spree_cm_commissioner/imports/
|
|
2036
|
-
- app/services/spree_cm_commissioner/imports/
|
|
2037
|
-
- app/services/spree_cm_commissioner/imports/
|
|
2035
|
+
- app/services/spree_cm_commissioner/imports/orders/base.rb
|
|
2036
|
+
- app/services/spree_cm_commissioner/imports/orders/create.rb
|
|
2037
|
+
- app/services/spree_cm_commissioner/imports/orders/update.rb
|
|
2038
2038
|
- app/services/spree_cm_commissioner/integrations/base/sync_manager.rb
|
|
2039
2039
|
- app/services/spree_cm_commissioner/integrations/base/sync_result.rb
|
|
2040
2040
|
- app/services/spree_cm_commissioner/integrations/cleanup_sync_sessions.rb
|
|
@@ -3215,9 +3215,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
3215
3215
|
version: '2.7'
|
|
3216
3216
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
3217
3217
|
requirements:
|
|
3218
|
-
- - "
|
|
3218
|
+
- - ">"
|
|
3219
3219
|
- !ruby/object:Gem::Version
|
|
3220
|
-
version:
|
|
3220
|
+
version: 1.3.1
|
|
3221
3221
|
requirements:
|
|
3222
3222
|
- none
|
|
3223
3223
|
rubygems_version: 3.4.1
|
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
module SpreeCmCommissioner
|
|
2
|
-
module Imports
|
|
3
|
-
class BaseImportOrderService
|
|
4
|
-
attr_reader :import_order_id, :fail_row_numbers
|
|
5
|
-
|
|
6
|
-
def initialize(import_order_id:)
|
|
7
|
-
@import_order_id = import_order_id
|
|
8
|
-
@fail_row_numbers = []
|
|
9
|
-
end
|
|
10
|
-
|
|
11
|
-
def call
|
|
12
|
-
update_import_status_when_start(:progress)
|
|
13
|
-
import_orders
|
|
14
|
-
save_fail_rows
|
|
15
|
-
update_import_status_when_finish(:done)
|
|
16
|
-
rescue StandardError => e
|
|
17
|
-
update_import_status_when_finish(:failed)
|
|
18
|
-
raise e
|
|
19
|
-
end
|
|
20
|
-
|
|
21
|
-
def save_fail_rows
|
|
22
|
-
import_order.update!(preferred_fail_rows: @fail_row_numbers.join(', ')) unless @fail_row_numbers.empty?
|
|
23
|
-
end
|
|
24
|
-
|
|
25
|
-
def record_failure(row_number)
|
|
26
|
-
@fail_row_numbers << row_number
|
|
27
|
-
end
|
|
28
|
-
|
|
29
|
-
def import_order
|
|
30
|
-
@import_order ||= SpreeCmCommissioner::Imports::ImportOrder.find(import_order_id)
|
|
31
|
-
end
|
|
32
|
-
|
|
33
|
-
def update_import_status_when_start(status)
|
|
34
|
-
import_order.update(status: status, started_at: Time.zone.now)
|
|
35
|
-
end
|
|
36
|
-
|
|
37
|
-
def update_import_status_when_finish(status)
|
|
38
|
-
import_order.update(status: status, finished_at: Time.zone.now)
|
|
39
|
-
end
|
|
40
|
-
|
|
41
|
-
def fetch_content
|
|
42
|
-
url = import_order.imported_file.url
|
|
43
|
-
response = Faraday.get(url)
|
|
44
|
-
|
|
45
|
-
raise "Failed to fetch content: #{response.status}" unless response.success?
|
|
46
|
-
|
|
47
|
-
response.body
|
|
48
|
-
end
|
|
49
|
-
|
|
50
|
-
def cleaned_value(value)
|
|
51
|
-
value.to_s.gsub(/\s+/, '')
|
|
52
|
-
end
|
|
53
|
-
end
|
|
54
|
-
end
|
|
55
|
-
end
|
|
@@ -1,99 +0,0 @@
|
|
|
1
|
-
module SpreeCmCommissioner
|
|
2
|
-
module Imports
|
|
3
|
-
class CreateOrderService < BaseImportOrderService
|
|
4
|
-
attr_reader :import_by_user_id
|
|
5
|
-
|
|
6
|
-
def initialize(import_order_id:, import_by_user_id:)
|
|
7
|
-
super(import_order_id: import_order_id)
|
|
8
|
-
@import_by_user_id = import_by_user_id
|
|
9
|
-
end
|
|
10
|
-
|
|
11
|
-
def import_orders
|
|
12
|
-
content = fetch_content
|
|
13
|
-
|
|
14
|
-
CSV.parse(content, headers: true).each.with_index(2) do |row, index|
|
|
15
|
-
order_data = row.to_hash.symbolize_keys
|
|
16
|
-
process_order(order_data, index)
|
|
17
|
-
end
|
|
18
|
-
end
|
|
19
|
-
|
|
20
|
-
def process_order(order_data, index)
|
|
21
|
-
ActiveRecord::Base.transaction do
|
|
22
|
-
params = build_order_params(order_data)
|
|
23
|
-
order = create_order(params, index)
|
|
24
|
-
record_failure(index) if order && !complete_order(order)
|
|
25
|
-
end
|
|
26
|
-
rescue StandardError
|
|
27
|
-
record_failure(index)
|
|
28
|
-
end
|
|
29
|
-
|
|
30
|
-
private
|
|
31
|
-
|
|
32
|
-
def build_order_params(order_data)
|
|
33
|
-
guest_attributes = order_data.slice(*SpreeCmCommissioner::Guest.csv_importable_columns)
|
|
34
|
-
if order_data[:variant_id].present?
|
|
35
|
-
{
|
|
36
|
-
channel: construct_channel('google_form'),
|
|
37
|
-
email: order_data[:email],
|
|
38
|
-
phone_number: order_data[:phone_number],
|
|
39
|
-
line_items_attributes: [
|
|
40
|
-
{
|
|
41
|
-
quantity: 1,
|
|
42
|
-
variant_id: order_data[:variant_id].to_i,
|
|
43
|
-
guests_attributes: Array.new(1, guest_attributes)
|
|
44
|
-
}
|
|
45
|
-
]
|
|
46
|
-
}
|
|
47
|
-
else
|
|
48
|
-
{
|
|
49
|
-
channel: construct_channel(order_data[:order_channel]),
|
|
50
|
-
email: order_data[:email],
|
|
51
|
-
phone_number: order_data[:phone_number],
|
|
52
|
-
line_items_attributes: [
|
|
53
|
-
{
|
|
54
|
-
quantity: order_data[:quantity].to_i,
|
|
55
|
-
sku: order_data[:variant_sku],
|
|
56
|
-
guests_attributes: Array.new(order_data[:quantity].to_i, guest_attributes)
|
|
57
|
-
}
|
|
58
|
-
]
|
|
59
|
-
}
|
|
60
|
-
end
|
|
61
|
-
end
|
|
62
|
-
|
|
63
|
-
def create_order(params, index)
|
|
64
|
-
order = Spree::Core::Importer::Order.import(import_by, params)
|
|
65
|
-
unless order
|
|
66
|
-
record_failure(index)
|
|
67
|
-
return nil
|
|
68
|
-
end
|
|
69
|
-
|
|
70
|
-
order
|
|
71
|
-
end
|
|
72
|
-
|
|
73
|
-
def complete_order(order)
|
|
74
|
-
# Wraps order completion and inventory update in a transaction to ensure atomicity.
|
|
75
|
-
# If either the order update or inventory update fails, both operations will be rolled back.
|
|
76
|
-
# This prevents partial updates that could lead to data inconsistency.
|
|
77
|
-
order.unstock_inventory! do
|
|
78
|
-
order.update!(
|
|
79
|
-
completed_at: Time.zone.now,
|
|
80
|
-
state: 'complete',
|
|
81
|
-
payment_total: order.total,
|
|
82
|
-
payment_state: 'paid'
|
|
83
|
-
)
|
|
84
|
-
end
|
|
85
|
-
rescue StandardError => e
|
|
86
|
-
AppLogger.error("#{self.class.name}::#complete_order failed for Order ID #{order.id}: #{e.message}")
|
|
87
|
-
false
|
|
88
|
-
end
|
|
89
|
-
|
|
90
|
-
def import_by
|
|
91
|
-
@import_by ||= Spree::User.find(import_by_user_id)
|
|
92
|
-
end
|
|
93
|
-
|
|
94
|
-
def construct_channel(order_channel)
|
|
95
|
-
"#{order_channel}-#{import_order.id}-#{import_order.slug}"
|
|
96
|
-
end
|
|
97
|
-
end
|
|
98
|
-
end
|
|
99
|
-
end
|
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
module SpreeCmCommissioner
|
|
2
|
-
module Imports
|
|
3
|
-
class UpdateOrderService < BaseImportOrderService
|
|
4
|
-
def import_orders
|
|
5
|
-
content = fetch_content
|
|
6
|
-
|
|
7
|
-
CSV.parse(content, headers: true).each.with_index(2) do |row, index|
|
|
8
|
-
order_number = cleaned_value(row['order_number'])
|
|
9
|
-
order = Spree::Order.find_by(number: order_number)
|
|
10
|
-
|
|
11
|
-
unless order
|
|
12
|
-
record_failure(index)
|
|
13
|
-
next
|
|
14
|
-
end
|
|
15
|
-
|
|
16
|
-
guest_id = cleaned_value(row['guest_id'])
|
|
17
|
-
seat_number = cleaned_value(row['seat_number'])
|
|
18
|
-
guest = order.guests.find_by(seat_number: seat_number) || order.guests.find_by(id: guest_id)
|
|
19
|
-
|
|
20
|
-
unless guest
|
|
21
|
-
record_failure(index)
|
|
22
|
-
next
|
|
23
|
-
end
|
|
24
|
-
|
|
25
|
-
guest_data = row.to_hash.symbolize_keys.slice(*SpreeCmCommissioner::Guest.csv_importable_columns)
|
|
26
|
-
guest_data.compact_blank!
|
|
27
|
-
|
|
28
|
-
if guest.update(guest_data)
|
|
29
|
-
recalculate_order(order)
|
|
30
|
-
else
|
|
31
|
-
record_failure(index)
|
|
32
|
-
end
|
|
33
|
-
end
|
|
34
|
-
end
|
|
35
|
-
|
|
36
|
-
def recalculate_order(order)
|
|
37
|
-
order.update_with_updater!
|
|
38
|
-
end
|
|
39
|
-
end
|
|
40
|
-
end
|
|
41
|
-
end
|