spree_cm_commissioner 2.5.14.pre.pre1 → 2.5.14.pre.pre2

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 629ae666350f41be96fbbffc7fca9d392eac8719b6e3de8bdc59d078aca7bc19
4
- data.tar.gz: c8c92dbab08ee3019c49cc1ca3d13ec85eee50e85e0197bc05da6654f2bd2a90
3
+ metadata.gz: 9fc822ca647b6847cc80bc5d4f24f68312c67c3cf772e8422801f29d36b8c871
4
+ data.tar.gz: ac27932993e5c366efcfe5d1f15491c7b0248a886f0d804af69545a28a6a83cd
5
5
  SHA512:
6
- metadata.gz: 91f9dfb5083aedf8e8d939962bcb190c78c5d7601352a947ddba56dfd18693ef21061a781137f45ec613445889113461f8739dbc5b660935c865a38186e1bdea
7
- data.tar.gz: 5634021b1f30d8473163aed1dcc78346fb82cebb0f3bdcb469e420755a66c3d0fc62790c393063e5b5d78ce8be3401118fe41ba1e4e3a7cd3887cc5747741712
6
+ metadata.gz: 6030cee41764d55a73430c81849bc91b12dcf12c04097795c3646297e75c53b3206ca186a704a6603eddcb6a57e4226d437e25227bf6a005fe514ea784891d26
7
+ data.tar.gz: d48e1f3ec06affa85260babeea658b9a9cb95ddffffe01175fa9dd24837df25c2a087fd5e4dbc3849ce2592178db9d71793719c21e783ca425820b226f142862
data/Gemfile.lock CHANGED
@@ -34,7 +34,7 @@ GIT
34
34
  PATH
35
35
  remote: .
36
36
  specs:
37
- spree_cm_commissioner (2.5.14.pre.pre1)
37
+ spree_cm_commissioner (2.5.14.pre.pre2)
38
38
  activerecord-multi-tenant
39
39
  activerecord_json_validator (~> 2.1, >= 2.1.3)
40
40
  aws-sdk-cloudfront
@@ -7,10 +7,9 @@ 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
- ) do |task|
12
- task.manually_triggered = true
13
- end.async_execute
10
+ maintainable_id: @taxon.parent.id,
11
+ manually_triggered: true
12
+ ).async_execute
14
13
 
15
14
  flash[:success] = flash_message_for(@taxon, :successfully_updated)
16
15
  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::Orders::Create.new(
5
+ SpreeCmCommissioner::Imports::CreateOrderService.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::Orders::Update.new(
10
+ SpreeCmCommissioner::Imports::UpdateOrderService.new(
11
11
  import_order_id: options[:import_order_id]
12
12
  ).call
13
13
  end
@@ -33,8 +33,7 @@ module SpreeCmCommissioner
33
33
  output_gz_file = Tempfile.new(['export', '.json.gz'])
34
34
 
35
35
  begin
36
- total_processed = stream_export_data_and_includes_to_separate_files(guests_query, guests_file, included_file)
37
- self.guests_count = total_processed
36
+ stream_export_data_and_includes_to_separate_files(guests_query, guests_file, included_file)
38
37
  stream_export_merge_and_compress_data_and_includes_to_a_single_file(guests_file, included_file, output_gz_file)
39
38
  attach_file_to_record(output_gz_file)
40
39
  ensure
@@ -99,8 +98,6 @@ module SpreeCmCommissioner
99
98
  update(track_processed_messages: track_processed_messages.last(50))
100
99
  end
101
100
  end
102
-
103
- total_processed_guests
104
101
  end
105
102
 
106
103
  def stream_export_merge_and_compress_data_and_includes_to_a_single_file(guests_file, included_file, output_gz_file)
@@ -8,12 +8,23 @@ module SpreeCmCommissioner
8
8
 
9
9
  confirmed_at ||= Time.current
10
10
  guest_ids = check_ins_attributes.pluck(:guest_id)
11
- indexed_guests = SpreeCmCommissioner::Guest.where(id: guest_ids).index_by(&:id)
11
+
12
+ indexed_guests = SpreeCmCommissioner::Guest
13
+ .includes(:event, line_item: :order)
14
+ .where(id: guest_ids)
15
+ .index_by(&:id)
12
16
 
13
17
  check_ins = ActiveRecord::Base.transaction do
14
18
  check_ins_attributes.map do |attrs|
15
19
  guest = indexed_guests[attrs[:guest_id].to_i]
16
- raise ActiveRecord::RecordNotFound, "Couldn't find Guest with 'id'=#{attrs[:guest_id]}" if guest.blank?
20
+ raise ActiveRecord::RecordNotFound, "Couldn't find Guest to check in" if guest.blank?
21
+
22
+ order = guest.line_item.order
23
+ if order.canceled?
24
+ error = ActiveRecord::RecordInvalid.new(guest)
25
+ error.record.errors.add(:base, 'Cannot check in Guest from cancelled order')
26
+ raise error
27
+ end
17
28
 
18
29
  check_in = check_in!(guest, attrs, check_in_by, confirmed_at)
19
30
  update_guest!(guest, attrs[:guest_attributes]) if attrs[:guest_attributes].present?
@@ -25,8 +36,8 @@ module SpreeCmCommissioner
25
36
  success(check_ins: check_ins)
26
37
  rescue ActiveRecord::RecordInvalid => e
27
38
  failure(:invalid_record, e.record.errors.full_messages.join(', '))
28
- rescue ActiveRecord::RecordNotFound => e
29
- failure(:record_not_found, e.message)
39
+ rescue ActiveRecord::RecordNotFound
40
+ failure(:record_not_found, 'Guest or related record not found')
30
41
  end
31
42
 
32
43
  private
@@ -0,0 +1,55 @@
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
@@ -0,0 +1,99 @@
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
@@ -0,0 +1,41 @@
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
@@ -29,6 +29,8 @@ module SpreeCmCommissioner
29
29
  def fetch_value(guest, column)
30
30
  if guest_field?(column)
31
31
  fetch_guest_value(guest, column)
32
+ elsif dynamic_field?(column)
33
+ fetch_dynamic_field_value(guest, column)
32
34
  else
33
35
  fetch_option_value(guest, column)
34
36
  end
@@ -38,6 +40,39 @@ module SpreeCmCommissioner
38
40
  SpreeCmCommissioner::KycBitwise::ORDERED_BIT_FIELDS.include?(column.to_sym)
39
41
  end
40
42
 
43
+ def dynamic_field?(column)
44
+ return false unless dynamic_fields_exist?
45
+
46
+ dynamic_field_labels.include?(column)
47
+ end
48
+
49
+ def dynamic_field_labels
50
+ return [] unless dynamic_fields_exist?
51
+
52
+ @dynamic_field_labels ||= load_dynamic_field_labels
53
+ end
54
+
55
+ def dynamic_fields_exist?
56
+ return @has_dynamic_fields unless @has_dynamic_fields.nil?
57
+
58
+ @has_dynamic_fields = event.event_products.joins(:product_dynamic_fields).exists?
59
+ end
60
+
61
+ def load_dynamic_field_labels
62
+ event.event_products.joins(product_dynamic_fields: :dynamic_field).distinct.pluck('label')
63
+ end
64
+
65
+ def fetch_dynamic_field_value(guest, column)
66
+ guest_dynamic_field = guest.guest_dynamic_fields.find { |gdf| gdf.dynamic_field&.label == column }
67
+ return '' unless guest_dynamic_field
68
+
69
+ if guest_dynamic_field.dynamic_field_option.present?
70
+ guest_dynamic_field.dynamic_field_option.value
71
+ else
72
+ guest_dynamic_field.value || ''
73
+ end
74
+ end
75
+
41
76
  def fetch_guest_value(guest, column)
42
77
  column_mappings(guest)[column] || ''
43
78
  end
@@ -82,6 +117,7 @@ module SpreeCmCommissioner
82
117
  :occupation,
83
118
  :nationality,
84
119
  :id_card,
120
+ guest_dynamic_fields: %i[dynamic_field dynamic_field_option],
85
121
  line_item: { variant: { option_values: :option_type } }
86
122
  ).complete
87
123
  scope = scope.where('cm_guests.created_at >= ?', formatted_date_time(filters[:from_date])) if filters[:from_date].present?
@@ -1,5 +1,5 @@
1
1
  module SpreeCmCommissioner
2
- VERSION = '2.5.14-pre1'.freeze
2
+ VERSION = '2.5.14.pre.pre2'.freeze
3
3
 
4
4
  module_function
5
5
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: spree_cm_commissioner
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.5.14.pre.pre1
4
+ version: 2.5.14.pre.pre2
5
5
  platform: ruby
6
6
  authors:
7
7
  - You
@@ -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/orders/base.rb
2036
- - app/services/spree_cm_commissioner/imports/orders/create.rb
2037
- - app/services/spree_cm_commissioner/imports/orders/update.rb
2035
+ - app/services/spree_cm_commissioner/imports/base_import_order_service.rb
2036
+ - app/services/spree_cm_commissioner/imports/create_order_service.rb
2037
+ - app/services/spree_cm_commissioner/imports/update_order_service.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
@@ -1,70 +0,0 @@
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
@@ -1,134 +0,0 @@
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
@@ -1,77 +0,0 @@
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