spree_cm_commissioner 2.10.1 → 2.10.2.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 34524289f2fc489da23a30fcaca4bfcdac167a60b0efd382368efda96433e4d9
4
- data.tar.gz: 47cd7bcb029126c27c0dd1c7081f26b8a217e740be768662f59a208a0e440ad6
3
+ metadata.gz: e5552124388d0792051115573a9cc5e51044c8edcf7f8e89c6f03b43d2ebd0ab
4
+ data.tar.gz: '0694645f790079a03ebad09626ca155e7495c37ea8b45f83064a3c31b2aa6f75'
5
5
  SHA512:
6
- metadata.gz: 134f803e39f5fce95401a2404cf6f559baf6997651440578767022cc9c7c4ddf1368da4b16ec12b096753569794593a03a8ace0ac1522fab107a0ae57b09db04
7
- data.tar.gz: d8401ff0a245a5429919380ffc56412e2a09614fe82a78bef24f2e90ff54d88feb885ea0bb78993d2f45e9e7cc6a294958642290e53f8ea41650fc3ca4652759
6
+ metadata.gz: 06b79003d8dee84088c17d6cd6f90b7d2b7d5eeca20b4045ca1775b467b3455b66898e72e47d33e9655a6b8b7c1b36dcef355b8b4ff5258daa066d87e8cdfb02
7
+ data.tar.gz: 386411dbfdd18ce5d25ade6d55e045b1bcaea788d3b8cb49437723789ab8e1e5e7e1b77e4cbece9ee962427f8b0c5c603c1cd1cdc091400ca8cf6e860dfd39a4
data/Gemfile.lock CHANGED
@@ -34,7 +34,7 @@ GIT
34
34
  PATH
35
35
  remote: .
36
36
  specs:
37
- spree_cm_commissioner (2.10.1)
37
+ spree_cm_commissioner (2.10.2.pre.pre1)
38
38
  activerecord-multi-tenant
39
39
  activerecord_json_validator (~> 2.1, >= 2.1.3)
40
40
  aws-sdk-cloudfront
@@ -14,6 +14,8 @@ module Spree
14
14
  end
15
15
 
16
16
  def update_telegram_chat
17
+ @vendor.update(preferred_telegram_alert_channels: submitted_alert_channels_mask)
18
+
17
19
  context = ::SpreeCmCommissioner::TelegramChatsFinder.call(
18
20
  telegram_chat_name: params['vendor']['preferred_telegram_chat_name'],
19
21
  telegram_chat_type: params['vendor']['preferred_telegram_chat_type']
@@ -34,6 +36,19 @@ module Spree
34
36
  redirect_to collection_url(@vendor)
35
37
  end
36
38
 
39
+ # OR the bits, never sum them. Sum is not idempotent: if the same bit arrives twice
40
+ # (duplicated checkbox, double-submit, hand-crafted post) 1 + 1 = 2, which silently means
41
+ # google_form instead of spree. ["0","1","1","16"].sum => 18 => [google_form, offline_sell];
42
+ # the same input OR'd => 17 => [spree, offline_sell].
43
+ #
44
+ # Masking against the known bits also drops junk from a crafted post (999 => 7).
45
+ def submitted_alert_channels_mask
46
+ known = SpreeCmCommissioner::OrderChannelBitwise::CHANNEL_ALERT_BITS.values.reduce(:|)
47
+
48
+ Array(params.dig(:vendor, :telegram_alert_channels))
49
+ .reduce(0) { |acc, value| acc | value.to_i } & known
50
+ end
51
+
37
52
  # @overrided
38
53
  def model_class
39
54
  Spree::User
@@ -0,0 +1,70 @@
1
+ # Owns everything about an order's `channel`: the allowed values, how a stored value
2
+ # resolves back to one of them, and the bitmask vendors use to choose which channels
3
+ # may alert their Telegram group.
4
+ #
5
+ # `channel` is validated by PREFIX, not equality, because the CSV importer stores
6
+ # "google_form-<import_order_id>-<slug>". Always compare via #channel_key, never `==`.
7
+ module SpreeCmCommissioner
8
+ module OrderChannelBitwise
9
+ extend ActiveSupport::Concern
10
+
11
+ SPREE_CHANNEL = 'spree'.freeze
12
+ GOOGLE_FORM_CHANNEL = 'google_form'.freeze
13
+ TELEGRAM_CHANNEL = 'telegram'.freeze
14
+ TICKET_TRANSFER_CHANNEL = 'ticket_transfer'.freeze
15
+ OFFLINE_SELL_CHANNEL = 'offline_sell'.freeze
16
+
17
+ ALLOWED_CHANNEL_PREFIXES = [
18
+ SPREE_CHANNEL, GOOGLE_FORM_CHANNEL, TELEGRAM_CHANNEL, TICKET_TRANSFER_CHANNEL, OFFLINE_SELL_CHANNEL
19
+ ].freeze
20
+
21
+ # Matched longest-first so a future 'spree_x' can never be swallowed by 'spree'.
22
+ SORTED_CHANNEL_PREFIXES = ALLOWED_CHANNEL_PREFIXES.sort_by { |prefix| -prefix.length }.freeze
23
+
24
+ # Bit values are PERSISTED in vendor preferences and are a permanent contract.
25
+ # Never renumber, reorder, or reuse a bit. To retire a channel, leave its bit
26
+ # burned and take the next free power of two.
27
+ #
28
+ # Deliberately literal, never derived from ALLOWED_CHANNEL_PREFIXES.index —
29
+ # reordering that array would silently remap every vendor's saved setting.
30
+ CHANNEL_ALERT_BITS = {
31
+ SPREE_CHANNEL => 1, # 1 << 0
32
+ GOOGLE_FORM_CHANNEL => 2, # 1 << 1
33
+ TELEGRAM_CHANNEL => 4, # 1 << 2
34
+ TICKET_TRANSFER_CHANNEL => 8, # 1 << 3
35
+ OFFLINE_SELL_CHANNEL => 16 # 1 << 4
36
+ }.freeze
37
+
38
+ # Every bit currently in use, for masking untrusted input down to known channels.
39
+ KNOWN_CHANNEL_ALERT_BITS = CHANNEL_ALERT_BITS.values.reduce(:|).freeze
40
+
41
+ # Only online orders alert by default. google_form & ticket_transfer set the state column
42
+ # directly instead of firing the state machine, so they have never sent an alert; this
43
+ # default therefore encodes today's real behaviour rather than changing it.
44
+ DEFAULT_TELEGRAM_ALERT_CHANNELS = CHANNEL_ALERT_BITS[SPREE_CHANNEL]
45
+
46
+ included do
47
+ validate :validate_channel_prefix, if: :channel_changed?
48
+ end
49
+
50
+ # The stored channel may carry a suffix — the importer writes
51
+ # "google_form-<import_order_id>-<slug>" — so the prefix, not the whole
52
+ # string, is the channel's identity. Returns nil for an unrecognized channel.
53
+ def channel_key
54
+ SORTED_CHANNEL_PREFIXES.find { |prefix| channel&.start_with?(prefix) }
55
+ end
56
+
57
+ # Order was created by an operator through the back-office Sell Ticket console.
58
+ def offline_sell?
59
+ channel_key == OFFLINE_SELL_CHANNEL
60
+ end
61
+
62
+ private
63
+
64
+ def validate_channel_prefix
65
+ return if channel_key.present?
66
+
67
+ errors.add(:channel, "must start with one of the following: #{ALLOWED_CHANNEL_PREFIXES.join(', ')}")
68
+ end
69
+ end
70
+ end
@@ -1,7 +1,7 @@
1
1
  # Make sure to put this concern below other concern or methods that generating additional order info like guests, seat number, etc.
2
2
  # This will ensure that when each notification is sent with neccessary data.
3
3
  module SpreeCmCommissioner
4
- module OrderStateMachine
4
+ module OrderStateMachine # rubocop:disable Metrics/ModuleLength
5
5
  extend ActiveSupport::Concern
6
6
 
7
7
  included do # rubocop:disable Metrics/BlockLength
@@ -271,15 +271,30 @@ module SpreeCmCommissioner
271
271
  return unless telegram_alert_enabled?
272
272
 
273
273
  vendor_list.each do |vendor|
274
- title = '🎫 --- [NEW ORDER FROM BOOKME+] ---'
274
+ # `next`, not `return`: the mask is per-vendor, so one opted-out vendor on a
275
+ # multi-vendor order must not suppress the others.
276
+ next unless vendor.alerts_telegram_for_channel?(channel_key)
277
+
275
278
  chat_id = vendor.preferred_telegram_chat_id
276
- if chat_id.present?
277
- factory = OrderTelegramMessageFactory.new(title: title, order: self, vendor: vendor)
278
- TelegramNotificationSenderJob.perform_later(chat_id: chat_id, message: factory.message, parse_mode: factory.parse_mode)
279
- end
279
+ next if chat_id.blank?
280
+
281
+ factory = OrderTelegramMessageFactory.new(title: vendor_alert_title(vendor), order: self, vendor: vendor)
282
+ TelegramNotificationSenderJob.perform_later(chat_id: chat_id, message: factory.message, parse_mode: factory.parse_mode)
280
283
  end
281
284
  end
282
285
 
286
+ # White-label vendors announce their own brand; platform vendors stay BookMe+.
287
+ #
288
+ # vendor.name is operator-supplied data interpolated into an HTML parse_mode message
289
+ # (TelegramMessageFactory#header wraps the title in <b>), so it MUST be escaped —
290
+ # Telegram rejects unescaped &, < and > with "400 can't parse entities", and
291
+ # TelegramNotificationSender swallows that error, so the alert would vanish silently.
292
+ def vendor_alert_title(vendor)
293
+ return '🎫 --- [NEW ORDER FROM BOOKME+] ---' unless vendor.tenant_present?
294
+
295
+ "🎫 --- [NEW ORDER FROM #{CGI.escapeHTML(vendor.name.to_s)}] ---"
296
+ end
297
+
283
298
  def notify_order_complete_app_notification_to_user
284
299
  return if products.all?(&:vote_package?) # disable app push notification for vote package orders
285
300
 
@@ -5,11 +5,11 @@ module SpreeCmCommissioner
5
5
  included do
6
6
  has_one :ticket_transfer, class_name: 'SpreeCmCommissioner::TicketTransfer'
7
7
 
8
- scope :not_ticket_transfer, -> { where.not(channel: SpreeCmCommissioner::OrderDecorator::TICKET_TRANSFER_CHANNEL) }
8
+ scope :not_ticket_transfer, -> { where.not(channel: SpreeCmCommissioner::OrderChannelBitwise::TICKET_TRANSFER_CHANNEL) }
9
9
  end
10
10
 
11
11
  def ticket_transfer?
12
- channel == SpreeCmCommissioner::OrderDecorator::TICKET_TRANSFER_CHANNEL
12
+ channel == SpreeCmCommissioner::OrderChannelBitwise::TICKET_TRANSFER_CHANNEL
13
13
  end
14
14
 
15
15
  # Completes an accepted ticket transfer for this order. Called from
@@ -8,6 +8,25 @@ module SpreeCmCommissioner
8
8
  preference :telegram_chat_id, :string
9
9
  preference :telegram_chat_name, :string
10
10
  preference :telegram_chat_type, :string
11
+ preference :telegram_alert_channels, :integer, default: 1
12
+ end
13
+
14
+ # Should this vendor's Telegram group be alerted for an order on this channel?
15
+ # An unmapped channel alerts — a stray message is a better failure than silence.
16
+ def alerts_telegram_for_channel?(channel_key)
17
+ bit = SpreeCmCommissioner::OrderChannelBitwise::CHANNEL_ALERT_BITS[channel_key]
18
+ return true if bit.nil?
19
+
20
+ telegram_alert_channels_mask.anybits?(bit)
21
+ end
22
+
23
+ # Spree's getter is `preferences.fetch(name) { default }`, which falls back only when the
24
+ # key is ABSENT. A key present with a nil value returns nil, and nil.to_i == 0 would mute
25
+ # EVERY channel silently. Fall back to the default instead; a deliberate 0 survives
26
+ # because 0 is truthy in Ruby.
27
+ def telegram_alert_channels_mask
28
+ (preferred_telegram_alert_channels ||
29
+ SpreeCmCommissioner::OrderChannelBitwise::DEFAULT_TELEGRAM_ALERT_CHANNELS).to_i
11
30
  end
12
31
  end
13
32
  end
@@ -303,6 +303,11 @@ module SpreeCmCommissioner
303
303
  Array(public_metadata['eligible_check_in_session_ids']).map(&:to_i)
304
304
  end
305
305
 
306
+ # Set by TicketTransfers::TransferGuest when this guest was created to receive a transferred ticket
307
+ def from_transfer?
308
+ ActiveModel::Type::Boolean.new.cast(public_metadata['from_transfer']) || false
309
+ end
310
+
306
311
  def eligible_check_in_session_ids=(ids)
307
312
  # Ensure public_metadata is a hash
308
313
  self.public_metadata = {} if public_metadata.nil?
@@ -1,12 +1,7 @@
1
1
  module SpreeCmCommissioner
2
2
  module OrderDecorator
3
- SPREE_CHANNEL = 'spree'.freeze
4
- GOOGLE_FORM_CHANNEL = 'google_form'.freeze
5
- TELEGRAM_CHANNEL = 'telegram'.freeze
6
- TICKET_TRANSFER_CHANNEL = 'ticket_transfer'.freeze
7
- ALLOWED_CHANNEL_PREFIXES = [SPREE_CHANNEL, GOOGLE_FORM_CHANNEL, TELEGRAM_CHANNEL, TICKET_TRANSFER_CHANNEL].freeze
8
-
9
3
  def self.prepended(base) # rubocop:disable Metrics/MethodLength
4
+ base.include SpreeCmCommissioner::OrderChannelBitwise
10
5
  base.include SpreeCmCommissioner::StoreMetadata
11
6
  base.include SpreeCmCommissioner::PhoneNumberSanitizer
12
7
  base.include SpreeCmCommissioner::OrderIntegration
@@ -27,7 +22,6 @@ module SpreeCmCommissioner
27
22
  base.store_public_metadata :order_options, :array, default: []
28
23
 
29
24
  base.validates :promo_total, base::MONEY_VALIDATION
30
- base.validate :validate_channel_prefix, if: :channel_changed?
31
25
  base.validates :phone_number, presence: true, if: :require_phone_number
32
26
 
33
27
  base.has_one :invoice, dependent: :destroy, class_name: 'SpreeCmCommissioner::Invoice'
@@ -296,7 +290,7 @@ module SpreeCmCommissioner
296
290
 
297
291
  # override spree_vpago method
298
292
  def payment_host
299
- tenant&.payment_url.presence || tenant&.formatted_url.presence || ENV.fetch('DEFAULT_URL_HOST')
293
+ tenant&.payment_url.presence || tenant&.formatted_url.presence || ENV.fetch('PAYMENT_BASE_URL')
300
294
  end
301
295
 
302
296
  # Returns arrays of connected line_item IDs grouped by connected_trip_id.
@@ -363,12 +357,6 @@ module SpreeCmCommissioner
363
357
  self.ship_address ||= customer.ship_address.try(:clone)
364
358
  end
365
359
 
366
- def validate_channel_prefix
367
- return if ALLOWED_CHANNEL_PREFIXES.any? { |prefix| channel&.start_with?(prefix) }
368
-
369
- errors.add(:channel, "must start with one of the following: #{ALLOWED_CHANNEL_PREFIXES.join(', ')}")
370
- end
371
-
372
360
  def set_tenant_id
373
361
  self.tenant_id = MultiTenant.current_tenant_id
374
362
  end
@@ -66,6 +66,10 @@ module SpreeCmCommissioner
66
66
  gift? || manual_payment?
67
67
  end
68
68
 
69
+ def requires_payment?
70
+ !free_transfer? && total.positive?
71
+ end
72
+
69
73
  # Records an audit trail of settlement_status changes to spree_state_changes.
70
74
  # Call this explicitly after a successful save to capture who changed the status and when.
71
75
  def log_settlement_status_changes(user_id:)
@@ -15,6 +15,7 @@ module SpreeCmCommissioner
15
15
  attribute :allowed_checkout, &:allowed_checkout?
16
16
  attribute :allowed_upload_later, &:allowed_upload_later?
17
17
  attribute :require_kyc_field, &:require_kyc_field?
18
+ attribute :from_transfer, &:from_transfer?
18
19
 
19
20
  belongs_to :occupation, serializer: Spree::V2::Storefront::TaxonSerializer
20
21
  belongs_to :nationality, serializer: Spree::V2::Storefront::TaxonSerializer
@@ -1,13 +1,24 @@
1
1
  module SpreeCmCommissioner
2
2
  module Checkout
3
3
  module CompleteDecorator
4
- # Override to bypass the order state machine for ticket transfer orders.
5
- #
6
- # Transfer orders skip guest finalization, inventory unstocking,
7
- # notifications, and all other callbacks that normally fire on completion.
4
+ # Bypass the order state machine for transfer orders (skips guest finalization,
5
+ # unstocking, notifications). That also skips finalize!, which normally reconciles
6
+ # payment_state, so we reconcile it here to match the real order payment flow.
7
+ # It matters because with an auto-capture gateway the payment reaches :completed
8
+ # before completion, so Spree::Payment#update_order never sets payment_state
9
+ # (gated on order.completed?), leaving it nil. We call Spree's canonical
10
+ # update_payment_state, not the full updater.update, to leave transfer totals intact.
8
11
  def call(order:)
9
12
  if order.ticket_transfer?
10
- order.update_columns(state: 'complete', completed_at: Time.current) # rubocop:disable Rails/SkipsModelValidations
13
+ order.updater.update_payment_total
14
+ order.updater.update_payment_state
15
+
16
+ order.update_columns( # rubocop:disable Rails/SkipsModelValidations
17
+ state: 'complete',
18
+ completed_at: order.completed_at || Time.current,
19
+ payment_state: order.payment_state,
20
+ payment_total: order.payment_total
21
+ )
11
22
  success(order)
12
23
  else
13
24
  super
@@ -3,7 +3,9 @@ module SpreeCmCommissioner
3
3
  class Create
4
4
  prepend ::Spree::ServiceModule::Base
5
5
 
6
- def call(trip_id:, from_date:, to_date:, user: nil, quantity: 1)
6
+ def call(trip_id:, from_date:, to_date:, user: nil, quantity: 1, created_by: nil, # rubocop:disable Metrics/ParameterLists
7
+ channel: SpreeCmCommissioner::OrderChannelBitwise::SPREE_CHANNEL
8
+ )
7
9
  validate!(trip_id: trip_id, from_date: from_date, to_date: to_date, quantity: quantity)
8
10
 
9
11
  quantity = quantity.to_i
@@ -13,7 +15,7 @@ module SpreeCmCommissioner
13
15
  variant = trip.product.variants.first
14
16
  raise ArgumentError, 'No variant found for trip' if variant.blank?
15
17
 
16
- order = Spree::Order.new(state: 'cart', use_billing: true, user: user)
18
+ order = Spree::Order.new(state: 'cart', use_billing: true, user: user, created_by: created_by, channel: channel)
17
19
 
18
20
  metadata = {
19
21
  trip_id: trip.id,
@@ -15,7 +15,7 @@ module SpreeCmCommissioner
15
15
  order = create_transfer_order!(ticket_transfer, buyer)
16
16
  ticket_transfer.update!(state: :accepted, order: order, to_user: buyer)
17
17
  ticket_transfer.log_state_changes(user_id: buyer.id)
18
- create_payment!(ticket_transfer.order, ticket_transfer) if ticket_transfer.free_transfer?
18
+ create_payment!(ticket_transfer.order, ticket_transfer) unless ticket_transfer.requires_payment?
19
19
 
20
20
  success(ticket_transfer: ticket_transfer, order: order)
21
21
  end
@@ -71,12 +71,12 @@ module SpreeCmCommissioner
71
71
  order = Spree::Order.create!(
72
72
  user_id: buyer.id,
73
73
  store_id: Spree::Store.default.id,
74
- channel: SpreeCmCommissioner::OrderDecorator::TICKET_TRANSFER_CHANNEL,
74
+ channel: SpreeCmCommissioner::OrderChannelBitwise::TICKET_TRANSFER_CHANNEL,
75
75
  email: buyer.email,
76
76
  phone_number: buyer.phone_number,
77
77
  currency: ticket_transfer.currency,
78
- state: ticket_transfer.free_transfer? ? 'complete' : 'payment',
79
- completed_at: ticket_transfer.free_transfer? ? Time.current : nil,
78
+ state: ticket_transfer.requires_payment? ? 'payment' : 'complete',
79
+ completed_at: ticket_transfer.requires_payment? ? nil : Time.current,
80
80
  item_total: ticket_transfer.price,
81
81
  total: ticket_transfer.total
82
82
  )
@@ -103,7 +103,8 @@ module SpreeCmCommissioner
103
103
  order
104
104
  end
105
105
 
106
- # Creates a Check-type payment record to mark the order as paid for free transfers (gift/manual_payment).
106
+ # Creates a Check-type payment record to mark the order as paid when no real payment is needed
107
+ # (gift/manual_payment transfers, or a purchase transfer priced at 0).
107
108
  # Spree requires every completed order to have payment records; without this, the order stays in "balance_due".
108
109
  def create_payment!(order, ticket_transfer)
109
110
  payment = order.payments.create!(
@@ -16,19 +16,25 @@ module SpreeCmCommissioner
16
16
  class Create
17
17
  prepend ::Spree::ServiceModule::Base
18
18
 
19
- def call(outbound_date:, inbound_date:, outbound_legs:, inbound_legs: [], user: nil, include_return: false) # rubocop:disable Metrics/ParameterLists
19
+ def call(outbound_date:, inbound_date:, outbound_legs:, inbound_legs: [], user: nil, created_by: nil, # rubocop:disable Metrics/ParameterLists
20
+ include_return: false, channel: SpreeCmCommissioner::OrderChannelBitwise::SPREE_CHANNEL
21
+ )
20
22
  return failure(nil, 'Outbound legs are missing') if outbound_legs.blank?
21
23
 
22
24
  begin
23
- order = create_order!(outbound_date, inbound_date, outbound_legs, inbound_legs, user, include_return)
25
+ order = create_order!(outbound_date, inbound_date, outbound_legs, inbound_legs, user, include_return,
26
+ created_by: created_by, channel: channel
27
+ )
24
28
  success(order: order)
25
29
  rescue StandardError => e
26
30
  failure(nil, e.message)
27
31
  end
28
32
  end
29
33
 
30
- def create_order!(outbound_date, inbound_date, outbound_legs, inbound_legs, user, include_return) # rubocop:disable Metrics/AbcSize,Metrics/CyclomaticComplexity,Metrics/PerceivedComplexity,Metrics/ParameterLists
31
- order = Spree::Order.new(state: 'cart', use_billing: true, user: user)
34
+ def create_order!(outbound_date, inbound_date, outbound_legs, inbound_legs, user, include_return, # rubocop:disable Metrics/AbcSize,Metrics/CyclomaticComplexity,Metrics/PerceivedComplexity,Metrics/ParameterLists
35
+ created_by: nil, channel: SpreeCmCommissioner::OrderChannelBitwise::SPREE_CHANNEL
36
+ )
37
+ order = Spree::Order.new(state: 'cart', use_billing: true, user: user, created_by: created_by, channel: channel)
32
38
 
33
39
  all_legs = outbound_legs + inbound_legs
34
40
  preload_trips_and_stops!(all_legs)
@@ -16,6 +16,21 @@
16
16
  <%= f.label :preferred_telegram_chat_id, Spree.t(:telegram_chat_id) %>
17
17
  <%= f.text_field :preferred_telegram_chat_id, class: 'form-control', disabled: true %>
18
18
  <% end %>
19
+ <%= f.field_container :preferred_telegram_alert_channels do %>
20
+ <%= f.label :preferred_telegram_alert_channels, Spree.t(:telegram_alert_channels) %>
21
+ <%# Without this, unticking every box submits no key at all and the mask would keep its old value. %>
22
+ <%= hidden_field_tag 'vendor[telegram_alert_channels][]', 0 %>
23
+ <% SpreeCmCommissioner::OrderChannelBitwise::CHANNEL_ALERT_BITS.each do |channel, bit| %>
24
+ <div class="form-check">
25
+ <%= check_box_tag 'vendor[telegram_alert_channels][]', bit,
26
+ @vendor.telegram_alert_channels_mask.anybits?(bit),
27
+ id: "telegram_alert_channel_#{channel}", class: 'form-check-input' %>
28
+ <%= label_tag "telegram_alert_channel_#{channel}",
29
+ I18n.t("views.organizer.order.channel_values.#{channel}", default: channel.humanize),
30
+ class: 'form-check-label' %>
31
+ </div>
32
+ <% end %>
33
+ <% end %>
19
34
  <small class="form-text text-muted">
20
35
  <ul>
21
36
  <% allow_extensions = SpreeCmCommissioner::VectorIcon::ACCEPTED_EXTENSIONS.to_sentence %>
@@ -270,6 +270,10 @@ en:
270
270
  enable_telegram_alert: "Enable Telegram Alert"
271
271
  enable_send_receipt: "Enable Send Receipt"
272
272
  enable_social_sharing_email: "Enable Social Sharing Email"
273
+ telegram_alert_channels: "Telegram Alert Channels"
274
+ telegram_chat_name: "Telegram Chat Name"
275
+ telegram_chat_type: "Telegram Chat Type"
276
+ telegram_chat_id: "Telegram Chat ID"
273
277
  registered_by:
274
278
  system_registered: "System Registered"
275
279
  self_registered: "Self Registered"
@@ -1,5 +1,5 @@
1
1
  module SpreeCmCommissioner
2
- VERSION = '2.10.1'.freeze
2
+ VERSION = '2.10.2-pre1'.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.10.1
4
+ version: 2.10.2.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-08-14 00:00:00.000000000 Z
11
+ date: 2026-08-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: spree
@@ -1477,6 +1477,7 @@ files:
1477
1477
  - app/models/concerns/spree_cm_commissioner/metafield.rb
1478
1478
  - app/models/concerns/spree_cm_commissioner/option_type_attr_type.rb
1479
1479
  - app/models/concerns/spree_cm_commissioner/option_value_attr_type.rb
1480
+ - app/models/concerns/spree_cm_commissioner/order_channel_bitwise.rb
1480
1481
  - app/models/concerns/spree_cm_commissioner/order_holdable.rb
1481
1482
  - app/models/concerns/spree_cm_commissioner/order_integration.rb
1482
1483
  - app/models/concerns/spree_cm_commissioner/order_qr_codeable.rb
@@ -3716,9 +3717,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
3716
3717
  version: '2.7'
3717
3718
  required_rubygems_version: !ruby/object:Gem::Requirement
3718
3719
  requirements:
3719
- - - ">="
3720
+ - - ">"
3720
3721
  - !ruby/object:Gem::Version
3721
- version: '0'
3722
+ version: 1.3.1
3722
3723
  requirements:
3723
3724
  - none
3724
3725
  rubygems_version: 3.4.1