spree_cm_commissioner 1.13.0 → 1.15.0.pre.beta1
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 +12 -1
- data/README.md +43 -1
- data/app/assets/images/category_icons/art_icon.png +0 -0
- data/app/assets/images/category_icons/concert_icon.png +0 -0
- data/app/assets/images/category_icons/fundraising_icon.png +0 -0
- data/app/assets/images/category_icons/marathon_icon.png +0 -0
- data/app/assets/images/category_icons/online_icon.png +0 -0
- data/app/assets/images/category_icons/workshop_icon.png +0 -0
- data/app/controllers/spree/admin/users_controller_decorator.rb +13 -0
- data/app/controllers/spree/api/chatrace/guests_controller.rb +2 -1
- data/app/controllers/spree/api/v2/organizer/invite_guests_controller.rb +21 -0
- data/app/controllers/spree/api/v2/storefront/cart_payment_method_groups_controller.rb +12 -1
- data/app/controllers/spree/api/v2/storefront/guests_controller.rb +3 -1
- data/app/controllers/spree/api/v2/tenant/cart_controller.rb +11 -0
- data/app/controllers/spree/api/v2/tenant/checkout_controller.rb +1 -0
- data/app/controllers/spree/api/v2/tenant/order_histories_controller.rb +65 -0
- data/app/controllers/spree_cm_commissioner/admin/variants_controller_decorator.rb +1 -1
- data/app/controllers/spree_cm_commissioner/well_known_controller.rb +46 -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/order_query_helper.rb +17 -0
- data/app/helpers/spree_cm_commissioner/transit/trip_helper.rb +12 -0
- data/app/interactors/spree_cm_commissioner/create_event.rb +31 -6
- data/app/interactors/spree_cm_commissioner/create_ticket.rb +36 -1
- data/app/interactors/spree_cm_commissioner/host_matcher.rb +28 -0
- data/app/interactors/spree_cm_commissioner/place_decoder.rb +16 -0
- data/app/interactors/spree_cm_commissioner/place_service.rb +32 -0
- data/app/interactors/spree_cm_commissioner/user_pin_code_authenticator.rb +9 -0
- data/app/models/concerns/spree_cm_commissioner/json_preference_validator.rb +23 -0
- data/app/models/concerns/spree_cm_commissioner/kyc_bitwise.rb +3 -1
- data/app/models/concerns/spree_cm_commissioner/store_preference.rb +2 -0
- data/app/models/concerns/spree_cm_commissioner/tenant_preference.rb +11 -0
- data/app/models/spree_cm_commissioner/cms_page_decorator.rb +16 -1
- data/app/models/spree_cm_commissioner/guest.rb +11 -2
- data/app/models/spree_cm_commissioner/invite_guest.rb +8 -0
- data/app/models/spree_cm_commissioner/order_decorator.rb +5 -0
- data/app/models/spree_cm_commissioner/payment_method_decorator.rb +8 -1
- data/app/models/spree_cm_commissioner/place.rb +3 -0
- data/app/models/spree_cm_commissioner/store_decorator.rb +2 -1
- data/app/models/spree_cm_commissioner/taxon_decorator.rb +4 -0
- data/app/models/spree_cm_commissioner/taxon_place.rb +12 -0
- data/app/models/spree_cm_commissioner/tenant.rb +5 -0
- data/app/models/spree_cm_commissioner/user_decorator.rb +14 -3
- data/app/models/spree_cm_commissioner/vendor_decorator.rb +7 -3
- data/app/models/spree_cm_commissioner/vendor_place.rb +11 -3
- data/app/overrides/spree/admin/stores/_form/store_preferences.html.erb.deface +85 -12
- data/app/overrides/spree/admin/variants/_form/kyc_field.html.erb.deface +3 -4
- data/app/queries/spree_cm_commissioner/reservation_query.rb +12 -0
- data/app/queries/spree_cm_commissioner/trip_query.rb +35 -25
- data/app/serializers/spree/v2/organizer/invite_guest_serializer.rb +1 -1
- data/app/serializers/spree/v2/storefront/taxon_serializer_decorator.rb +1 -0
- data/app/serializers/spree/v2/tenant/cart_serializer.rb +8 -0
- data/app/serializers/spree_cm_commissioner/v2/storefront/guest_serializer.rb +1 -1
- data/app/services/spree_cm_commissioner/organizer/export_invite_guest_csv_service.rb +63 -0
- data/app/services/spree_cm_commissioner/payment_method_type_mapper.rb +11 -0
- data/app/views/spree/admin/tenants/_form.html.erb +68 -2
- data/config/initializers/spree_permitted_attributes.rb +3 -0
- data/config/routes.rb +7 -0
- data/db/migrate/20250127081646_add_preferences_to_cm_tenants.rb +7 -0
- data/db/migrate/20250527043231_create_spree_commissioner_taxon_places.rb +15 -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/db/migrate/20250528090330_add_place_type_to_cm_vendor_place.rb +6 -0
- data/db/migrate/20250602094751_add_host_to_cm_tenants.rb +6 -0
- data/db/migrate/20250609015216_remove_claimed_at_and_expires_at_from_cm_invite_guest.rb +6 -0
- data/db/migrate/20250610080108_add_contact_to_cm_guests.rb +5 -0
- data/db/migrate/20250611023548_add_country_code_to_guests.rb +5 -0
- data/db/migrate/20250612035937_add_intel_phone_number_to_guests.rb +5 -0
- data/lib/spree_cm_commissioner/test_helper/factories/cms_page_factory.rb +11 -0
- data/lib/spree_cm_commissioner/test_helper/factories/invite_guests_factory.rb +6 -0
- data/lib/spree_cm_commissioner/test_helper/factories/tenant_factory.rb +1 -0
- data/lib/spree_cm_commissioner/test_helper/factories/vendor_place_factory.rb +17 -4
- data/lib/spree_cm_commissioner/version.rb +1 -1
- data/lib/spree_cm_commissioner.rb +1 -0
- data/spree_cm_commissioner.gemspec +2 -0
- metadata +66 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b81b8e884fba65cb5081f039fe5c4eafbe2873a355c69f844dbbd8205b70b3fe
|
4
|
+
data.tar.gz: 6c6648d65bc80caeabb0d6fab484086647b9c80bcebb4d36e3160210be7aa3d4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 37e68c1ba296971013b060663e13758907ff0a567c413f1899f6b1f88d4f5eb7a17ceea8695ded4dbca9dd3be0d06669038fbf19e81ff230446b8c7e651a395d
|
7
|
+
data.tar.gz: 85f7a966e0396433617edc3375909fb92ca88bae2118fec2af8a99bd2d16d6e9b1af013ed3ad3f0ca08539f8395cde3e5312ea792e4b4f3974ccd98b62fbefcb
|
data/Gemfile.lock
CHANGED
@@ -34,7 +34,7 @@ GIT
|
|
34
34
|
PATH
|
35
35
|
remote: .
|
36
36
|
specs:
|
37
|
-
spree_cm_commissioner (1.
|
37
|
+
spree_cm_commissioner (1.15.0.pre.beta1)
|
38
38
|
activerecord-multi-tenant
|
39
39
|
activerecord_json_validator (~> 2.1, >= 2.1.3)
|
40
40
|
aws-sdk-cloudfront
|
@@ -66,6 +66,8 @@ PATH
|
|
66
66
|
spree_backend (>= 4.5.0)
|
67
67
|
spree_extension
|
68
68
|
spree_multi_vendor (>= 2.4.1)
|
69
|
+
spree_vpago
|
70
|
+
strong_password (~> 0.0.10)
|
69
71
|
telegram-bot
|
70
72
|
twilio-ruby (~> 5.48.0)
|
71
73
|
|
@@ -849,6 +851,14 @@ GEM
|
|
849
851
|
spree_backend (>= 4.3.0.rc1)
|
850
852
|
spree_emails (>= 4.3.0.rc1)
|
851
853
|
spree_extension
|
854
|
+
spree_vpago (2.0.5.pre.beta)
|
855
|
+
faraday
|
856
|
+
google-cloud-firestore
|
857
|
+
spree_api (>= 4.5)
|
858
|
+
spree_backend (>= 4.5)
|
859
|
+
spree_core (>= 4.5)
|
860
|
+
spree_extension
|
861
|
+
spree_multi_vendor (>= 2.4.1)
|
852
862
|
sprockets (4.2.1)
|
853
863
|
concurrent-ruby (~> 1.0)
|
854
864
|
rack (>= 2.2.4, < 4)
|
@@ -866,6 +876,7 @@ GEM
|
|
866
876
|
stimulus-rails (1.3.0)
|
867
877
|
railties (>= 6.0.0)
|
868
878
|
stringex (2.8.6)
|
879
|
+
strong_password (0.0.10)
|
869
880
|
telegram-bot (0.15.7)
|
870
881
|
actionpack (>= 4.0, < 7.1)
|
871
882
|
activesupport (>= 4.0, < 7.1)
|
data/README.md
CHANGED
@@ -123,6 +123,48 @@ EXCEPTION_TELEGRAM_BOT_TOKEN=""
|
|
123
123
|
EXCEPTION_NOTIFIER_TELEGRAM_CHANNEL_ID=""
|
124
124
|
```
|
125
125
|
|
126
|
+
## JSON Format Examples For Store and Tenant Preferences
|
127
|
+
|
128
|
+
### Asset Links Format
|
129
|
+
For Android app integration, use the following format in your `assetlinks.json`:
|
130
|
+
|
131
|
+
```json
|
132
|
+
[
|
133
|
+
{
|
134
|
+
"relation": ["delegate_permission/common.handle_all_urls"],
|
135
|
+
"target": {
|
136
|
+
"namespace": "android_app",
|
137
|
+
"package_name": "com.yourapp.app",
|
138
|
+
"sha256_cert_fingerprints": [
|
139
|
+
"SHA256_CERTIFICATE_FINGERPRINT_HERE"
|
140
|
+
]
|
141
|
+
}
|
142
|
+
}
|
143
|
+
]
|
144
|
+
```
|
145
|
+
|
146
|
+
### Apple App Site Association Format
|
147
|
+
For iOS app integration, use the following format in your `apple-app-site-association`:
|
148
|
+
|
149
|
+
```json
|
150
|
+
{
|
151
|
+
"webcredentials": {
|
152
|
+
"apps": [
|
153
|
+
"TEAM_ID.com.yourapp.app"
|
154
|
+
]
|
155
|
+
},
|
156
|
+
"applinks": {
|
157
|
+
"apps": [],
|
158
|
+
"details": [
|
159
|
+
{
|
160
|
+
"appID": "TEAM_ID.com.yourapp.app",
|
161
|
+
"paths": ["*"]
|
162
|
+
}
|
163
|
+
]
|
164
|
+
}
|
165
|
+
}
|
166
|
+
```
|
167
|
+
|
126
168
|
## Using Deface DSL (.deface files)
|
127
169
|
|
128
170
|
- Make sure the path of override should match the path of view template
|
@@ -338,7 +380,7 @@ end
|
|
338
380
|
|
339
381
|
## Protected Cloudfront with signed requests
|
340
382
|
|
341
|
-
To use signed cookies with CloudFront, you'll need to set up your CloudFront distribution to require signed cookies and then generate and distribute the signed cookies to your users. Here
|
383
|
+
To use signed cookies with CloudFront, you'll need to set up your CloudFront distribution to require signed cookies and then generate and distribute the signed cookies to your users. Here's how to do it using Terraform for infrastructure setup and Ruby for cookie generation.
|
342
384
|
|
343
385
|
### Generating keypair
|
344
386
|
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
@@ -5,6 +5,19 @@ module Spree
|
|
5
5
|
base.before_action :build_profile, only: %i[create update]
|
6
6
|
end
|
7
7
|
|
8
|
+
# override
|
9
|
+
def create
|
10
|
+
@user = Spree.user_class.new(user_params)
|
11
|
+
@user.assigned_roles = Spree::Role.where(id: params.dig(:user, :spree_role_ids)).pluck(:name) if params.dig(:user, :spree_role_ids)
|
12
|
+
|
13
|
+
if @user.save
|
14
|
+
flash[:success] = flash_message_for(@user, :successfully_created)
|
15
|
+
redirect_to spree.edit_admin_user_path(@user)
|
16
|
+
else
|
17
|
+
render :new, status: :unprocessable_entity
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
8
21
|
private
|
9
22
|
|
10
23
|
def build_profile
|
@@ -48,7 +48,8 @@ module Spree
|
|
48
48
|
order_phone_number: order.intel_phone_number || order.customer_address&.phone,
|
49
49
|
checked_in_at: guest.check_in&.confirmed_at,
|
50
50
|
qr_data: guest.qr_data,
|
51
|
-
order_qr_data: order.qr_data
|
51
|
+
order_qr_data: order.qr_data,
|
52
|
+
country_code: guest.country_code
|
52
53
|
}
|
53
54
|
end
|
54
55
|
end
|
@@ -16,9 +16,12 @@ module Spree
|
|
16
16
|
return render_error(:fully_claimed) if @invite_guest.fully_claimed?
|
17
17
|
|
18
18
|
guest = @line_item.guests.new(guest_params)
|
19
|
+
guest.event_id = @invite_guest.event_id
|
19
20
|
|
20
21
|
if guest.save
|
21
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
|
+
|
22
25
|
render json: SpreeCmCommissioner::V2::Storefront::GuestSerializer.new(guest.reload).serializable_hash
|
23
26
|
else
|
24
27
|
render_error_payload(guest.errors.full_messages.to_sentence)
|
@@ -27,6 +30,24 @@ module Spree
|
|
27
30
|
|
28
31
|
private
|
29
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
|
+
guest: guest,
|
42
|
+
vendor: guest.event.vendor
|
43
|
+
)
|
44
|
+
SpreeCmCommissioner::TelegramNotificationSenderJob.perform_later(
|
45
|
+
chat_id: chat_id,
|
46
|
+
message: factory.message,
|
47
|
+
parse_mode: factory.parse_mode
|
48
|
+
)
|
49
|
+
end
|
50
|
+
|
30
51
|
def load_invite_guest_by_token
|
31
52
|
@invite_guest = SpreeCmCommissioner::InviteGuest.find_by(token: params[:id])
|
32
53
|
rescue ActiveRecord::RecordNotFound
|
@@ -17,7 +17,7 @@ module Spree
|
|
17
17
|
# override
|
18
18
|
def collection
|
19
19
|
@collection ||= SpreeCmCommissioner::PaymentMethods::GroupByBank.new.execute(
|
20
|
-
payment_methods:
|
20
|
+
payment_methods: payment_methods,
|
21
21
|
preferred_payment_method_id: spree_current_user&.preferred_payment_method_id
|
22
22
|
)
|
23
23
|
end
|
@@ -26,6 +26,17 @@ module Spree
|
|
26
26
|
def collection_serializer
|
27
27
|
SpreeCmCommissioner::V2::Storefront::PaymentMethodGroupSerializer
|
28
28
|
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
def payment_methods
|
33
|
+
methods = spree_current_order.available_payment_methods
|
34
|
+
|
35
|
+
return methods.reject(&:mini_app?) if params[:type].blank?
|
36
|
+
|
37
|
+
type = SpreeCmCommissioner::PaymentMethodTypeMapper.call(params[:type])
|
38
|
+
methods.select { |pm| pm.mini_app? && pm.type == type }
|
39
|
+
end
|
29
40
|
end
|
30
41
|
end
|
31
42
|
end
|
@@ -6,6 +6,7 @@ module Spree
|
|
6
6
|
include Spree::Api::V2::Storefront::OrderConcern
|
7
7
|
include Spree::Api::V2::CouponCodesHelper
|
8
8
|
include Spree::Api::V2::Storefront::MetadataControllerConcern
|
9
|
+
include SpreeCmCommissioner::OrderConcern
|
9
10
|
|
10
11
|
around_action :wrap_with_multitenant_without, except: %i[create]
|
11
12
|
|
@@ -138,6 +139,16 @@ module Spree
|
|
138
139
|
end
|
139
140
|
end
|
140
141
|
|
142
|
+
# Restart the checkout flow to bring the order back to the cart view
|
143
|
+
def restart_checkout_flow
|
144
|
+
spree_authorize! :update, spree_current_order, order_token
|
145
|
+
|
146
|
+
spree_current_order.restart_checkout_flow
|
147
|
+
spree_current_order.update_with_updater!
|
148
|
+
|
149
|
+
render_serialized_payload { serialized_current_order }
|
150
|
+
end
|
151
|
+
|
141
152
|
private
|
142
153
|
|
143
154
|
def wrap_with_multitenant_without(&block)
|
@@ -0,0 +1,65 @@
|
|
1
|
+
module Spree
|
2
|
+
module Api
|
3
|
+
module V2
|
4
|
+
module Tenant
|
5
|
+
class OrderHistoriesController < BaseController
|
6
|
+
# GET /api/v2/tenant/order_histories
|
7
|
+
# For user - no params needed
|
8
|
+
# For guest - pass: { "order_tokens[]": [1, 2, 3] }
|
9
|
+
|
10
|
+
around_action :wrap_with_multitenant_without
|
11
|
+
|
12
|
+
def index
|
13
|
+
render_serialized_payload do
|
14
|
+
serialize_collection(paginated_collection)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
# PATCH /api/v2/tenant/order_histories/:id/archive
|
19
|
+
def archive
|
20
|
+
order_token = params[:id]
|
21
|
+
order = Spree::Order.not_archived.find_by!(token: order_token)
|
22
|
+
|
23
|
+
spree_authorize! :update, order, order_token
|
24
|
+
raise CanCan::AccessDenied unless order.payment?
|
25
|
+
|
26
|
+
if order.mark_as_archive
|
27
|
+
render_serialized_payload { serialize_resource(order) }
|
28
|
+
else
|
29
|
+
render_error_payload(order.errors.full_messages.to_sentence)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
private
|
34
|
+
|
35
|
+
def wrap_with_multitenant_without(&block)
|
36
|
+
MultiTenant.without(&block)
|
37
|
+
end
|
38
|
+
|
39
|
+
def collection
|
40
|
+
if spree_current_user.present?
|
41
|
+
spree_current_user.orders.payment.not_archived
|
42
|
+
else
|
43
|
+
order_tokens = Array(params[:order_tokens])
|
44
|
+
return Spree::Order.none if order_tokens.empty?
|
45
|
+
|
46
|
+
Spree::Order.payment.not_archived.without_user.where(token: order_tokens)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def collection_serializer
|
51
|
+
Spree::V2::Tenant::CartSerializer
|
52
|
+
end
|
53
|
+
|
54
|
+
def resource_serializer
|
55
|
+
Spree::V2::Tenant::CartSerializer
|
56
|
+
end
|
57
|
+
|
58
|
+
def model_class
|
59
|
+
Spree::Order
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
@@ -37,7 +37,7 @@ module SpreeCmCommissioner
|
|
37
37
|
bit_fields = SpreeCmCommissioner::KycBitwise::BIT_FIELDS.keys
|
38
38
|
|
39
39
|
if permitted_resource_params[:use_product_kyc] == '1'
|
40
|
-
permitted_resource_params[:kyc] =
|
40
|
+
permitted_resource_params[:kyc] = @product.kyc
|
41
41
|
else
|
42
42
|
@kyc_result = calculate_kyc_value(params[:variant])
|
43
43
|
permitted_resource_params[:kyc] = @kyc_result
|
@@ -0,0 +1,46 @@
|
|
1
|
+
module SpreeCmCommissioner
|
2
|
+
class WellKnownController < ApplicationController
|
3
|
+
before_action :identify_request_source
|
4
|
+
rescue_from StandardError, with: :handle_error
|
5
|
+
|
6
|
+
def show
|
7
|
+
case params[:id]
|
8
|
+
when 'assetlinks.json'
|
9
|
+
render_preference(:preferred_assetlinks)
|
10
|
+
when 'apple-app-site-association'
|
11
|
+
render_preference(:preferred_apple_app_site_association)
|
12
|
+
else
|
13
|
+
render_not_found
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
def identify_request_source
|
20
|
+
host = params[:original_host].presence || request.host.downcase
|
21
|
+
|
22
|
+
result = SpreeCmCommissioner::HostMatcher.call(host: host)
|
23
|
+
|
24
|
+
@store = result.store
|
25
|
+
@tenant = result.tenant
|
26
|
+
end
|
27
|
+
|
28
|
+
def render_preference(preference_key)
|
29
|
+
if @store&.send(preference_key).present?
|
30
|
+
render json: @store.send(preference_key)
|
31
|
+
elsif @tenant&.send(preference_key).present?
|
32
|
+
render json: @tenant.send(preference_key)
|
33
|
+
else
|
34
|
+
render_not_found
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def render_not_found
|
39
|
+
render json: { error: 'Not found' }, status: :not_found
|
40
|
+
end
|
41
|
+
|
42
|
+
def handle_error
|
43
|
+
render json: { error: 'Internal server error' }, status: :internal_server_error
|
44
|
+
end
|
45
|
+
end
|
46
|
+
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, :guest, :show_details_link
|
28
|
+
|
29
|
+
def initialize(title:, order:, guest:, **options)
|
30
|
+
@order = order
|
31
|
+
@vendor = options[:vendor]
|
32
|
+
@guest = guest
|
33
|
+
@show_details_link = options[:show_details_link] || false
|
34
|
+
|
35
|
+
super(title: title, subtitle: options[:subtitle])
|
36
|
+
end
|
37
|
+
|
38
|
+
def selected_line_items
|
39
|
+
return order.line_items.for_vendor(vendor) if vendor.present?
|
40
|
+
|
41
|
+
order.line_items
|
42
|
+
end
|
43
|
+
|
44
|
+
# override
|
45
|
+
def body
|
46
|
+
text = []
|
47
|
+
text << "Order Number:\n<code>#{order.number}</code>\n"
|
48
|
+
text << "\n✅ <b>Ticket Successfully Claimed!</b>\n"
|
49
|
+
text << selected_line_items.map { |item| line_item_content(item) }.compact.join("\n\n")
|
50
|
+
text.compact.join("\n")
|
51
|
+
end
|
52
|
+
|
53
|
+
def line_item_content(line_item)
|
54
|
+
text = []
|
55
|
+
|
56
|
+
text << bold(line_item.product.name.to_s)
|
57
|
+
text << "Quantity: #{line_item.quantity}"
|
58
|
+
text << italic("👉 #{line_item.options_text}") if line_item.options_text.present?
|
59
|
+
text << italic(pretty_date_for(line_item)) if pretty_date_for(line_item).present?
|
60
|
+
text << italic("🏪 #{line_item.vendor.name}") if line_item.vendor&.name.present? && vendor.blank?
|
61
|
+
|
62
|
+
text.compact.join("\n")
|
63
|
+
end
|
64
|
+
|
65
|
+
def pretty_date_for(line_item)
|
66
|
+
return nil unless line_item.date_present?
|
67
|
+
|
68
|
+
from_date = pretty_date(line_item.from_date)
|
69
|
+
to_date = pretty_date(line_item.to_date)
|
70
|
+
|
71
|
+
if from_date == to_date
|
72
|
+
"🗓️ #{from_date}"
|
73
|
+
else
|
74
|
+
"🗓️ #{from_date} -> #{to_date}"
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
# override
|
79
|
+
def footer
|
80
|
+
text = []
|
81
|
+
|
82
|
+
text << bold('🙍 Claimed By')
|
83
|
+
text << "Name: #{guest.first_name} #{guest.last_name}" if guest.first_name.present? || guest.last_name.present?
|
84
|
+
text << "Tel: #{inline_code(guest.intel_phone_number)}" if guest.intel_phone_number.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,17 @@
|
|
1
|
+
module SpreeCmCommissioner
|
2
|
+
module Transit
|
3
|
+
module OrderQueryHelper
|
4
|
+
def self.transit_orders_for_vendor(vendor_id)
|
5
|
+
return Spree::Order.none if vendor_id.nil?
|
6
|
+
|
7
|
+
Spree::Order
|
8
|
+
.includes(:user, :created_by, { payments: :payment_method }, { line_items: { variant: :product } })
|
9
|
+
.joins(line_items: { variant: :product })
|
10
|
+
.where(spree_products: { product_type: :transit })
|
11
|
+
.where(spree_variants: { vendor_id: vendor_id })
|
12
|
+
.distinct
|
13
|
+
.order(created_at: :desc)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
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
|
@@ -9,7 +9,8 @@ module SpreeCmCommissioner
|
|
9
9
|
assign_vendor
|
10
10
|
assign_prototype
|
11
11
|
create_child_taxon
|
12
|
-
|
12
|
+
build_asset
|
13
|
+
create_place
|
13
14
|
end
|
14
15
|
end
|
15
16
|
|
@@ -55,15 +56,39 @@ module SpreeCmCommissioner
|
|
55
56
|
context.fail!(message: child_taxon.errors.full_messages.join(', '))
|
56
57
|
end
|
57
58
|
|
58
|
-
def
|
59
|
-
return if context.params[
|
59
|
+
def asset(banner_type, asset_param, failure_message)
|
60
|
+
return if context.params[asset_param].nil?
|
60
61
|
|
61
|
-
banner =
|
62
|
+
banner = banner_type.create(
|
62
63
|
viewable: @parent_taxon,
|
63
|
-
attachment: context.params[
|
64
|
+
attachment: context.params[asset_param]
|
64
65
|
)
|
65
66
|
|
66
|
-
context.fail!(message:
|
67
|
+
context.fail!(message: failure_message) unless banner.persisted?
|
68
|
+
end
|
69
|
+
|
70
|
+
def build_asset
|
71
|
+
asset(SpreeCmCommissioner::TaxonCategoryIcon, :category_icon, 'Logo upload failed') if context.params[:category_icon].present?
|
72
|
+
asset(SpreeCmCommissioner::TaxonHomeBanner, :home_banner, 'Home banner upload failed') if context.params[:home_banner].present?
|
73
|
+
context.params[:app_banner] = context.params[:home_banner] if context.params[:use_main_photo] == '1'
|
74
|
+
asset(SpreeCmCommissioner::TaxonAppBanner, :app_banner, 'App banner upload failed') if context.params[:app_banner].present?
|
75
|
+
asset(SpreeCmCommissioner::TaxonWebBanner, :web_banner, 'Web banner upload failed') if context.params[:web_banner].present?
|
76
|
+
end
|
77
|
+
|
78
|
+
def create_place
|
79
|
+
return if context.params[:base_64_content].blank?
|
80
|
+
|
81
|
+
place = SpreeCmCommissioner::PlaceDecoder.process_place(context.params[:base_64_content])
|
82
|
+
|
83
|
+
if place.save
|
84
|
+
SpreeCmCommissioner::TaxonPlace.create(
|
85
|
+
place_id: place.id,
|
86
|
+
taxon_id: @parent_taxon.id,
|
87
|
+
description: context.params[:place_description]
|
88
|
+
)
|
89
|
+
else
|
90
|
+
context.fail!(message: place.errors.full_messages.join(', '))
|
91
|
+
end
|
67
92
|
end
|
68
93
|
end
|
69
94
|
end
|
@@ -9,6 +9,8 @@ module SpreeCmCommissioner
|
|
9
9
|
set_option_value
|
10
10
|
create_variant
|
11
11
|
create_stock_item
|
12
|
+
upload_image
|
13
|
+
create_place
|
12
14
|
end
|
13
15
|
end
|
14
16
|
|
@@ -75,6 +77,37 @@ module SpreeCmCommissioner
|
|
75
77
|
context.fail!(message: @stock_item.errors.full_messages.join(', '))
|
76
78
|
end
|
77
79
|
|
80
|
+
def upload_image
|
81
|
+
return if context.params[:ticket_image].blank?
|
82
|
+
|
83
|
+
@image = @ticket.master.images.new(attachment: context.params[:ticket_image])
|
84
|
+
return if @image.save
|
85
|
+
|
86
|
+
context.fail!(message: @image.errors.full_messages.join(', '))
|
87
|
+
end
|
88
|
+
|
89
|
+
def create_place
|
90
|
+
if context.params[:base_64_content].present?
|
91
|
+
place = SpreeCmCommissioner::PlaceDecoder.process_place(context.params[:base_64_content])
|
92
|
+
|
93
|
+
if place.save
|
94
|
+
product_place = SpreeCmCommissioner::ProductPlace.create(
|
95
|
+
place_id: place.id,
|
96
|
+
product_id: @ticket.id
|
97
|
+
)
|
98
|
+
context.fail!(message: product_place.errors.full_messages.join(', ')) unless product_place.persisted?
|
99
|
+
else
|
100
|
+
context.fail!(message: place.errors.full_messages.join(', '))
|
101
|
+
end
|
102
|
+
elsif context.params[:place_id].present?
|
103
|
+
product_place = SpreeCmCommissioner::ProductPlace.create(
|
104
|
+
place_id: context.params[:place_id],
|
105
|
+
product_id: @ticket.id
|
106
|
+
)
|
107
|
+
context.fail!(message: product_place.errors.full_messages.join(', ')) unless product_place.persisted?
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
78
111
|
def ticket_params
|
79
112
|
{
|
80
113
|
name: context.params[:name],
|
@@ -88,7 +121,9 @@ module SpreeCmCommissioner
|
|
88
121
|
vendor_id: context.params[:vendor_id],
|
89
122
|
status: context.params[:status],
|
90
123
|
shipping_category_id: context.params[:shipping_category_id],
|
91
|
-
option_type_ids: context.params[:option_type_ids]
|
124
|
+
option_type_ids: context.params[:option_type_ids],
|
125
|
+
allow_anonymous_booking: context.params[:allow_anonymous_booking],
|
126
|
+
allow_self_check_in: context.params[:allow_self_check_in]
|
92
127
|
}
|
93
128
|
end
|
94
129
|
end
|