spree_cm_commissioner 1.12.0 → 1.14.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.
- checksums.yaml +4 -4
- data/Gemfile.lock +1 -1
- data/app/controllers/spree/admin/product_places_controller.rb +2 -0
- data/app/controllers/spree/api/v2/organizer/invite_guests_controller.rb +90 -0
- data/app/factory/spree_cm_commissioner/invite_guest_claimed_telegram_message_factory.rb +120 -0
- data/app/finders/spree_cm_commissioner/products/find_decorator.rb +16 -0
- data/app/helpers/spree_cm_commissioner/transit/trip_helper.rb +12 -0
- data/app/interactors/spree_cm_commissioner/order_importer/multi_guest.rb +31 -0
- data/app/models/concerns/spree_cm_commissioner/order_state_machine.rb +2 -3
- data/app/models/spree_cm_commissioner/cms_page_decorator.rb +16 -1
- data/app/models/spree_cm_commissioner/invite_guest.rb +23 -0
- data/app/models/spree_cm_commissioner/place.rb +1 -1
- data/app/models/spree_cm_commissioner/product_place.rb +1 -0
- data/app/models/spree_cm_commissioner/taxon_decorator.rb +2 -0
- data/app/queries/spree_cm_commissioner/trip_query.rb +35 -25
- data/app/serializers/spree/v2/organizer/invite_guest_serializer.rb +13 -0
- data/app/serializers/spree_cm_commissioner/v2/storefront/guest_serializer.rb +2 -1
- data/app/views/spree_cm_commissioner/event_transactional_mailer/_mailer_stylesheets.html.erb +2 -0
- data/config/routes.rb +1 -0
- data/db/migrate/20250422014417_create_spree_cm_commissioner_invite_guest.rb +21 -0
- data/db/migrate/20250528073748_remove_unique_slug_index_on_spree_cms_pages.rb +12 -0
- data/db/migrate/20250528074043_add_unique_index_on_slug_tenant_id_deleted_at_to_spree_cms_pages.rb +13 -0
- data/lib/spree_cm_commissioner/test_helper/factories/cms_page_factory.rb +11 -0
- data/lib/spree_cm_commissioner/version.rb +1 -1
- metadata +13 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a83f128539c20da0667aaa913954b8d686df38054b90ea51ede36b2967a96c4b
|
4
|
+
data.tar.gz: 46fa67f9aff722e83efd60ae52bb640f5ba9b2576294625a3c07093cbf0c2784
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d48ff6f2945c262955121a7f7144c5fc4ad53afa23bb2b093baaefd985346276a60b82de985b1912ec5a8fb64e6e86d37eb163638c2261446c2f85945165c3df
|
7
|
+
data.tar.gz: 7e21994489d8d36559a632a0008a92ecf9902c95be865190624173b89e1c8ad6146f405744971dbd448935cf9a9557b60401f34b6d211ce833eca61880082719
|
data/Gemfile.lock
CHANGED
@@ -49,6 +49,8 @@ module Spree
|
|
49
49
|
place_json = Base64.strict_decode64(place_base_64_content)
|
50
50
|
place_hash = JSON.parse(place_json)
|
51
51
|
|
52
|
+
place_hash = place_hash.except('lft', 'rgt', 'parent_id', 'depth')
|
53
|
+
|
52
54
|
@place = SpreeCmCommissioner::Place.where(reference: place_hash['reference']).first_or_initialize do |place|
|
53
55
|
place.assign_attributes(place_hash)
|
54
56
|
end
|
@@ -0,0 +1,90 @@
|
|
1
|
+
module Spree
|
2
|
+
module Api
|
3
|
+
module V2
|
4
|
+
module Organizer
|
5
|
+
class InviteGuestsController < ::Spree::Api::V2::Organizer::BaseController
|
6
|
+
before_action :load_invite_guest_by_token, only: :show
|
7
|
+
before_action :load_invite_guest, :assign_line_item_data, only: :update
|
8
|
+
|
9
|
+
def show
|
10
|
+
render_serialized_payload { serialize_resource(@invite_guest) }
|
11
|
+
end
|
12
|
+
|
13
|
+
def update
|
14
|
+
return render_error(:revoked) if @invite_guest.revoked?
|
15
|
+
return render_error(:closed) if @invite_guest.expired?
|
16
|
+
return render_error(:fully_claimed) if @invite_guest.fully_claimed?
|
17
|
+
|
18
|
+
guest = @line_item.guests.new(guest_params)
|
19
|
+
guest.event_id = @invite_guest.event_id
|
20
|
+
|
21
|
+
if guest.save
|
22
|
+
@invite_guest.update(claimed_status: :claimed) if @line_item.guests.count == @invite_guest.quantity
|
23
|
+
send_guest_claimed_invitation_telegram_alert_to_vendor(guest)
|
24
|
+
|
25
|
+
render json: SpreeCmCommissioner::V2::Storefront::GuestSerializer.new(guest.reload).serializable_hash
|
26
|
+
else
|
27
|
+
render_error_payload(guest.errors.full_messages.to_sentence)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
def send_guest_claimed_invitation_telegram_alert_to_vendor(guest)
|
34
|
+
title = '📣 --- [NEW GUEST CLAIMED INVITATION] ---' # Style/StringLiterals
|
35
|
+
chat_id = guest.event.vendor.preferred_telegram_chat_id
|
36
|
+
return if chat_id.blank?
|
37
|
+
|
38
|
+
factory = SpreeCmCommissioner::InviteGuestClaimedTelegramMessageFactory.new(
|
39
|
+
title: title,
|
40
|
+
order: @invite_guest.order,
|
41
|
+
vendor: guest.event.vendor
|
42
|
+
)
|
43
|
+
SpreeCmCommissioner::TelegramNotificationSenderJob.perform_later(
|
44
|
+
chat_id: chat_id,
|
45
|
+
message: factory.message,
|
46
|
+
parse_mode: factory.parse_mode
|
47
|
+
)
|
48
|
+
end
|
49
|
+
|
50
|
+
def load_invite_guest_by_token
|
51
|
+
@invite_guest = SpreeCmCommissioner::InviteGuest.find_by(token: params[:id])
|
52
|
+
rescue ActiveRecord::RecordNotFound
|
53
|
+
render_error_payload(I18n.t('invite.url_not_found'))
|
54
|
+
end
|
55
|
+
|
56
|
+
def load_invite_guest
|
57
|
+
@invite_guest = SpreeCmCommissioner::InviteGuest.find(params[:id])
|
58
|
+
end
|
59
|
+
|
60
|
+
def assign_line_item_data
|
61
|
+
@line_item = @invite_guest.order.line_items.first
|
62
|
+
@guests = @line_item.guests
|
63
|
+
end
|
64
|
+
|
65
|
+
def render_error(message)
|
66
|
+
render json: { errors: message }
|
67
|
+
end
|
68
|
+
|
69
|
+
def guest_params
|
70
|
+
params.require(:invite_guest).permit(
|
71
|
+
:first_name,
|
72
|
+
:last_name,
|
73
|
+
:dob,
|
74
|
+
:gender,
|
75
|
+
:age,
|
76
|
+
:emergency_contact,
|
77
|
+
:phone_number,
|
78
|
+
:address,
|
79
|
+
:other_organization
|
80
|
+
)
|
81
|
+
end
|
82
|
+
|
83
|
+
def resource_serializer
|
84
|
+
::Spree::V2::Organizer::InviteGuestSerializer
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
@@ -0,0 +1,120 @@
|
|
1
|
+
# 🎟️ --- [TICKET CLAIMED] ---
|
2
|
+
#
|
3
|
+
# Order Number:
|
4
|
+
# <code>R621016753</code>
|
5
|
+
#
|
6
|
+
# ✅ <b>Ticket Successfully Claimed!</b>
|
7
|
+
#
|
8
|
+
# [ x1 ]
|
9
|
+
# <b>5km Running Ticket</b>
|
10
|
+
# <i>👉 Distance: 5km, T-shirt: M</i>
|
11
|
+
# <i>🗓️ Nov 15, 2023</i>
|
12
|
+
# <i>🏪 Temple Run with Sai</i>
|
13
|
+
#
|
14
|
+
# [ x2 ]
|
15
|
+
# <b>5km Running Ticket</b>
|
16
|
+
# <i>👉 Distance: 5km, T-shirt: S</i>
|
17
|
+
# <i>🗓️ Nov 15, 2023 -> Nov 17, 2023</i>
|
18
|
+
# <i>🏪 Temple Run with Sai</i>
|
19
|
+
#
|
20
|
+
# <b>🙍 Claimed By</b>
|
21
|
+
# Name: Vaneath Awesome
|
22
|
+
# Tel: <code>+85570760548</code>
|
23
|
+
# Email: <code>admin_dev@cm.com</code>
|
24
|
+
|
25
|
+
module SpreeCmCommissioner
|
26
|
+
class InviteGuestClaimedTelegramMessageFactory < TelegramMessageFactory
|
27
|
+
attr_reader :order, :vendor, :show_details_link
|
28
|
+
|
29
|
+
def initialize(title:, order:, subtitle: nil, show_details_link: nil, vendor: nil)
|
30
|
+
@order = order
|
31
|
+
@vendor = vendor
|
32
|
+
@show_details_link = show_details_link || false
|
33
|
+
|
34
|
+
super(title: title, subtitle: subtitle)
|
35
|
+
end
|
36
|
+
|
37
|
+
def selected_line_items
|
38
|
+
return order.line_items.for_vendor(vendor) if vendor.present?
|
39
|
+
|
40
|
+
order.line_items
|
41
|
+
end
|
42
|
+
|
43
|
+
# override
|
44
|
+
def body
|
45
|
+
text = []
|
46
|
+
text << "Order Number:\n<code>#{order.number}</code>\n"
|
47
|
+
text << "\n✅ <b>Ticket Successfully Claimed!</b>\n"
|
48
|
+
text << selected_line_items.map { |item| line_item_content(item) }.compact.join("\n\n")
|
49
|
+
text.compact.join("\n")
|
50
|
+
end
|
51
|
+
|
52
|
+
def line_item_content(line_item)
|
53
|
+
text = []
|
54
|
+
|
55
|
+
text << bold(line_item.product.name.to_s)
|
56
|
+
text << "Quantity: #{line_item.quantity}"
|
57
|
+
text << italic("👉 #{line_item.options_text}") if line_item.options_text.present?
|
58
|
+
text << italic(pretty_date_for(line_item)) if pretty_date_for(line_item).present?
|
59
|
+
text << italic("🏪 #{line_item.vendor.name}") if line_item.vendor&.name.present? && vendor.blank?
|
60
|
+
|
61
|
+
text.compact.join("\n")
|
62
|
+
end
|
63
|
+
|
64
|
+
def pretty_date_for(line_item)
|
65
|
+
return nil unless line_item.date_present?
|
66
|
+
|
67
|
+
from_date = pretty_date(line_item.from_date)
|
68
|
+
to_date = pretty_date(line_item.to_date)
|
69
|
+
|
70
|
+
if from_date == to_date
|
71
|
+
"🗓️ #{from_date}"
|
72
|
+
else
|
73
|
+
"🗓️ #{from_date} -> #{to_date}"
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
# override
|
78
|
+
def footer
|
79
|
+
text = []
|
80
|
+
|
81
|
+
text << bold('🙍 Claimed By')
|
82
|
+
text << "Name: #{order.name}"
|
83
|
+
text << "Tel: #{inline_code(order.intel_phone_number || order.phone_number)}"
|
84
|
+
text << "Email: #{inline_code(order.email)}" if order.email.present?
|
85
|
+
|
86
|
+
if show_details_link && order.guests.any?
|
87
|
+
text << ''
|
88
|
+
text << 'View Tickets:'
|
89
|
+
text += generate_guests_links(order.guests)
|
90
|
+
end
|
91
|
+
|
92
|
+
text.compact.join("\n")
|
93
|
+
end
|
94
|
+
|
95
|
+
# Result:
|
96
|
+
# | No. A24 | No. A24 |
|
97
|
+
# | No. A24 | No. A24 |
|
98
|
+
# | No. A24 | No. A24 |
|
99
|
+
# | No. A24 | No. A24 |
|
100
|
+
# | No. A24 | No. A24 |
|
101
|
+
# | No. A24 |
|
102
|
+
def generate_guests_links(guests, guests_per_row = 2)
|
103
|
+
rows = (guests.size.to_f / guests_per_row).ceil
|
104
|
+
formatted_rows = []
|
105
|
+
|
106
|
+
rows.times do |i|
|
107
|
+
row_guests = guests.slice(i * guests_per_row, guests_per_row)
|
108
|
+
formatted_row = row_guests.map do |guest|
|
109
|
+
button_label = guest.seat_number.present? ? "No. #{guest.seat_number}" : "No. #{guest.formatted_bib_number || 'N/A'}"
|
110
|
+
link = Rails.application.routes.url_helpers.guest_cards_url(guest.token)
|
111
|
+
"| <a href='#{link}'>#{button_label}</a>"
|
112
|
+
end.join(' ')
|
113
|
+
|
114
|
+
formatted_rows << ("#{formatted_row} |")
|
115
|
+
end
|
116
|
+
|
117
|
+
formatted_rows
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module SpreeCmCommissioner
|
2
|
+
module Products
|
3
|
+
module FindDecorator
|
4
|
+
# override: to return only visble products
|
5
|
+
def by_taxons(products)
|
6
|
+
return products unless taxons?
|
7
|
+
|
8
|
+
products.joins(:classifications).where(::Spree::Classification.table_name => { taxon_id: taxons, visible: true })
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
unless Spree::Products::Find.included_modules.include?(SpreeCmCommissioner::Products::FindDecorator)
|
15
|
+
Spree::Products::Find.prepend(SpreeCmCommissioner::Products::FindDecorator)
|
16
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
module SpreeCmCommissioner
|
2
|
+
module Transit
|
3
|
+
module TripHelper
|
4
|
+
def parse_time(time, timezone = nil)
|
5
|
+
return nil if time.blank?
|
6
|
+
|
7
|
+
formatted_time = Time.zone.parse(time.to_s)
|
8
|
+
timezone ? formatted_time.in_time_zone(timezone) : formatted_time
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module SpreeCmCommissioner
|
2
|
+
module OrderImporter
|
3
|
+
class MultiGuest < BaseInteractor
|
4
|
+
delegate :params, :quantity, to: :context
|
5
|
+
|
6
|
+
def call
|
7
|
+
return context.fail!(message: 'variant_id_is_required') if params[:variant_id].blank?
|
8
|
+
return context.fail!(message: 'email_or_phone_is_required') if params[:order_email].blank? && params[:order_phone_number].blank?
|
9
|
+
|
10
|
+
context.order = construct_order
|
11
|
+
context.fail!(message: context.order.errors.full_messages.to_sentence) unless context.order.save
|
12
|
+
end
|
13
|
+
|
14
|
+
def construct_order
|
15
|
+
Spree::Order.new(
|
16
|
+
email: params[:order_email],
|
17
|
+
phone_number: params[:order_phone_number],
|
18
|
+
completed_at: Date.current,
|
19
|
+
state: 'complete',
|
20
|
+
payment_state: 'paid',
|
21
|
+
line_items_attributes: [
|
22
|
+
{
|
23
|
+
quantity: quantity.to_i,
|
24
|
+
variant_id: params[:variant_id]
|
25
|
+
}
|
26
|
+
]
|
27
|
+
)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -98,13 +98,12 @@ module SpreeCmCommissioner
|
|
98
98
|
line_items.each do |line_item|
|
99
99
|
next if line_item.event.nil?
|
100
100
|
|
101
|
-
event_id
|
102
|
-
SpreeCmCommissioner::EventTransactionalMailer.send_to_participant(event_id, user.id).deliver_later
|
101
|
+
SpreeCmCommissioner::EventTransactionalMailer.send_to_participant(line_item.event_id, user.id).deliver_later
|
103
102
|
end
|
104
103
|
end
|
105
104
|
|
106
105
|
def user_has_email?
|
107
|
-
user.email.present?
|
106
|
+
user.present? && user.email.present?
|
108
107
|
end
|
109
108
|
|
110
109
|
# allow authorized user to accept all requested line items
|
@@ -2,8 +2,23 @@ module SpreeCmCommissioner
|
|
2
2
|
module CmsPageDecorator
|
3
3
|
def self.prepended(base)
|
4
4
|
base.belongs_to :tenant, class_name: 'SpreeCmCommissioner::Tenant'
|
5
|
+
|
6
|
+
base.validates :slug,
|
7
|
+
uniqueness: {
|
8
|
+
scope: %i[tenant_id deleted_at],
|
9
|
+
allow_nil: true,
|
10
|
+
case_sensitive: true
|
11
|
+
}
|
5
12
|
end
|
6
13
|
end
|
7
14
|
end
|
8
15
|
|
9
|
-
|
16
|
+
unless Spree::CmsPage.included_modules.include?(SpreeCmCommissioner::CmsPageDecorator)
|
17
|
+
# remove old :slug validations
|
18
|
+
Spree::CmsPage._validators.reject! { |key, _| key == :slug }
|
19
|
+
Spree::CmsPage._validate_callbacks.each do |c|
|
20
|
+
c.filter.attributes.delete(:slug) if c.filter.respond_to?(:attributes)
|
21
|
+
end
|
22
|
+
|
23
|
+
Spree::CmsPage.prepend(SpreeCmCommissioner::CmsPageDecorator)
|
24
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module SpreeCmCommissioner
|
2
|
+
class InviteGuest < SpreeCmCommissioner::Base
|
3
|
+
enum invite_type: { invite: 0, open: 1, sponsor: 2 }
|
4
|
+
enum claimed_status: { active: 0, claimed: 1, revoked: 2 }
|
5
|
+
|
6
|
+
belongs_to :variant, class_name: 'Spree::Variant'
|
7
|
+
belongs_to :order, class_name: 'Spree::Order'
|
8
|
+
belongs_to :event, class_name: 'Spree::Taxon'
|
9
|
+
|
10
|
+
self.whitelisted_ransackable_attributes = %w[claimed_status]
|
11
|
+
|
12
|
+
def expired?
|
13
|
+
expiration_date.present? && expiration_date < Time.current
|
14
|
+
end
|
15
|
+
|
16
|
+
def fully_claimed?
|
17
|
+
return false unless order.present? && order.line_items.any?
|
18
|
+
|
19
|
+
line_item = order.line_items.first
|
20
|
+
line_item.guests.count >= order.line_items.first.number_of_guests
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -17,7 +17,7 @@ module SpreeCmCommissioner
|
|
17
17
|
has_many :products, through: :product_places
|
18
18
|
|
19
19
|
has_many :children, -> { order(:lft) }, class_name: 'SpreeCmCommissioner::Place', foreign_key: :parent_id, dependent: :destroy
|
20
|
-
has_many :vendor_stops, class_name: 'SpreeCmCommissioner::VendorStop', dependent: :destroy
|
20
|
+
has_many :vendor_stops, class_name: 'SpreeCmCommissioner::VendorStop', dependent: :destroy, foreign_key: :stop_id
|
21
21
|
|
22
22
|
def self.ransackable_attributes(auth_object = nil)
|
23
23
|
super & %w[name code]
|
@@ -1,6 +1,7 @@
|
|
1
1
|
module SpreeCmCommissioner
|
2
2
|
class ProductPlace < Base
|
3
3
|
self.inheritance_column = '_type_disabled'
|
4
|
+
acts_as_list column: :position
|
4
5
|
|
5
6
|
belongs_to :product, class_name: 'Spree::Product', optional: false
|
6
7
|
belongs_to :place, class_name: 'SpreeCmCommissioner::Place', optional: false
|
@@ -55,6 +55,8 @@ module SpreeCmCommissioner
|
|
55
55
|
base.has_many :crew_invites, class_name: 'SpreeCmCommissioner::CrewInvite', dependent: :destroy
|
56
56
|
base.has_many :invite_user_events, through: :user_events, class_name: 'SpreeCmCommissioner::InviteUserEvent'
|
57
57
|
|
58
|
+
base.has_many :invite_guests, class_name: 'SpreeCmCommissioner::InviteGuest', foreign_key: :event_id
|
59
|
+
|
58
60
|
base.has_many :line_items, through: :products
|
59
61
|
base.has_many :event_line_items, class_name: 'Spree::LineItem', foreign_key: :event_id
|
60
62
|
|
@@ -1,21 +1,23 @@
|
|
1
1
|
module SpreeCmCommissioner
|
2
2
|
class TripQuery
|
3
|
-
|
3
|
+
include SpreeCmCommissioner::Transit::TripHelper
|
4
4
|
|
5
|
-
|
5
|
+
attr_reader :origin_id, :destination_id, :travel_date, :params
|
6
|
+
|
7
|
+
def initialize(origin_id:, destination_id:, travel_date:, params: {})
|
6
8
|
@origin_id = origin_id
|
7
9
|
@destination_id = destination_id
|
8
10
|
@travel_date = travel_date
|
11
|
+
@travel_date = Time.zone.now if travel_date.to_date == Time.zone.now.to_date
|
12
|
+
@params = params
|
9
13
|
end
|
10
14
|
|
11
15
|
def call
|
12
|
-
|
13
|
-
connections = connected_trips if trips.size < 3
|
14
|
-
|
15
|
-
trip_results = trips.map { |trip| SpreeCmCommissioner::TripQueryResult.new([trip]) }
|
16
|
+
return [] if travel_date.to_date < Date.current
|
16
17
|
|
17
|
-
|
18
|
-
|
18
|
+
direct_results = direct_trips.map { |trip| SpreeCmCommissioner::TripQueryResult.new([trip]) }
|
19
|
+
connected_results = connected_trips || []
|
20
|
+
direct_results + connected_results
|
19
21
|
end
|
20
22
|
|
21
23
|
def direct_trips
|
@@ -38,7 +40,12 @@ module SpreeCmCommissioner
|
|
38
40
|
.joins('INNER JOIN cm_trip_stops AS drop_off ON drop_off.trip_id = spree_variants.id AND drop_off.stop_type = 1')
|
39
41
|
.joins('INNER JOIN spree_vendors AS vendors ON vendors.id = spree_variants.vendor_id')
|
40
42
|
.joins('INNER JOIN spree_products AS routes ON routes.id = spree_variants.product_id')
|
41
|
-
|
43
|
+
result = result.where(vendors: { id: params[:vendor_id] }) if params[:vendor_id].present?
|
44
|
+
result = result.where('boarding.stop_id = ? AND drop_off.stop_id = ?', origin_id, destination_id)
|
45
|
+
.where('trips.departure_time > ? AND trips.departure_time <= ?',
|
46
|
+
travel_date.strftime('%H:%M:%S'),
|
47
|
+
travel_date.end_of_day.strftime('%H:%M:%S')
|
48
|
+
)
|
42
49
|
|
43
50
|
result.map do |trip|
|
44
51
|
trip_result_options = {
|
@@ -53,7 +60,7 @@ module SpreeCmCommissioner
|
|
53
60
|
destination_id: trip[:destination_id],
|
54
61
|
destination: trip[:destination],
|
55
62
|
vehicle_id: trip[:vehicle_id],
|
56
|
-
departure_time: trip[:departure_time],
|
63
|
+
departure_time: parse_time(trip[:departure_time]),
|
57
64
|
duration: trip[:duration]
|
58
65
|
}
|
59
66
|
SpreeCmCommissioner::TripResult.new(trip_result_options)
|
@@ -63,17 +70,17 @@ module SpreeCmCommissioner
|
|
63
70
|
def connected_trips # rubocop:disable Metrics/MethodLength
|
64
71
|
result = SpreeCmCommissioner::TripConnection
|
65
72
|
.joins('
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
73
|
+
INNER JOIN spree_variants variant1 ON variant1.id = cm_trip_connections.from_trip_id
|
74
|
+
INNER JOIN spree_variants variant2 ON variant2.id = cm_trip_connections.to_trip_id
|
75
|
+
INNER JOIN spree_products AS routes1 ON routes1.id = variant1.product_id
|
76
|
+
INNER JOIN spree_products AS routes2 ON routes2.id = variant2.product_id
|
77
|
+
INNER JOIN cm_trips AS trip1 ON trip1.variant_id = cm_trip_connections.from_trip_id
|
78
|
+
INNER JOIN cm_trips AS trip2 ON trip2.variant_id = cm_trip_connections.to_trip_id
|
79
|
+
INNER JOIN cm_trip_stops trip1_origin ON trip1_origin.trip_id = variant1.id AND trip1_origin.stop_type = 0
|
80
|
+
INNER JOIN cm_trip_stops trip2_origin ON trip2_origin.trip_id = variant2.id AND trip2_origin.stop_type = 0
|
81
|
+
INNER JOIN cm_trip_stops trip2_destination ON trip2_destination.trip_id = variant2.id AND trip2_destination.stop_type = 1
|
82
|
+
INNER JOIN spree_vendors AS vendor1 ON vendor1.id = variant1.vendor_id
|
83
|
+
INNER JOIN spree_vendors AS vendor2 ON vendor2.id = variant2.vendor_id'
|
77
84
|
)
|
78
85
|
.select('cm_trip_connections.id AS id,
|
79
86
|
trip1.variant_id AS trip1_id,
|
@@ -97,8 +104,11 @@ module SpreeCmCommissioner
|
|
97
104
|
trip2_origin.stop_name AS trip2_origin,
|
98
105
|
trip2_destination.stop_name AS trip2_destination,
|
99
106
|
vendor2.name AS trip2_vendor_name'
|
100
|
-
).where('trip1_origin.stop_id = ? AND trip2_destination.stop_id = ?', origin_id, destination_id
|
101
|
-
|
107
|
+
).where('trip1_origin.stop_id = ? AND trip2_destination.stop_id = ?', origin_id, destination_id)
|
108
|
+
result = result.where('vendor1.id = ? OR vendor2.id = ?', params[:vendor_id], params[:vendor_id]) if params[:vendor_id].present?
|
109
|
+
result = result.where('trip1.departure_time > ? AND trip1.departure_time <= ?', travel_date.strftime('%H:%M:%S'),
|
110
|
+
travel_date.end_of_day.strftime('%H:%M:%S')
|
111
|
+
).uniq
|
102
112
|
|
103
113
|
return [] if result.blank?
|
104
114
|
|
@@ -113,7 +123,7 @@ module SpreeCmCommissioner
|
|
113
123
|
trip_id: trip[:trip1_id],
|
114
124
|
origin_id: trip[:trip1_origin_id],
|
115
125
|
destination_id: trip[:trip1_destination_id],
|
116
|
-
departure_time: trip[:trip1_departure_time],
|
126
|
+
departure_time: parse_time(trip[:trip1_departure_time]),
|
117
127
|
duration: trip[:trip1_duration],
|
118
128
|
vendor_name: trip[:trip1_vendor_name],
|
119
129
|
route_name: trip[:route1_name],
|
@@ -126,7 +136,7 @@ module SpreeCmCommissioner
|
|
126
136
|
trip_id: trip[:trip2_id],
|
127
137
|
origin_id: trip[:trip2_origin_id],
|
128
138
|
destination_id: trip[:trip2_destination_id],
|
129
|
-
departure_time: trip[:trip2_departure_time],
|
139
|
+
departure_time: parse_time(trip[:trip2_departure_time]),
|
130
140
|
duration: trip[:trip2_duration],
|
131
141
|
vendor_name: trip[:trip2_vendor_name],
|
132
142
|
route_name: trip[:route2_name],
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module Spree
|
2
|
+
module V2
|
3
|
+
module Organizer
|
4
|
+
class InviteGuestSerializer < BaseSerializer
|
5
|
+
attributes :email, :quantity, :token, :invite_type, :claimed_status, :issued_to, :expiration_date,
|
6
|
+
:claimed_at, :email_send_at, :created_at, :updated_at, :remark
|
7
|
+
belongs_to :variant, serializer: SpreeCmCommissioner::V2::Storefront::EventVariantSerializer
|
8
|
+
belongs_to :order, serializer: Spree::V2::Storefront::OrderSerializer
|
9
|
+
belongs_to :event, serializer: Spree::V2::Storefront::TaxonSerializer
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -6,7 +6,8 @@ module SpreeCmCommissioner
|
|
6
6
|
|
7
7
|
attributes :first_name, :last_name, :dob, :gender, :kyc_fields, :other_occupation, :created_at, :updated_at,
|
8
8
|
:qr_data, :social_contact_platform, :social_contact, :available_social_contact_platforms,
|
9
|
-
:age, :emergency_contact, :other_organization, :expectation, :upload_later, :address, :formatted_bib_number, :phone_number
|
9
|
+
:age, :emergency_contact, :other_organization, :expectation, :upload_later, :address, :formatted_bib_number, :phone_number,
|
10
|
+
:token
|
10
11
|
|
11
12
|
# temporary, once app release after cm-app v1.9.1, we no longer need this.
|
12
13
|
attribute :seat_number do |object|
|
data/config/routes.rb
CHANGED
@@ -0,0 +1,21 @@
|
|
1
|
+
class CreateSpreeCmCommissionerInviteGuest < ActiveRecord::Migration[7.0]
|
2
|
+
def change
|
3
|
+
create_table :cm_invite_guests, if_not_exists: true do |t|
|
4
|
+
t.references :variant, foreign_key: { to_table: :spree_variants }, null: true, index: true
|
5
|
+
t.references :order, foreign_key: { to_table: :spree_orders }, null: true, index: true
|
6
|
+
t.references :event, foreign_key: { to_table: :spree_taxons }, null: true, index: true
|
7
|
+
t.string :email, index: true
|
8
|
+
t.integer :quantity, default: 1
|
9
|
+
t.string :token, null: false, unique: true, index: true
|
10
|
+
t.integer :invite_type, default: 0
|
11
|
+
t.integer :claimed_status, default: 0
|
12
|
+
t.string :issued_to
|
13
|
+
t.datetime :expiration_date
|
14
|
+
t.text :remark
|
15
|
+
t.datetime :expires_at
|
16
|
+
t.datetime :claimed_at
|
17
|
+
t.datetime :email_send_at
|
18
|
+
t.timestamps
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
class RemoveUniqueSlugIndexOnSpreeCmsPages < ActiveRecord::Migration[7.0]
|
2
|
+
def change
|
3
|
+
if index_exists?(:spree_cms_pages,
|
4
|
+
[:slug, :store_id, :deleted_at],
|
5
|
+
unique: true,
|
6
|
+
name: "index_spree_cms_pages_on_slug_and_store_id_and_deleted_at")
|
7
|
+
|
8
|
+
remove_index :spree_cms_pages,
|
9
|
+
name: "index_spree_cms_pages_on_slug_and_store_id_and_deleted_at"
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
data/db/migrate/20250528074043_add_unique_index_on_slug_tenant_id_deleted_at_to_spree_cms_pages.rb
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
class AddUniqueIndexOnSlugTenantIdDeletedAtToSpreeCmsPages < ActiveRecord::Migration[7.0]
|
2
|
+
def change
|
3
|
+
unless index_exists?(:spree_cms_pages,
|
4
|
+
[:slug, :tenant_id, :deleted_at],
|
5
|
+
unique: true,
|
6
|
+
name: "index_spree_cms_pages_on_slug_and_tenant_id_and_deleted_at")
|
7
|
+
|
8
|
+
add_index :spree_cms_pages, [:slug, :tenant_id, :deleted_at],
|
9
|
+
unique: true,
|
10
|
+
name: "index_spree_cms_pages_on_slug_and_tenant_id_and_deleted_at"
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
FactoryBot.define do
|
2
|
+
factory :cm_cms_page, class: 'Spree::CmsPage' do
|
3
|
+
sequence(:slug) { |n| "page-slug-#{n}" }
|
4
|
+
title { "Sample Page Title" }
|
5
|
+
association :store, factory: :store
|
6
|
+
locale { 'en' }
|
7
|
+
type { 'Spree::Cms::Pages::StandardPage' }
|
8
|
+
tenant { nil }
|
9
|
+
deleted_at { nil }
|
10
|
+
end
|
11
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: spree_cm_commissioner
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.14.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- You
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2025-05-
|
11
|
+
date: 2025-05-30 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: spree
|
@@ -779,6 +779,7 @@ files:
|
|
779
779
|
- app/controllers/spree/api/v2/operator/taxons_controller.rb
|
780
780
|
- app/controllers/spree/api/v2/organizer/base_controller.rb
|
781
781
|
- app/controllers/spree/api/v2/organizer/images_controller.rb
|
782
|
+
- app/controllers/spree/api/v2/organizer/invite_guests_controller.rb
|
782
783
|
- app/controllers/spree/api/v2/organizer/invites_controller.rb
|
783
784
|
- app/controllers/spree/api/v2/organizer/s3_signed_urls_controller.rb
|
784
785
|
- app/controllers/spree/api/v2/organizer/ticket_images_controller.rb
|
@@ -960,12 +961,14 @@ files:
|
|
960
961
|
- app/errors/spree_cm_commissioner/unauthorized_event_error.rb
|
961
962
|
- app/errors/spree_cm_commissioner/unauthorized_vendor_error.rb
|
962
963
|
- app/exception_notifier/spree_cm_commissioner/telegram_notifier.rb
|
964
|
+
- app/factory/spree_cm_commissioner/invite_guest_claimed_telegram_message_factory.rb
|
963
965
|
- app/factory/spree_cm_commissioner/order_telegram_message_factory.rb
|
964
966
|
- app/factory/spree_cm_commissioner/telegram_message_factory.rb
|
965
967
|
- app/finders/spree_cm_commissioner/line_items/find_by_variant_decorator.rb
|
966
968
|
- app/finders/spree_cm_commissioner/orders/find.rb
|
967
969
|
- app/finders/spree_cm_commissioner/orders/find_by_state.rb
|
968
970
|
- app/finders/spree_cm_commissioner/payment_methods/group_by_bank.rb
|
971
|
+
- app/finders/spree_cm_commissioner/products/find_decorator.rb
|
969
972
|
- app/helpers/spree/admin/base_helper_decorator.rb
|
970
973
|
- app/helpers/spree/admin/google_wallets_helper.rb
|
971
974
|
- app/helpers/spree/base_helper_decorator.rb
|
@@ -984,6 +987,7 @@ files:
|
|
984
987
|
- app/helpers/spree_cm_commissioner/pin_code_sender_helper.rb
|
985
988
|
- app/helpers/spree_cm_commissioner/telegram/base_helper.rb
|
986
989
|
- app/helpers/spree_cm_commissioner/transit/service_calendars_helper.rb
|
990
|
+
- app/helpers/spree_cm_commissioner/transit/trip_helper.rb
|
987
991
|
- app/interactors/spree_cm_commissioner/accommodation_search_detail.rb
|
988
992
|
- app/interactors/spree_cm_commissioner/account_deletion.rb
|
989
993
|
- app/interactors/spree_cm_commissioner/account_deletion_cron_executor.rb
|
@@ -1034,6 +1038,7 @@ files:
|
|
1034
1038
|
- app/interactors/spree_cm_commissioner/order_accepted_state_updater.rb
|
1035
1039
|
- app/interactors/spree_cm_commissioner/order_complete_notification_sender.rb
|
1036
1040
|
- app/interactors/spree_cm_commissioner/order_complete_telegram_sender.rb
|
1041
|
+
- app/interactors/spree_cm_commissioner/order_importer/multi_guest.rb
|
1037
1042
|
- app/interactors/spree_cm_commissioner/order_importer/single_guest.rb
|
1038
1043
|
- app/interactors/spree_cm_commissioner/order_rejected_notification_sender.rb
|
1039
1044
|
- app/interactors/spree_cm_commissioner/order_rejected_state_updater.rb
|
@@ -1211,6 +1216,7 @@ files:
|
|
1211
1216
|
- app/models/spree_cm_commissioner/import.rb
|
1212
1217
|
- app/models/spree_cm_commissioner/imports/import_order.rb
|
1213
1218
|
- app/models/spree_cm_commissioner/invite.rb
|
1219
|
+
- app/models/spree_cm_commissioner/invite_guest.rb
|
1214
1220
|
- app/models/spree_cm_commissioner/invite_user_event.rb
|
1215
1221
|
- app/models/spree_cm_commissioner/invite_user_taxon.rb
|
1216
1222
|
- app/models/spree_cm_commissioner/invoice.rb
|
@@ -1498,6 +1504,7 @@ files:
|
|
1498
1504
|
- app/serializers/spree/v2/organizer/asset_serializer.rb
|
1499
1505
|
- app/serializers/spree/v2/organizer/base_serializer.rb
|
1500
1506
|
- app/serializers/spree/v2/organizer/image_serializer.rb
|
1507
|
+
- app/serializers/spree/v2/organizer/invite_guest_serializer.rb
|
1501
1508
|
- app/serializers/spree/v2/organizer/invite_serializer.rb
|
1502
1509
|
- app/serializers/spree/v2/organizer/s3_signed_url_serializer.rb
|
1503
1510
|
- app/serializers/spree/v2/organizer/taxon_serializer.rb
|
@@ -2405,6 +2412,7 @@ files:
|
|
2405
2412
|
- db/migrate/20250404050117_add_archived_at_to_spree_orders.rb
|
2406
2413
|
- db/migrate/20250407092556_add_variant_id_to_cm_trips.rb
|
2407
2414
|
- db/migrate/20250418072528_add_nested_set_columns_to_places.rb
|
2415
|
+
- db/migrate/20250422014417_create_spree_cm_commissioner_invite_guest.rb
|
2408
2416
|
- db/migrate/20250425084929_add_description_to_spree_prototypes.rb
|
2409
2417
|
- db/migrate/20250425085938_add_preferences_to_spree_prototypes.rb
|
2410
2418
|
- db/migrate/20250428025645_add_slug_to_spree_prototypes.rb
|
@@ -2418,6 +2426,8 @@ files:
|
|
2418
2426
|
- db/migrate/20250520044533_add_event_to_spree_line_items.rb
|
2419
2427
|
- db/migrate/20250521024345_add_tenant_id_to_cm_waiting_room_sessions.rb
|
2420
2428
|
- db/migrate/20250521095539_add_kyc_to_spree_variants.rb
|
2429
|
+
- db/migrate/20250528073748_remove_unique_slug_index_on_spree_cms_pages.rb
|
2430
|
+
- db/migrate/20250528074043_add_unique_index_on_slug_tenant_id_deleted_at_to_spree_cms_pages.rb
|
2421
2431
|
- docker-compose.yml
|
2422
2432
|
- docs/option_types/attr_types.md
|
2423
2433
|
- docs/private_key.pem
|
@@ -2451,6 +2461,7 @@ files:
|
|
2451
2461
|
- lib/spree_cm_commissioner/test_helper/factories/back_image_factory.rb
|
2452
2462
|
- lib/spree_cm_commissioner/test_helper/factories/branch_factory.rb
|
2453
2463
|
- lib/spree_cm_commissioner/test_helper/factories/check_in_factory.rb
|
2464
|
+
- lib/spree_cm_commissioner/test_helper/factories/cms_page_factory.rb
|
2454
2465
|
- lib/spree_cm_commissioner/test_helper/factories/country_factory.rb
|
2455
2466
|
- lib/spree_cm_commissioner/test_helper/factories/customer_factory.rb
|
2456
2467
|
- lib/spree_cm_commissioner/test_helper/factories/customer_notification_factory.rb
|