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 +4 -4
- data/Gemfile.lock +1 -1
- data/app/controllers/spree/admin/vendor_authorized_users_controller.rb +15 -0
- data/app/models/concerns/spree_cm_commissioner/order_channel_bitwise.rb +70 -0
- data/app/models/concerns/spree_cm_commissioner/order_state_machine.rb +21 -6
- data/app/models/concerns/spree_cm_commissioner/ticket_transferable.rb +2 -2
- data/app/models/concerns/spree_cm_commissioner/vendor_preference.rb +19 -0
- data/app/models/spree_cm_commissioner/guest.rb +5 -0
- data/app/models/spree_cm_commissioner/order_decorator.rb +2 -14
- data/app/models/spree_cm_commissioner/ticket_transfer.rb +4 -0
- data/app/serializers/spree_cm_commissioner/v2/storefront/guest_serializer.rb +1 -0
- data/app/services/spree_cm_commissioner/checkout/complete_decorator.rb +16 -5
- data/app/services/spree_cm_commissioner/intercity_taxi_order/create.rb +4 -2
- data/app/services/spree_cm_commissioner/ticket_transfers/accept.rb +6 -5
- data/app/services/spree_cm_commissioner/transit_order/create.rb +10 -4
- data/app/views/spree/admin/vendor_authorized_users/index.html.erb +15 -0
- data/config/locales/en.yml +4 -0
- data/lib/spree_cm_commissioner/version.rb +1 -1
- metadata +5 -4
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: e5552124388d0792051115573a9cc5e51044c8edcf7f8e89c6f03b43d2ebd0ab
|
|
4
|
+
data.tar.gz: '0694645f790079a03ebad09626ca155e7495c37ea8b45f83064a3c31b2aa6f75'
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 06b79003d8dee84088c17d6cd6f90b7d2b7d5eeca20b4045ca1775b467b3455b66898e72e47d33e9655a6b8b7c1b36dcef355b8b4ff5258daa066d87e8cdfb02
|
|
7
|
+
data.tar.gz: 386411dbfdd18ce5d25ade6d55e045b1bcaea788d3b8cb49437723789ab8e1e5e7e1b77e4cbece9ee962427f8b0c5c603c1cd1cdc091400ca8cf6e860dfd39a4
|
data/Gemfile.lock
CHANGED
|
@@ -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
|
-
|
|
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.
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
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::
|
|
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::
|
|
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('
|
|
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
|
-
#
|
|
5
|
-
#
|
|
6
|
-
#
|
|
7
|
-
#
|
|
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.
|
|
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)
|
|
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::
|
|
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.
|
|
79
|
-
completed_at: ticket_transfer.
|
|
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
|
|
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,
|
|
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
|
|
31
|
-
|
|
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 %>
|
data/config/locales/en.yml
CHANGED
|
@@ -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"
|
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.
|
|
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-
|
|
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:
|
|
3722
|
+
version: 1.3.1
|
|
3722
3723
|
requirements:
|
|
3723
3724
|
- none
|
|
3724
3725
|
rubygems_version: 3.4.1
|