spree_cm_commissioner 2.5.0.pre.pre14 → 2.5.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 (32) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile.lock +1 -1
  3. data/app/assets/images/mailer/call.png +0 -0
  4. data/app/assets/images/mailer/email.png +0 -0
  5. data/app/assets/images/mailer/user-tenant.png +0 -0
  6. data/app/controllers/spree_cm_commissioner/admin/orders_controller_decorator.rb +9 -1
  7. data/app/models/spree_cm_commissioner/order_decorator.rb +14 -1
  8. data/app/models/spree_cm_commissioner/saved_guest.rb +2 -0
  9. data/app/overrides/spree/admin/orders/_order_actions/actions.html.erb.deface +36 -1
  10. data/app/services/spree_cm_commissioner/vendor_places/create_with_google_map_data.rb +24 -7
  11. data/app/services/spree_cm_commissioner/vendor_places/update.rb +4 -2
  12. data/app/views/spree/order_mailer/cancel_email.html.erb +0 -2
  13. data/app/views/spree/order_mailer/confirm_email.html.erb +2 -2
  14. data/app/views/spree_cm_commissioner/cancel_order_mailer/_cancel_email.html.erb +5 -4
  15. data/app/views/spree_cm_commissioner/cancel_order_mailer/_mailer_stylesheets.html.erb +0 -51
  16. data/app/views/spree_cm_commissioner/cancel_order_mailer/tenant/_cancel_email.html.erb +5 -4
  17. data/app/views/spree_cm_commissioner/layouts/order_mailer.html.erb +1 -1
  18. data/app/views/spree_cm_commissioner/order_mailer/_customer_info.html.erb +2 -8
  19. data/app/views/spree_cm_commissioner/order_mailer/_mailer_stylesheets.html.erb +51 -23
  20. data/app/views/spree_cm_commissioner/order_mailer/_support_contact.html.erb +2 -7
  21. data/app/views/spree_cm_commissioner/order_mailer/purchased_items/_items.html.erb +76 -42
  22. data/app/views/spree_cm_commissioner/order_mailer/tenant/_customer_info.html.erb +4 -10
  23. data/app/views/spree_cm_commissioner/order_mailer/tenant/_support_contact.html.erb +3 -8
  24. data/config/locales/en.yml +1 -2
  25. data/config/locales/km.yml +1 -2
  26. data/db/migrate/20260105072146_add_nationality_group_and_age_group_to_cm_saved_guests.rb +6 -0
  27. data/db/migrate/20260106093359_add_contact_phone_to_cm_vendor_places.rb +5 -0
  28. data/lib/spree_cm_commissioner/version.rb +1 -1
  29. metadata +9 -7
  30. data/app/views/spree_cm_commissioner/cancel_order_mailer/_your_booking.html.erb +0 -8
  31. data/app/views/spree_cm_commissioner/cancel_order_mailer/purchased_items/_items.html.erb +0 -53
  32. data/app/views/spree_cm_commissioner/cancel_order_mailer/purchased_items/_summary.html.erb +0 -108
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1a284ecbc4094b414d407ecc02ee8892b199ff39ea3049b79c9ab9feb1f56545
4
- data.tar.gz: 0df5f1a16d68f0927ccbff0e265c7984343853f31e2c6d9473b0818f5013a9ef
3
+ metadata.gz: d5557d617bd3e8ccabfd0aa1f71fb307e487a44ae4c57b293876895f0cd8a65d
4
+ data.tar.gz: d78139ff783ca22c00466d4cab53029be917351ef53bc705a0864d63c173a44e
5
5
  SHA512:
6
- metadata.gz: fb468b68eaeeecb491b899a84f5bb6153bb26d7bd29dfe13713dc98226e7e0e1e67ba33646212193b30730ba6bfbb250f652a2f4b4ca6f7ba783d252fd8d0de2
7
- data.tar.gz: 5e9cfb969a2d94bda9a23f2ef5bfe8382705d5df502458eba98ad5eb9082e1f9bfee08ef258555548834240ae2c5241b9091c00e0bd39cab58c8c975fa2dc2f7
6
+ metadata.gz: d85570681eb8d97a4399cdf3e81638bdad90552d5703e4584f47eae7b942d186a5238ad44909d09d1ed592ae80e242f6daa834bae9170f9ca9d40dff9941cde5
7
+ data.tar.gz: ec1f0dcb3af96dfebaf899cb4b872906be495a62102e9880029a493c4e439c63f3e2d78a62f83b44ca5abfc213846a34232d3efcb6ae1f87681fb338bf4b44ed
data/Gemfile.lock CHANGED
@@ -34,7 +34,7 @@ GIT
34
34
  PATH
35
35
  remote: .
36
36
  specs:
37
- spree_cm_commissioner (2.5.0.pre.pre14)
37
+ spree_cm_commissioner (2.5.0)
38
38
  activerecord-multi-tenant
39
39
  activerecord_json_validator (~> 2.1, >= 2.1.3)
40
40
  aws-sdk-cloudfront
Binary file
Binary file
@@ -38,6 +38,14 @@ module SpreeCmCommissioner
38
38
  redirect_back fallback_location: spree.edit_admin_order_url(@order)
39
39
  end
40
40
 
41
+ # override
42
+ def cancel
43
+ internal_note = params.dig(:order, :internal_note)
44
+ @order.canceled_by(try_spree_current_user, cancellation_reason: internal_note)
45
+ flash[:success] = Spree.t(:order_canceled)
46
+ redirect_back fallback_location: spree.edit_admin_order_url(@order)
47
+ end
48
+
41
49
  def fire_notification
42
50
  method = @notification_methods.find { |e| e == params['notification_method'] }
43
51
 
@@ -92,7 +100,7 @@ module SpreeCmCommissioner
92
100
 
93
101
  # override
94
102
  def initialize_order_events
95
- @order_events = %w[alert_request_to_vendor approve cancel resume]
103
+ @order_events = %w[alert_request_to_vendor resume approve]
96
104
  end
97
105
 
98
106
  def initialize_notification_methods
@@ -57,7 +57,20 @@ module SpreeCmCommissioner
57
57
  end
58
58
  end
59
59
 
60
- # Override spree_core behavior to intentionally avoid calling `next!`.
60
+ # override to allow storing cancellation reason in one DB write
61
+ def canceled_by(user, cancellation_reason: nil)
62
+ transaction do
63
+ cancel!
64
+
65
+ update_columns( # rubocop:disable Rails/SkipsModelValidations
66
+ canceler_id: user.id,
67
+ canceled_at: Time.current,
68
+ internal_note: cancellation_reason
69
+ )
70
+ end
71
+ end
72
+
73
+ # override spree_core behavior to intentionally avoid calling `next!`.
61
74
  #
62
75
  # Goal: keep the order state at 'cart' when restarting checkout, especially
63
76
  # when seats were held during the address step.
@@ -5,6 +5,8 @@ module SpreeCmCommissioner
5
5
  include SpreeCmCommissioner::PhoneNumberSanitizer
6
6
 
7
7
  enum gender: { :other => 0, :male => 1, :female => 2 }
8
+ enum nationality_group: { :local => 0, :foreigner => 1 }
9
+ enum age_group: { :adult => 0, :child => 1 }
8
10
 
9
11
  belongs_to :user, class_name: 'Spree::User', optional: true
10
12
  belongs_to :occupation, class_name: 'Spree::Taxon', optional: true
@@ -3,4 +3,39 @@
3
3
  <%= button_link_to Spree.t('print'),
4
4
  main_app.url_for("/o/#{order.qr_data}"),
5
5
  icon: 'printer.svg',
6
- target: :_blank %>
6
+ target: :_blank %>
7
+
8
+ <% if can?(:fire, order) && order.can_cancel? %>
9
+ <% cancel_label = Spree.t(:cancel, scope: 'admin.order.events', default: Spree.t(:cancel)) %>
10
+ <%= button_link_to cancel_label,
11
+ '#',
12
+ icon: 'cancel.svg',
13
+ class: 'btn-light',
14
+ data: { toggle: 'modal', target: "#cancel-modal-#{order.number}" } %>
15
+
16
+ <div id="cancel-modal-<%= order.number %>" class="modal fade" tabindex="-1" role="dialog" aria-labelledby="cancelModalLabel-<%= order.number %>" aria-hidden="true">
17
+ <div class="modal-dialog" role="document">
18
+ <div class="modal-content">
19
+ <div class="modal-header">
20
+ <h5 class="modal-title mr-auto" id="cancelModalLabel-<%= order.number %>"><%= Spree.t(:order_sure_want_to, event: cancel_label) %></h5>
21
+ <button type="button" class="close" data-dismiss="modal" aria-label="<%= Spree.t(:close) %>">
22
+ <span aria-hidden="true">&times;</span>
23
+ </button>
24
+ </div>
25
+
26
+ <%= form_with model: order, url: spree.cancel_admin_order_url(order), method: :put do |f| %>
27
+ <div class="modal-body">
28
+ <div class="form-group text-left text-start">
29
+ <%= f.label :internal_note, raw(Spree.t(:reason) + required_span_tag), class: 'd-block text-left text-start' %>
30
+ <%= f.text_area :internal_note, rows: 3, class: 'form-control', placeholder: Spree.t(:enter_internal_note, default: 'Enter reason here...'), required: true %>
31
+ </div>
32
+ </div>
33
+ <div class="modal-footer d-flex justify-end">
34
+ <button type="button" class="btn btn-primary" data-dismiss="modal"><%= Spree.t(:close) %></button>
35
+ <%= f.submit Spree.t(:confirm), class: 'btn btn-danger' %>
36
+ </div>
37
+ <% end %>
38
+ </div>
39
+ </div>
40
+ </div>
41
+ <% end %>
@@ -5,6 +5,7 @@
5
5
  # result = SpreeCmCommissioner::VendorPlaces::CreateWithGoogleMapData.call(
6
6
  # vendor: current_vendor,
7
7
  # place_type: 'stop',
8
+ # contact_phone: '+1234567890',
8
9
  # google_place_base_64_content: google_place_base_64_content,
9
10
  # description: 'Main Warehouse',
10
11
  # location: parent_vendor_location
@@ -19,7 +20,7 @@
19
20
  module SpreeCmCommissioner
20
21
  module VendorPlaces
21
22
  class CreateWithGoogleMapData < Base
22
- def call(vendor:, place_type:, google_place_base_64_content:, description: nil, location: nil)
23
+ def call(vendor:, place_type:, google_place_base_64_content:, contact_phone: nil, description: nil, location: nil) # rubocop:disable Metrics/ParameterLists
23
24
  error_message = validate_place_type!(place_type)
24
25
  return failure(nil, error_message) if error_message.present?
25
26
 
@@ -29,7 +30,14 @@ module SpreeCmCommissioner
29
30
  place = process_place(google_place_base_64_content: google_place_base_64_content)
30
31
  return failure(nil, place) unless place.is_a?(SpreeCmCommissioner::Place)
31
32
 
32
- vendor_place = create_vendor_place(vendor: vendor, place: place, place_type: place_type, description: description, location: location)
33
+ vendor_place = create_vendor_place(
34
+ vendor: vendor,
35
+ place: place,
36
+ place_type: place_type,
37
+ contact_phone: contact_phone,
38
+ description: description,
39
+ location: location
40
+ )
33
41
  return failure(nil, vendor_place) if vendor_place.nil? || vendor_place.is_a?(String)
34
42
 
35
43
  success(vendor_place)
@@ -46,10 +54,17 @@ module SpreeCmCommissioner
46
54
  e.message
47
55
  end
48
56
 
49
- def create_vendor_place(vendor:, place:, place_type:, description:, location:)
57
+ def create_vendor_place(vendor:, place:, place_type:, contact_phone:, description:, location:) # rubocop:disable Metrics/ParameterLists
50
58
  error_message = nil
51
59
  result = ActiveRecord::Base.transaction do
52
- vendor_place = build_vendor_place(vendor: vendor, place: place, type: place_type, description: description, location: location)
60
+ vendor_place = build_vendor_place(
61
+ vendor: vendor,
62
+ place: place,
63
+ type: place_type,
64
+ contact_phone: contact_phone,
65
+ description: description,
66
+ location: location
67
+ )
53
68
  unless vendor_place.save
54
69
  error_message = vendor_place.errors.full_messages.to_sentence
55
70
  raise ActiveRecord::Rollback
@@ -59,19 +74,21 @@ module SpreeCmCommissioner
59
74
  error_message || result
60
75
  end
61
76
 
62
- def build_vendor_place(vendor:, place:, type:, description: nil, location: nil)
77
+ def build_vendor_place(vendor:, place:, type:, description: nil, location: nil, contact_phone: nil) # rubocop:disable Metrics/ParameterLists
63
78
  case type
64
79
  when 'stop'
65
80
  vendor.stops.new(
66
81
  place_id: place.id,
67
82
  description: description,
68
- location_id: location&.id
83
+ location_id: location&.id,
84
+ contact_phone: contact_phone
69
85
  )
70
86
  when 'branch'
71
87
  vendor.branches.new(
72
88
  place_id: place.id,
73
89
  description: description,
74
- location_id: location&.id
90
+ location_id: location&.id,
91
+ contact_phone: contact_phone
75
92
  )
76
93
  when 'location'
77
94
  vendor.locations.new(
@@ -1,10 +1,11 @@
1
1
  # Updates all vendor places matching the same vendor, place_id, and location_id.
2
- # Only updates description and location_id. Rolls back if any update fails.
2
+ # Only updates description, location_id, and contact_phone. Rolls back if any update fails.
3
3
  #
4
4
  # Usage:
5
5
  # result = SpreeCmCommissioner::VendorPlaces::Update.call(
6
6
  # vendor: current_vendor,
7
7
  # vendor_place: existing_vendor_place,
8
+ # contact_phone: '+1234567890',
8
9
  # location_id: new_location_id,
9
10
  # description: 'Updated description'
10
11
  # )
@@ -17,7 +18,7 @@
17
18
  module SpreeCmCommissioner
18
19
  module VendorPlaces
19
20
  class Update < Base
20
- def call(vendor:, vendor_place:, description: nil, location_id: nil)
21
+ def call(vendor:, vendor_place:, contact_phone: nil, description: nil, location_id: nil)
21
22
  if vendor_place.blank?
22
23
  return failure(
23
24
  nil,
@@ -35,6 +36,7 @@ module SpreeCmCommissioner
35
36
  update_attrs = {}
36
37
  update_attrs[:description] = description unless description.nil?
37
38
  update_attrs[:location_id] = location_id unless location_id.nil?
39
+ update_attrs[:contact_phone] = contact_phone unless contact_phone.nil?
38
40
 
39
41
  related_places.each do |vp|
40
42
  unless vp.update(update_attrs)
@@ -4,14 +4,12 @@
4
4
  <div class="content-wrapper">
5
5
  <%= render 'spree_cm_commissioner/cancel_order_mailer/header'%>
6
6
  <%= render 'spree_cm_commissioner/cancel_order_mailer/cancel_email', order: @order %>
7
- <%= render 'spree_cm_commissioner/cancel_order_mailer/your_booking', order: @order, show_booking_header: true %>
8
7
  <%= render 'spree_cm_commissioner/cancel_order_mailer/footer', order: @order%>
9
8
  </div>
10
9
  <% else %>
11
10
  <div class="content-wrapper">
12
11
  <%= render 'spree_cm_commissioner/cancel_order_mailer/tenant/header', order: @order ,logo: @logo, name: @name %>
13
12
  <%= render 'spree_cm_commissioner/cancel_order_mailer/tenant/cancel_email', order: @order %>
14
- <%= render 'spree_cm_commissioner/cancel_order_mailer/your_booking', order: @order , show_booking_header: true%>
15
13
  <%= render 'spree_cm_commissioner/cancel_order_mailer/tenant/footer', order: @order, name: @name %>
16
14
  </div>
17
15
  <% end %>
@@ -1,6 +1,6 @@
1
1
  <tr>
2
- <td class="email-body" width="570" cellpadding="0" cellspacing="0">
3
- <table class="email-body_inner" align="center" width="570" cellpadding="0" cellspacing="0" role="presentation">
2
+ <td width="100%" cellpadding="0" cellspacing="0">
3
+ <table align="center" width="100%" style="max-width: 570px;" cellpadding="0" cellspacing="0" role="presentation">
4
4
  <tbody>
5
5
  <tr>
6
6
  <td>
@@ -3,10 +3,11 @@
3
3
  <%= I18n.t('mail.order_mailer.hello', full_name: user_full_name(order))%>
4
4
  </h1>
5
5
  <p class="description">
6
- <%= I18n.t('mail.order_mailer.cancel_description') %>
6
+ <%= raw I18n.t('mail.order_mailer.cancel_description', order_number: order.number || 'NA') %>
7
+ </p>
8
+ <p class="description">
9
+ <span style="font-weight: bold; color: #000000;">Reason:</span>
10
+ <%= order&.internal_note %>
7
11
  </p>
8
- <b>
9
- <%= I18n.t('mail.order_mailer.order_cancelled', order_number: order.number || 'NA') %>
10
- </b>
11
12
  <div style="border-bottom: 1px solid #E5E7EB; margin-top: 1.5rem;">
12
13
  </div>
@@ -76,57 +76,6 @@
76
76
  font-size: 0.9rem;
77
77
  }
78
78
 
79
- .content-wrapper .purchase {
80
- width: 100%;
81
- border-collapse: collapse;
82
- }
83
-
84
- .content-wrapper .purchase_image {
85
- width: 20%;
86
- }
87
- .content-wrapper .purchase_item {
88
- padding: 0 0.625rem;
89
- width: 60%;
90
- }
91
- .content-wrapper .purchase-item-option-text {
92
- font-size: 0.8rem;
93
- background-color: #F2F2F2;
94
- color: #646161;
95
- white-space: normal;
96
- overflow: hidden;
97
- display: inline-block;
98
- max-width: 100%;
99
- width: auto;
100
- padding: 0.375rem 0.875rem;
101
- margin: 0.625rem 0;
102
- border-radius: 6.25rem;
103
- word-wrap: break-word;
104
- word-break: break-word;
105
- }
106
- .content-wrapper .purchase_item_price {
107
- margin-bottom: 0.5rem; }
108
- .content-wrapper .purchase-summary-item {
109
- margin-top: 0.625rem;
110
- }
111
- .purchase_total {
112
- font-weight: normal;
113
- text-align: right;
114
- padding-top: 1rem;
115
- margin: 0;
116
- }
117
- .content-wrapper .purchase-summary_sub_total {
118
- margin-bottom: 0.875rem;
119
- }
120
- .content-wrapper .purchase_footer {
121
- border-top: none;
122
- }
123
- .content-wrapper .purchase_total--label {
124
- text-align: left;
125
- }
126
- .content-wrapper .purchase_total-col {
127
- text-align: right;
128
- align: right;
129
- }
130
79
  .content-wrapper .footer{
131
80
  text-align: center;
132
81
  color: gray;
@@ -3,10 +3,11 @@
3
3
  <%= I18n.t('mail.order_mailer.hello', full_name: user_full_name(order))%>
4
4
  </h1>
5
5
  <p class="description">
6
- <%= I18n.t('mail.order_mailer.cancel_description') %>
6
+ <%= raw I18n.t('mail.order_mailer.cancel_description', order_number: order.number || 'NA') %>
7
+ </p>
8
+ <p class="description">
9
+ <span style="font-weight: bold; color: #000000;">Reason:</span>
10
+ <%= order&.internal_note %>
7
11
  </p>
8
- <b>
9
- <%= I18n.t('mail.order_mailer.order_cancelled', order_number: order.number || 'NA') %>
10
- </b>
11
12
  <div style="border-bottom: 1px solid #E5E7EB; margin-top: 1.5rem;">
12
13
  </div>
@@ -20,7 +20,7 @@
20
20
  </tr>
21
21
  <tr>
22
22
  <td height="60px">
23
- <table class="email-footer" align="center" width="570" cellpadding="0" cellspacing="0" role="presentation">
23
+ <table class="email-footer" align="center" width="100%" style="max-width: 570px;" cellpadding="0" cellspacing="0" role="presentation">
24
24
  <tr>
25
25
  <td>
26
26
  <% if @order.tenant.nil? %>
@@ -1,31 +1,25 @@
1
1
  <div class="content-cell">
2
2
  <div class="container">
3
3
  <h2><%= I18n.t('mail.order_mailer.customer_info')%></h2>
4
- <div class="flex two-columns">
4
+ <div class="flex two-columns-contact">
5
5
  <div class="two-columns-item">
6
6
  <div class="flex two-columns-item_detail">
7
- <div class="two-columns_icon"><%= image_tag "mailer/user.png", class: "mail-icon"%></div>
7
+ <div class="two-columns_icon" style="color: black;"><%= image_tag "mailer/user.png", class: "mail-icon"%></div>
8
8
  <div class="two-columns_text-container">
9
- <p class="two-columns_title">Name</p>
10
9
  <p class="two-columns_description"><%= user_full_name(order) %></p>
11
10
  </div>
12
11
  </div>
13
12
  <div class="flex two-columns-item_detail">
14
13
  <div class="two-columns_icon"><%= image_tag "mailer/envelope.png", class: "mail-icon"%></div>
15
14
  <div class="two-columns_text-container">
16
- <p class="two-columns_title">Email</p>
17
15
  <% if order.email.present? %>
18
16
  <p class="two-columns_description"><%= link_to order.email, "mailto:#{order.email}" %></p>
19
17
  <% end %>
20
18
  </div>
21
19
  </div>
22
- </div>
23
- <div class="vertical-separater"></div>
24
- <div class="two-columns-item">
25
20
  <div class="flex two-columns-item_detail">
26
21
  <div class="two-columns_icon"><%= image_tag "mailer/phone.png", class: "mail-icon"%></div>
27
22
  <div class="two-columns_text-container">
28
- <p class="two-columns_title">Contact</p>
29
23
  <% if order.phone_number.present? || order.intel_phone_number.present? %>
30
24
  <p class="two-columns_description">
31
25
  <%= link_to(
@@ -1,5 +1,9 @@
1
1
  <style type="text/css" rel="stylesheet" media="all">
2
2
  /* Custom Mailer ------------------------------ */
3
+ body {
4
+ padding: 0;
5
+ margin: 0;
6
+ }
3
7
 
4
8
  #confirm-email {
5
9
  font-family: "Poppins", "Nunito Sans", Helvetica, Arial, sans-serif;
@@ -95,12 +99,12 @@
95
99
  margin-bottom: 0.625rem;
96
100
  }
97
101
  #confirm-email .icon-hang-meas {
98
- width: 50%;
102
+ width: 40%;
99
103
  text-align: right;
100
104
  }
101
105
  #confirm-email .icon-hang-meas img {
102
- width: 6.25rem;
103
- height: 6.25rem;
106
+ width: 3.5rem;
107
+ height: 3.5rem;
104
108
  border-radius: 50%;
105
109
  background-color: #fff;
106
110
  display: inline-block;
@@ -108,7 +112,8 @@
108
112
  #confirm-email .header h1 {
109
113
  margin: 0;
110
114
  color: #fff;
111
- width: 50%;
115
+ width: 60%;
116
+ font-size: 1.8rem;
112
117
  }
113
118
 
114
119
  #confirm-email .header {
@@ -140,26 +145,25 @@
140
145
  padding: 0.625rem 0;
141
146
  }
142
147
  #confirm-email .purchase_image {
143
- width: 20%;
148
+ border-radius:10px;
149
+ width:auto; height:auto;
150
+ display:block; margin-bottom:6px;
151
+ margin-right: 8px;
144
152
  }
145
153
  #confirm-email .purchase_item {
146
154
  padding: 0 0.625rem;
147
155
  width: 60%;
148
156
  }
149
157
  #confirm-email .purchase-item-option-text {
150
- font-size: 1rem;
151
- background-color: #F2F2F2;
152
- color: #646161;
153
- white-space: normal;
154
- overflow: hidden;
155
- display: inline-block;
156
- max-width: 100%;
157
- width: auto;
158
- padding: 0.375rem 0.875rem;
159
- margin: 0.625rem 0;
160
- border-radius: 6.25rem;
161
- word-wrap: break-word;
162
- word-break: break-word;
158
+ padding:12px;
159
+ border:1px solid #d1d5db;
160
+ background-color:#f3f4f6;
161
+ border-radius:10px;
162
+ font-size:12px;
163
+ line-height:1.25;
164
+ color:#4b5563;
165
+ word-wrap:break-word;
166
+ text-align:start;
163
167
  }
164
168
  #confirm-email .purchase_item_price {
165
169
  margin-bottom: 0.5rem; }
@@ -186,9 +190,18 @@
186
190
  height: auto;
187
191
  background: #F2F2F2;
188
192
  }
193
+ #confirm-email .two-columns-contact{
194
+ display: flex;
195
+ flex-direction: column;
196
+ }
197
+ #confirm-email .two-columns-contact .two-columns-item {
198
+ flex: 1 1 45%;
199
+ word-wrap: break-word;
200
+ word-break: break-word;
201
+ width: 100%;
202
+ }
189
203
  #confirm-email .two-columns .two-columns-item {
190
204
  flex: 1 1 45%;
191
- margin: 0.5rem 0;
192
205
  word-wrap: break-word;
193
206
  word-break: break-word;
194
207
  width: 100%;
@@ -200,16 +213,30 @@
200
213
  width: 65%;
201
214
  justify-content: right;
202
215
  }
203
- #confirm-email .two-columns .two-columns-item_detail {
216
+ #confirm-email .two-columns-contact .two-columns-item_detail {
204
217
  margin-bottom: 1rem;
205
218
  width: 100%;
219
+ display: flex;
220
+ align-items: center;
206
221
  }
207
222
  #confirm-email .two-columns_icon {
208
- min-width: 3rem;
209
- height: 3rem;
223
+ min-width: 2rem;
224
+ height: 2rem;
210
225
  background: #f1f1f1;
211
226
  border-radius: 50%;
212
227
  display: flex;
228
+ align-items: center;
229
+ justify-content: center;
230
+ fill: blue;
231
+ stroke: black;
232
+ }
233
+ #confirm-email .two-columns_icon .mail-icon {
234
+ width: 1rem; /* Adjust size as needed */
235
+ height: 1rem;
236
+ }
237
+ #confirm-email .two-columns_icon .mail-icon-tenant {
238
+ width: 1.2rem;
239
+ height: 1.2rem;
213
240
  }
214
241
  #confirm-email .two-columns_icon .vendor-logo {
215
242
  max-width: 3rem;
@@ -295,6 +322,7 @@
295
322
  padding: 1.5rem;
296
323
  border-radius: 0 0 1.5625rem 1.5625rem;
297
324
  border: 0.0625rem solid #dddfe2;
325
+ background-color: #fff;
298
326
  }
299
327
  .purchase {
300
328
  width: 100%;
@@ -310,7 +338,7 @@
310
338
  align: right;
311
339
  }
312
340
  .align-right {
313
- padding: 0.625rem;
341
+ padding: 0.625rem 0;
314
342
  text-align: right;
315
343
  align: right;
316
344
  }
@@ -1,12 +1,11 @@
1
1
  <div class="content-cell">
2
2
  <div class="container">
3
3
  <h2><%= I18n.t('mail.order_mailer.bookmeplus_support')%></h2>
4
- <div class="flex two-columns">
4
+ <div class="flex two-columns-contact">
5
5
  <div class="two-columns-item">
6
6
  <div class="flex two-columns-item_detail">
7
- <div class="two-columns_icon"><%= image_tag "mailer/phone.png", class: "mail-icon"%></div>
7
+ <div class="two-columns_icon"><%= image_tag "mailer/phone.png", class: "mail-icon" %></div>
8
8
  <div class="two-columns_text-container">
9
- <p class="two-columns_title">Contact</p>
10
9
  <% if current_store.contact_phone.present? %>
11
10
  <p class="two-columns_description">
12
11
  <%= link_to current_store.contact_phone, "tel:#{current_store.contact_phone}" %>
@@ -14,13 +13,9 @@
14
13
  <% end %>
15
14
  </div>
16
15
  </div>
17
- </div>
18
- <div class="vertical-separater"></div>
19
- <div class="two-columns-item">
20
16
  <div class="flex two-columns-item_detail">
21
17
  <div class="two-columns_icon"><%= image_tag "mailer/envelope.png", class: "mail-icon"%></div>
22
18
  <div class="two-columns_text-container">
23
- <p class="two-columns_title">Email</p>
24
19
  <% if current_store.customer_support_email.present? %>
25
20
  <p class="two-columns_description">
26
21
  <%= link_to current_store.customer_support_email, "mailto:#{current_store.customer_support_email}" %>
@@ -1,46 +1,80 @@
1
- <table class="purchase order-info">
1
+ <table class="purchase order-info" width="100%" cellpadding="0" cellspacing="0">
2
2
  <% line_items.each do |line_item| %>
3
3
  <tr>
4
- <td class="purchase_image align-center-vertical">
5
- <% if line_item.variant.present? && variant_image_url(line_item.variant).present? %>
6
- <%= link_to(
7
- image_tag(
8
- variant_image_url(line_item.variant),
9
- style: "border-radius: 10px; width: 100%;"),
10
- custom_product_storefront_resource_url(line_item.product) || '#'
11
- ) %>
12
- <% end %>
13
- </td>
14
- <td class="purchase_item">
15
- <% if line_item.name.present? %>
16
- <p><%= link_to(
17
- raw(line_item.name),
4
+ <td>
5
+ <!-- Outer container table -->
6
+ <table width="100%" cellpadding="0" cellspacing="0" role="presentation">
7
+
8
+ <!-- Row 1: Name + Quantity × Price -->
9
+ <tr>
10
+ <td align="left" valign="top" width="60%">
11
+ <% if line_item.name.present? %>
12
+ <span>
13
+ <%= link_to(raw(line_item.name), custom_product_storefront_resource_url(line_item.product) || '#') %>
14
+ </span>
15
+ <% end %>
16
+ </td>
17
+ <td align="right" valign="top" width="40%">
18
+ <table width="100%" cellpadding="0" cellspacing="0" role="presentation">
19
+ <tr>
20
+ <td align="right" style="color: gray; padding-bottom:2px; white-space:nowrap;">
21
+ <%= line_item.quantity %> x <%= line_item.single_money %>
22
+ </td>
23
+ </tr>
24
+ <tr>
25
+ <td align="right">
26
+ <span style="font-weight:600;"><%= line_item.display_amount %></span>
27
+ </td>
28
+ </tr>
29
+ </table>
30
+ </td>
31
+ </tr>
32
+
33
+ </table>
34
+
35
+ <!-- Separate table for Image + Options to avoid width conflicts -->
36
+ <table width="100%" cellpadding="0" cellspacing="0" role="presentation" style="margin-top:6px;">
37
+ <tr>
38
+ <!-- Image -->
39
+ <td align="left" valign="top">
40
+ <% if line_item.variant.present? && variant_image_url(line_item.variant).present? %>
41
+ <%= link_to(
42
+ image_tag(
43
+ variant_image_url(line_item.variant),
44
+ class: "purchase_image"
45
+ ),
18
46
  custom_product_storefront_resource_url(line_item.product) || '#'
19
- ) %></p>
20
- <% end %>
21
- <% if line_item.variant.options_text.present? %>
22
- <div class="purchase-item-option-text">
23
- <%= sanitize(line_item.variant.options_text) %>
24
- </div>
25
- <% end %>
26
- <div> <%= link_to 'View Details', custom_product_line_item_url(line_item) %></div>
27
- </td>
28
- <td class="align-right align-center-vertical" width="10%">
29
- <span>
30
- <%= line_item.quantity %>x
31
- </span>
47
+ ) %>
48
+ <% end %>
49
+ </td>
50
+
51
+ <!-- Options -->
52
+ <td align="right" valign="top" width="100%">
53
+ <% if line_item.variant.options_text.present? %>
54
+ <table width="100%" cellpadding="0" cellspacing="0" role="presentation">
55
+ <tr>
56
+ <td class="purchase-item-option-text">
57
+ <%= sanitize(line_item.variant.options_text) %>
58
+ </td>
59
+ </tr>
60
+ </table>
61
+ <% end %>
62
+ </td>
63
+ </tr>
64
+
65
+ <!-- Detail link -->
66
+ <tr>
67
+ <td></td>
68
+ <td align="right" style="padding-top:6px;">
69
+ <%= link_to 'View Pass', custom_product_line_item_url(line_item)%>
70
+ </td>
71
+ </tr>
72
+ </table>
32
73
  </td>
33
- <td class="align-right align-center-vertical" width="20%">
34
- <div class="f-fallback purchase_item_price">
35
- <%= line_item.single_money %><br>
36
- </div>
37
- <div class="f-fallback purchase_item_price">
38
- <%= line_item.display_amount %>
39
- </div>
40
- </td>
41
- </tr>
42
- <tr>
43
- <td colspan="4"><hr></td>
44
- </tr>
45
- <%end%>
46
- </table>
74
+ </tr>
75
+
76
+ <tr>
77
+ <td><hr></td>
78
+ </tr>
79
+ <% end %>
80
+ </table>
@@ -1,31 +1,25 @@
1
1
  <div class="content-cell">
2
2
  <div class="container">
3
3
  <h2><%= I18n.t('mail.order_mailer.customer_info') %></h2>
4
- <div class="flex two-columns">
4
+ <div class="flex two-columns-contact">
5
5
  <div class="two-columns-item">
6
6
  <div class="flex two-columns-item_detail">
7
- <div class="two-columns_icon"><%= image_tag "mailer/tenant_user.png", class: "mail-icon" %></div>
7
+ <div class="two-columns_icon"><%= image_tag "mailer/user-tenant.png", class: "mail-icon" %></div>
8
8
  <div class="two-columns_text-container">
9
- <p class="two-columns_title">Name</p>
10
9
  <p class="two-columns_description"><%= user_full_name(order) %></p>
11
10
  </div>
12
11
  </div>
13
12
  <div class="flex two-columns-item_detail">
14
- <div class="two-columns_icon"><%= image_tag "mailer/mail.png", class: "mail-icon" %></div>
13
+ <div class="two-columns_icon"><%= image_tag "mailer/email.png", class: "mail-icon" %></div>
15
14
  <div class="two-columns_text-container">
16
- <p class="two-columns_title">Email</p>
17
15
  <% if order.email.present? %>
18
16
  <p class="two-columns_description"><%= link_to order.email, "mailto:#{order.email}" %></p>
19
17
  <% end %>
20
18
  </div>
21
19
  </div>
22
- </div>
23
- <div class="vertical-separater"></div>
24
- <div class="two-columns-item">
25
20
  <div class="flex two-columns-item_detail">
26
- <div class="two-columns_icon"><%= image_tag "mailer/tenant_phone.png", class: "mail-icon" %></div>
21
+ <div class="two-columns_icon"><%= image_tag "mailer/call.png", class: "mail-icon-tenant" %></div>
27
22
  <div class="two-columns_text-container">
28
- <p class="two-columns_title">Contact</p>
29
23
  <% if order.phone_number.present? || order.intel_phone_number.present? %>
30
24
  <p class="two-columns_description">
31
25
  <%= link_to(
@@ -1,12 +1,11 @@
1
1
  <div class="content-cell">
2
2
  <div class="container">
3
3
  <h2><%= name %> Support</h2>
4
- <div class="flex two-columns">
4
+ <div class="flex two-columns-contact">
5
5
  <div class="two-columns-item">
6
6
  <div class="flex two-columns-item_detail">
7
- <div class="two-columns_icon"><%= image_tag "mailer/tenant_phone.png", class: "mail-icon"%></div>
7
+ <div class="two-columns_icon"><%= image_tag "mailer/call.png", class: "mail-icon-tenant"%></div>
8
8
  <div class="two-columns_text-container">
9
- <p class="two-columns_title">Contact</p>
10
9
  <% if order&.tenant&.contact_phone&.present? %>
11
10
  <p class="two-columns_description">
12
11
  <%= link_to order.tenant.contact_phone, "tel:#{order.tenant.contact_phone}" %>
@@ -14,13 +13,9 @@
14
13
  <% end %>
15
14
  </div>
16
15
  </div>
17
- </div>
18
- <div class="vertical-separater"></div>
19
- <div class="two-columns-item">
20
16
  <div class="flex two-columns-item_detail">
21
- <div class="two-columns_icon"><%= image_tag "mailer/mail.png", class: "mail-icon"%></div>
17
+ <div class="two-columns_icon"><%= image_tag "mailer/email.png", class: "mail-icon"%></div>
22
18
  <div class="two-columns_text-container">
23
- <p class="two-columns_title">Email</p>
24
19
  <p class="two-columns_description">
25
20
  <%= order&.tenant&.customer_support_email.present? ? link_to(order.tenant.customer_support_email, "mailto:#{order.tenant.customer_support_email}") : "N/A" %>
26
21
  </p>
@@ -539,8 +539,7 @@ en:
539
539
  hello: "Hello %{full_name},"
540
540
  thanks: "Thanks %{full_name},"
541
541
  booking_event: "Your booking for %{order_number} is successfully complete!"
542
- cancel_description: "Your order has been CANCELED. Please retain this cancellation information for your records."
543
- order_cancelled: "Order %{order_number} Summary [CANCELED]"
542
+ cancel_description: "Your order <span style='color: #000000; font-weight: bold;'>%{order_number}</span> has been <span style='color: red; font-weight: bold;'>CANCELLED</span>. Please retain this cancellation information for your records."
544
543
  cancel_thank: "Thank you for your business."
545
544
  from_team: "The %{store} Team"
546
545
  booking_reference: "For reference, your booking ID is %{order_number}."
@@ -410,8 +410,7 @@ km:
410
410
  hello: "Hello %{full_name},"
411
411
  thanks: "Thanks %{full_name},"
412
412
  booking_event: "Your booking for %{order_number} is successfully complete!"
413
- cancel_description: "Your order has been CANCELED. Please retain this cancellation information for your records."
414
- order_cancelled: "Order %{order_number} Summary [CANCELED]"
413
+ cancel_description: "Your order <span style='color: #000000; font-weight: bold;'>%{order_number}</span> has been <span style='color: red; font-weight: bold;'>CANCELLED</span>. Please retain this cancellation information for your records."
415
414
  cancel_thank: "Thank you for your business."
416
415
  from_team: "The %{store} Team"
417
416
  booking_reference: "For reference, your booking ID is %{order_number}."
@@ -0,0 +1,6 @@
1
+ class AddNationalityGroupAndAgeGroupToCmSavedGuests < ActiveRecord::Migration[7.0]
2
+ def change
3
+ add_column :cm_saved_guests, :nationality_group, :integer, default: 0, null: false, if_not_exists: true
4
+ add_column :cm_saved_guests, :age_group, :integer, default: 0, null: false, if_not_exists: true
5
+ end
6
+ end
@@ -0,0 +1,5 @@
1
+ class AddContactPhoneToCmVendorPlaces < ActiveRecord::Migration[7.0]
2
+ def change
3
+ add_column :cm_vendor_places, :contact_phone, :string, if_not_exists: true
4
+ end
5
+ end
@@ -1,5 +1,5 @@
1
1
  module SpreeCmCommissioner
2
- VERSION = '2.5.0.pre.pre14'.freeze
2
+ VERSION = '2.5.0'.freeze
3
3
 
4
4
  module_function
5
5
 
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.0.pre.pre14
4
+ version: 2.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - You
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2026-01-04 00:00:00.000000000 Z
11
+ date: 2026-01-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: spree
@@ -731,6 +731,8 @@ files:
731
731
  - app/assets/images/mailer/bookme-plus.png
732
732
  - app/assets/images/mailer/bookme-plus_light.svg
733
733
  - app/assets/images/mailer/calendar.png
734
+ - app/assets/images/mailer/call.png
735
+ - app/assets/images/mailer/email.png
734
736
  - app/assets/images/mailer/envelope.png
735
737
  - app/assets/images/mailer/event-mailer-bg.png
736
738
  - app/assets/images/mailer/facebook.png
@@ -742,6 +744,7 @@ files:
742
744
  - app/assets/images/mailer/tenant_phone.png
743
745
  - app/assets/images/mailer/tenant_user.png
744
746
  - app/assets/images/mailer/twitter.png
747
+ - app/assets/images/mailer/user-tenant.png
745
748
  - app/assets/images/mailer/user.png
746
749
  - app/assets/images/payment_methods/cm-payment-affirm.svg
747
750
  - app/assets/images/payment_methods/cm-payment-alipay.svg
@@ -2507,9 +2510,6 @@ files:
2507
2510
  - app/views/spree_cm_commissioner/cancel_order_mailer/_footer.html.erb
2508
2511
  - app/views/spree_cm_commissioner/cancel_order_mailer/_header.html.erb
2509
2512
  - app/views/spree_cm_commissioner/cancel_order_mailer/_mailer_stylesheets.html.erb
2510
- - app/views/spree_cm_commissioner/cancel_order_mailer/_your_booking.html.erb
2511
- - app/views/spree_cm_commissioner/cancel_order_mailer/purchased_items/_items.html.erb
2512
- - app/views/spree_cm_commissioner/cancel_order_mailer/purchased_items/_summary.html.erb
2513
2513
  - app/views/spree_cm_commissioner/cancel_order_mailer/tenant/_cancel_email.html.erb
2514
2514
  - app/views/spree_cm_commissioner/cancel_order_mailer/tenant/_footer.html.erb
2515
2515
  - app/views/spree_cm_commissioner/cancel_order_mailer/tenant/_header.html.erb
@@ -2979,6 +2979,8 @@ files:
2979
2979
  - db/migrate/20251127074809_change_guest_dynamic_fields_value_from_jsonb_to_text.rb
2980
2980
  - db/migrate/20251209022924_add_contact_fields_to_cm_tenants.rb
2981
2981
  - db/migrate/20251219035243_add_migrations_to_support_vehicle_types.rb
2982
+ - db/migrate/20260105072146_add_nationality_group_and_age_group_to_cm_saved_guests.rb
2983
+ - db/migrate/20260106093359_add_contact_phone_to_cm_vendor_places.rb
2982
2984
  - docker-compose.yml
2983
2985
  - docs/api/scoped-access-token-endpoints.md
2984
2986
  - docs/option_types/attr_types.md
@@ -3153,9 +3155,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
3153
3155
  version: '2.7'
3154
3156
  required_rubygems_version: !ruby/object:Gem::Requirement
3155
3157
  requirements:
3156
- - - ">"
3158
+ - - ">="
3157
3159
  - !ruby/object:Gem::Version
3158
- version: 1.3.1
3160
+ version: '0'
3159
3161
  requirements:
3160
3162
  - none
3161
3163
  rubygems_version: 3.4.1
@@ -1,8 +0,0 @@
1
- <table width="100%" cellpadding="0" cellspacing="0">
2
- <tr>
3
- <td>
4
- <%= render 'spree_cm_commissioner/cancel_order_mailer/purchased_items/items', line_items: order.line_items %>
5
- <%= render 'spree_cm_commissioner/cancel_order_mailer/purchased_items/summary', order: order%>
6
- </td>
7
- </tr>
8
- </table>
@@ -1,53 +0,0 @@
1
- <table class="purchase order-info">
2
- <% line_items.each do |line_item| %>
3
- <tr>
4
- <td class="purchase_image align-center-vertical">
5
- <% if line_item.variant.present? && variant_image_url(line_item.variant).present? %>
6
- <%= link_to(
7
- image_tag(
8
- variant_image_url(line_item.variant),
9
- style: "border-radius: 10px; width: 100%;"),
10
- custom_product_storefront_resource_url(line_item.product) || '#'
11
- ) %>
12
- <% end %>
13
- </td>
14
- <td class="purchase_item">
15
- <% if line_item.name.present? %>
16
- <p><%= link_to(
17
- raw(line_item.name),
18
- custom_product_storefront_resource_url(line_item.product) || '#'
19
- ) %></p>
20
- <% end %>
21
- <% if line_item.variant.options_text.present? %>
22
- <div class="purchase-item-option-text">
23
- <%= sanitize(line_item.variant.options_text) %>
24
- </div>
25
- <% end %>
26
- <div> <%= link_to 'View Details', custom_product_line_item_url(line_item) %></div>
27
- </td>
28
- <td class="align-right align-center-vertical" width="10%">
29
- <span>
30
- <%= line_item.quantity %>x
31
- </span>
32
- </td>
33
- <td class="align-right align-center-vertical" width="20%">
34
- <div class="f-fallback purchase_item_price">
35
- <%= line_item.single_money %><br>
36
- </div>
37
- <div class="f-fallback purchase_item_price">
38
- <%= line_item.display_amount %>
39
- </div>
40
- </td>
41
- </tr>
42
- <tr>
43
- <td colspan="4">
44
- <hr style="
45
- border: none;
46
- border-top: 1px solid #E5E7EB;
47
- margin: 1.5rem 0 0 0;
48
- height: 0;
49
- ">
50
- </td>
51
- </tr>
52
- <%end%>
53
- </table>
@@ -1,108 +0,0 @@
1
- <table class="purchase purchase-summary">
2
- <tr>
3
- <td valign="middle" colspan="2">
4
- <p class="f-fallback purchase_total purchase_total--label">
5
- <%= Spree.t('order_mailer.subtotal') %>
6
- </p>
7
- </td>
8
- <td valign="middle">
9
- <p class="f-fallback purchase_total align-right">
10
- <%= order.display_item_total %>
11
- </p>
12
- </td>
13
- </tr>
14
- <% if order.line_item_adjustments.exists? %>
15
- <% if order.all_adjustments.promotion.eligible.exists? %>
16
- <% order.all_adjustments.promotion.eligible.group_by(&:label).each do |label, adjustments| %>
17
- <tr class="purchase-summary-item">
18
- <td class="purchase_footer" valign="middle">
19
- <p class="f-fallback purchase_total purchase_total--label">
20
- <%= Spree.t(:promotion) %>
21
- </p>
22
- </td>
23
- <td class="purchase_footer" valign="middle">
24
- <p class="f-fallback purchase_total--name purchase_total--label">
25
- <%= label %>
26
- </p>
27
- </td>
28
- <td class="purchase_footer" valign="middle">
29
- <p class="f-fallback purchase_total align-right">
30
- <%= Spree::Money.new(adjustments.sum(&:amount), currency: order.currency) %>
31
- </p>
32
- </td>
33
- </tr>
34
- <% end %>
35
- <% end %>
36
- <% end %>
37
- <% order.shipments.group_by { |s| s.selected_shipping_rate&.name }.each do |name, shipments| %>
38
- <tr class="purchase-summary-item">
39
- <td class="purchase_footer" valign="middle">
40
- <p class="f-fallback purchase_total purchase_total--label">
41
- <%= Spree.t(:shipping) %>
42
- </p>
43
- </td>
44
- <td class="purchase_footer" valign="middle">
45
- <p class="f-fallback purchase_total--name purchase_total--label">
46
- <%= name %>
47
- </p>
48
- </td>
49
- <td class="purchase_footer" valign="middle">
50
- <p class="f-fallback purchase_total align-right">
51
- <%= Spree::Money.new(shipments.sum(&:discounted_cost), currency: order.currency) %>
52
- </p>
53
- </td>
54
- </tr>
55
- <%end%>
56
- <% if order.additional_tax_total != 0 %>
57
- <tr class="purchase-summary-item">
58
- <td class="purchase_footer" valign="middle" colspan="2">
59
- <p class="f-fallback purchase_total purchase_total--label">
60
- <%= Spree.t(:tax) %>
61
- </p>
62
- </td>
63
- <td class="purchase_footer" valign="middle">
64
- <p class="f-fallback purchase_total align-right">
65
- <%= order.display_additional_tax_total.to_html %>
66
- </p>
67
- </td>
68
- </tr>
69
- <% end %>
70
-
71
- <% order.adjustments.eligible.each do |adjustment| %>
72
- <% next if (adjustment.source_type == 'Spree::TaxRate') || (adjustment.amount == 0) %>
73
- <tr>
74
- <td class="purchase_footer" valign="middle">
75
- <p class="f-fallback purchase_total purchase_total--label">
76
- <%= Spree.t(:adjustments) %>
77
- </p>
78
- </td>
79
- <td class="purchase_footer" valign="middle">
80
- <p class="f-fallback purchase_total--name purchase_total--label">
81
- <%= raw(adjustment.label) %>:
82
- </p>
83
- </td>
84
- <td class="purchase_total-col align-right">
85
- <p class="f-fallback purchase_total">
86
- <%= Spree::Money.new(adjustment.amount, currency: order.currency) %>
87
- </p>
88
- </td>
89
- </tr>
90
- <% end %>
91
- <tr>
92
- <td class="purchase_footer" colspan="2">
93
- <p class="f-fallback purchase_total purchase_total--label">
94
- <strong><%= I18n.t('mail.order_mailer.etotal') %></strong> (<%= I18n.t('mail.order_mailer.including_vat') %>)
95
- </p>
96
- </td>
97
- <td class="purchase_total-col align-right">
98
- <p class="f-fallback purchase_total">
99
- <strong><%= order.display_total %></strong>
100
- </p>
101
- </td>
102
- </tr>
103
- <tr>
104
- <td colspan="4">
105
- <hr style="border-top-width: 1px; border-top-color: #E5E7EB; height: 0; margin: 1.5rem 0 0; border-style: solid none none;" />
106
- </td>
107
- </tr>
108
- </table>