spree_cm_commissioner 2.1.9.pre.pre1 → 2.2.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/.env.example +29 -75
- data/.gitignore +3 -0
- data/Gemfile.lock +2 -1
- data/app/controllers/spree/admin/users_controller_decorator.rb +2 -0
- data/app/controllers/spree/api/v2/storefront/account/guest_dynamic_fields_controller.rb +3 -5
- data/app/controllers/spree/api/v2/storefront/account/mark_guest_info_complete_controller.rb +3 -8
- data/app/controllers/spree/api/v2/storefront/guests_controller.rb +37 -18
- data/app/interactors/spree_cm_commissioner/account_recover.rb +2 -2
- data/app/interactors/spree_cm_commissioner/guest_dynamic_field_notification_sender.rb +11 -0
- data/app/interactors/spree_cm_commissioner/notification_reader.rb +3 -1
- data/app/interactors/spree_cm_commissioner/stock/inventory_item_resetter.rb +1 -1
- data/app/interactors/spree_cm_commissioner/team_member_adder.rb +37 -0
- data/app/interactors/spree_cm_commissioner/team_member_creator.rb +58 -0
- data/app/interactors/spree_cm_commissioner/transit/draft_order_creator.rb +4 -0
- data/app/interactors/spree_cm_commissioner/trip_clone_creator.rb +2 -21
- data/app/interactors/spree_cm_commissioner/user_password_authenticator.rb +2 -2
- data/app/interactors/spree_cm_commissioner/user_registration_with_fb_token.rb +1 -1
- data/app/interactors/spree_cm_commissioner/user_registration_with_id_token.rb +1 -1
- data/app/interactors/spree_cm_commissioner/user_telegram_web_app_authenticator.rb +2 -0
- data/app/interactors/spree_cm_commissioner/user_vendor_assigner.rb +39 -0
- data/app/interactors/spree_cm_commissioner/vattanac_bank_initiator.rb +2 -0
- data/app/jobs/spree_cm_commissioner/transit/route_fulfilled_order_count_incrementer_job.rb +10 -0
- data/app/jobs/spree_cm_commissioner/transit/route_order_count_incrementer_job.rb +10 -0
- data/app/jobs/spree_cm_commissioner/transit/route_previous_trip_count_decrementer_job.rb +13 -0
- data/app/jobs/spree_cm_commissioner/transit/route_trip_count_decrementer_job.rb +10 -0
- data/app/jobs/spree_cm_commissioner/transit/route_trip_count_incrementer_job.rb +10 -0
- data/app/models/concerns/spree_cm_commissioner/order_state_machine.rb +12 -0
- data/app/models/concerns/spree_cm_commissioner/route_order_countable.rb +30 -0
- data/app/models/concerns/spree_cm_commissioner/route_trip_count_callbacks.rb +48 -0
- data/app/models/concerns/spree_cm_commissioner/service_type.rb +35 -0
- data/app/models/concerns/spree_cm_commissioner/store_metadata.rb +14 -3
- data/app/models/spree_cm_commissioner/guest.rb +3 -0
- data/app/models/spree_cm_commissioner/inventory_item.rb +1 -1
- data/app/models/spree_cm_commissioner/notification.rb +5 -1
- data/app/models/spree_cm_commissioner/order_decorator.rb +5 -0
- data/app/models/spree_cm_commissioner/redis_stock/cached_inventory_items_builder.rb +2 -2
- data/app/models/spree_cm_commissioner/redis_stock/inventory_updater.rb +2 -2
- data/app/models/spree_cm_commissioner/route.rb +12 -0
- data/app/models/spree_cm_commissioner/trip.rb +40 -0
- data/app/models/spree_cm_commissioner/user_decorator.rb +11 -0
- data/app/models/spree_cm_commissioner/vendor_decorator.rb +1 -0
- data/app/models/spree_cm_commissioner/vendor_route.rb +9 -0
- data/app/notifications/spree_cm_commissioner/guest_dynamic_field_notification.rb +24 -0
- data/app/overrides/spree/admin/users/_form/user_add_on.html.erb.deface +27 -0
- data/app/services/spree_cm_commissioner/transit/base_route_order_metrics_updater.rb +62 -0
- data/app/services/spree_cm_commissioner/transit/route_fulfilled_order_count_incrementer_service.rb +18 -0
- data/app/services/spree_cm_commissioner/transit/route_order_count_incrementer_service.rb +19 -0
- data/app/services/spree_cm_commissioner/transit/route_previous_trip_count_decrementer_service.rb +30 -0
- data/app/services/spree_cm_commissioner/transit/route_trip_count_decrementer_service.rb +33 -0
- data/app/services/spree_cm_commissioner/transit/route_trip_count_incrementer_service.rb +33 -0
- data/app/services/spree_cm_commissioner/users/incomplete_guest_checker_service.rb +34 -0
- data/app/views/blazer/queries/embed/_content.html.erb +4 -2
- data/config/initializers/spree_permitted_attributes.rb +1 -0
- data/config/locales/en.yml +20 -0
- data/config/locales/km.yml +20 -0
- data/db/migrate/20250911042815_create_cm_routes.rb +16 -0
- data/db/migrate/20250911045649_create_cm_vendor_routes.rb +12 -0
- data/db/migrate/20251008064344_add_route_id_to_cm_trips.rb +7 -0
- data/db/migrate/20251009033331_add_registered_by_to_spree_users.rb +6 -0
- data/db/migrate/20251009073040_add_lock_version_to_cm_routes.rb +5 -0
- data/db/migrate/20251009073929_add_lock_version_to_cm_vendor_routes.rb +5 -0
- data/lib/spree_cm_commissioner/engine.rb +4 -0
- data/lib/spree_cm_commissioner/test_helper/factories/route_factory.rb +10 -0
- data/lib/spree_cm_commissioner/test_helper/factories/trip_factory.rb +1 -0
- data/lib/spree_cm_commissioner/test_helper/factories/vendor_route_factory.rb +7 -0
- data/lib/spree_cm_commissioner/version.rb +1 -1
- data/lib/spree_cm_commissioner.rb +13 -34
- data/lib/tasks/backfill_confirmed_at.rake +21 -0
- data/spree_cm_commissioner.gemspec +1 -0
- metadata +50 -4
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 03b6ceb6f610d931285c1edb4bf699bb82098cb042c7a675a7cf4ca97d20c2d1
|
|
4
|
+
data.tar.gz: 7e4a0b523320e28f397556545a5c912a3efc9418c993a3dcc06c403a6d1b64b0
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 0a01870d81ac4d66b2c931b49552891ca2167257d0ae83956b7748af60d6c17b17bacd6d444a32b87b12d1db722451e3fc3c374eb108f45dc454ab3648f57b7a
|
|
7
|
+
data.tar.gz: 11efa1fc32c865d667bd37e2753b79d6971b923c4fc0ffa9e463c7b17a0e3ccf5cfb211b84aa97fe4d8554ff4542ec1cc36483c45ca578ef57e5ba7e863c73a8
|
data/.env.example
CHANGED
|
@@ -1,75 +1,29 @@
|
|
|
1
|
-
#
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
ASSETS_SYNC_CF_DIST_ID=E3DV5NICAX5NCH # CloudFront distribution ID for asset synchronization
|
|
31
|
-
AWS_CF_MEDIA_DOMAIN=medias.bookme.plus # CloudFront media domain (e.g., medias.bookme.plus)
|
|
32
|
-
AWS_CF_PUBLIC_KEY_ID= # CloudFront public key ID for signed URLs
|
|
33
|
-
AWS_CF_PRIVATE_KEY= # CloudFront private key for signed URLs (PEM format)
|
|
34
|
-
|
|
35
|
-
# Cache Configuration
|
|
36
|
-
CONTENT_CACHE_MAX_AGE=180 # Maximum age for CDN content cache in seconds (default: 86400)
|
|
37
|
-
|
|
38
|
-
# Email Configuration
|
|
39
|
-
NO_REPLY_EMAIL=noreply@example.com # No-reply email address for outgoing emails
|
|
40
|
-
|
|
41
|
-
# SMS Configuration
|
|
42
|
-
SMS_SENDER_ID=SMS Info # Sender ID for SMS messages (default: 'SMS Info')
|
|
43
|
-
|
|
44
|
-
# Payment Gateway Configuration
|
|
45
|
-
VATTANAC_AES_SECRET_KEY= # Vattanac Bank AES secret key for encryption
|
|
46
|
-
BOOKMEPLUS_PRIVATE_KEY= # BookMe+ private key for Vattanac Bank integration
|
|
47
|
-
VATTANAC_PUBLIC_KEY= # Vattanac Bank public key for signature verification
|
|
48
|
-
|
|
49
|
-
# Google Services Configuration
|
|
50
|
-
GOOGLE_MAP_KEY=AIzaSyBt-OSnDZze6hxGjfiapSxpcyGzBo_COv8 # Google Maps API key for nearby places and location services
|
|
51
|
-
ISSUER_ID=3388000000022336356 # Google Wallet issuer ID for digital passes
|
|
52
|
-
|
|
53
|
-
# Waiting Room System Configuration
|
|
54
|
-
WAITING_ROOM_DISABLED=no # Disable waiting room functionality (set to 'yes' to disable)
|
|
55
|
-
WAITING_ROOM_SESSION_SIGNATURE=4234f0a3-c42f-40b5-9057-7c006793cea4 # JWT signature key for waiting room session tokens
|
|
56
|
-
WAITING_ROOM_SESSION_EXPIRE_DURATION_IN_SECOND=180 # Session expiration duration in seconds (default: 180 / 3 minutes)
|
|
57
|
-
WAITING_ROOM_MIN_SESSIONS_COUNT=5 # Minimum sessions count for waiting room calculation (default: 5)
|
|
58
|
-
WAITING_ROOM_SERVERS_COUNT=2 # Number of running servers for capacity calculation (default: 2)
|
|
59
|
-
WAITING_ROOM_MAX_THREAD_COUNT=10 # Maximum thread count per server (default: 10)
|
|
60
|
-
WAITING_ROOM_MULTIPLIER=150 # Multiplier for waiting room capacity calculation (default: 150)
|
|
61
|
-
|
|
62
|
-
# Exception Notification Configuration
|
|
63
|
-
EXCEPTION_NOTIFY_ENABLE=yes # Enable exception notifications (set to 'yes' to enable)
|
|
64
|
-
EXCEPTION_TELEGRAM_BOT_TOKEN=6441690414:AAFBpevRdBaRTXmalJR2vcSdPNzYoDnMEFk # Telegram bot token for exception notifications
|
|
65
|
-
EXCEPTION_NOTIFIER_TELEGRAM_CHANNEL_ID=-1001807686211 # Telegram channel ID for exception notifications
|
|
66
|
-
|
|
67
|
-
# Telegram Bot Configuration
|
|
68
|
-
DEFAULT_TELEGRAM_BOT_API_TOKEN=6441690414:AAFBpevRdBaRTXmalJR2vcSdPNzYoDnMEFk # Default Telegram bot API token
|
|
69
|
-
PIN_CODE_DEBUG_NOTIFIY_TELEGRAM_ENABLE=yes # Enable PIN code debug notifications via Telegram (set to 'yes' to enable)
|
|
70
|
-
|
|
71
|
-
# Business Rules Configuration
|
|
72
|
-
ACCOMMODATION_MAX_STAY_DAYS=10 # Maximum number of days allowed for accommodation stays (default: 10)
|
|
73
|
-
|
|
74
|
-
# Development/Testing Configuration
|
|
75
|
-
BUNDLE_GEMFILE= # Gemfile location for bundler
|
|
1
|
+
# aws
|
|
2
|
+
AWS_ACCESS_KEY_ID=""
|
|
3
|
+
AWS_BUCKET_NAME=""
|
|
4
|
+
AWS_REGION=""
|
|
5
|
+
AWS_SECRET_ACCESS_KEY=
|
|
6
|
+
AWS_CLUSTER_NAME="" # fetch all tasks
|
|
7
|
+
|
|
8
|
+
AWS_CF_MEDIA_DOMAIN="medias.bookme.plus"
|
|
9
|
+
AWS_CF_PUBLIC_KEY_ID="KKC****QFJ2"
|
|
10
|
+
AWS_OUTPUT_BUCKET_NAME="output-production-cm"
|
|
11
|
+
|
|
12
|
+
AWS_CF_PRIVATE_KEY="-----BEGIN PRIVATE KEY-----
|
|
13
|
+
-----END PRIVATE KEY-----"
|
|
14
|
+
|
|
15
|
+
# for GET request with following host, it will be cached.
|
|
16
|
+
CONTENT_HOST_URL=https://content.bookme.plus
|
|
17
|
+
CONTENT_CACHE_MAX_AGE=7200
|
|
18
|
+
|
|
19
|
+
WAITING_ROOM_SESSION_SIGNATURE="e6b2********************26e3"
|
|
20
|
+
WAITING_ROOM_SESSION_EXPIRE_DURATION_IN_SECOND=
|
|
21
|
+
WAITING_ROOM_MIN_SESSIONS_COUNT=5
|
|
22
|
+
WAITING_ROOM_DISABLED=no
|
|
23
|
+
|
|
24
|
+
# Vattanac Bank
|
|
25
|
+
VATTANAC_AES_SECRET_KEY= ""
|
|
26
|
+
VATTANAC_PUBLIC_KEY=""
|
|
27
|
+
|
|
28
|
+
# Organizer URL
|
|
29
|
+
ORGANIZER_URL=http://127.0.0.1:4000/organizer
|
data/.gitignore
CHANGED
data/Gemfile.lock
CHANGED
|
@@ -34,7 +34,7 @@ GIT
|
|
|
34
34
|
PATH
|
|
35
35
|
remote: .
|
|
36
36
|
specs:
|
|
37
|
-
spree_cm_commissioner (2.
|
|
37
|
+
spree_cm_commissioner (2.2.0)
|
|
38
38
|
activerecord-multi-tenant
|
|
39
39
|
activerecord_json_validator (~> 2.1, >= 2.1.3)
|
|
40
40
|
aws-sdk-cloudfront
|
|
@@ -69,6 +69,7 @@ PATH
|
|
|
69
69
|
spree_api_v1 (>= 4.5.0)
|
|
70
70
|
spree_auth_devise (>= 4.5.0)
|
|
71
71
|
spree_backend (>= 4.5.0)
|
|
72
|
+
spree_emails (>= 4.5.0)
|
|
72
73
|
spree_extension
|
|
73
74
|
spree_multi_vendor (>= 2.4.1)
|
|
74
75
|
spree_vpago
|
|
@@ -9,6 +9,8 @@ module Spree
|
|
|
9
9
|
def create
|
|
10
10
|
@user = Spree.user_class.new(user_params)
|
|
11
11
|
@user.assigned_roles = Spree::Role.where(id: params.dig(:user, :spree_role_ids)).pluck(:name) if params.dig(:user, :spree_role_ids)
|
|
12
|
+
@user.confirmed_at = Time.zone.now
|
|
13
|
+
@user.registered_by = :system_registered
|
|
12
14
|
|
|
13
15
|
if @user.save
|
|
14
16
|
flash[:success] = flash_message_for(@user, :successfully_created)
|
|
@@ -22,7 +22,7 @@ module Spree
|
|
|
22
22
|
|
|
23
23
|
ActiveRecord::Base.transaction do
|
|
24
24
|
fields.each do |field|
|
|
25
|
-
process_dynamic_field(field
|
|
25
|
+
process_dynamic_field(field)
|
|
26
26
|
end
|
|
27
27
|
|
|
28
28
|
@guest.save_and_move_to_next_stage
|
|
@@ -52,11 +52,9 @@ module Spree
|
|
|
52
52
|
end
|
|
53
53
|
end
|
|
54
54
|
|
|
55
|
-
def process_dynamic_field(field
|
|
55
|
+
def process_dynamic_field(field)
|
|
56
56
|
dynamic_field = SpreeCmCommissioner::DynamicField.find(field[:id])
|
|
57
|
-
guest_field = @guest.guest_dynamic_fields.
|
|
58
|
-
|
|
59
|
-
return if guest_field.new_record? && dynamic_field.data_fill_stage != phase
|
|
57
|
+
guest_field = @guest.guest_dynamic_fields.build(dynamic_field_id: dynamic_field.id)
|
|
60
58
|
|
|
61
59
|
if dynamic_field.requires_dynamic_field_options?
|
|
62
60
|
option = dynamic_field.dynamic_field_options.find_by(value: field[:value])
|
|
@@ -7,18 +7,13 @@ module Spree
|
|
|
7
7
|
before_action :require_spree_current_user
|
|
8
8
|
|
|
9
9
|
def update
|
|
10
|
-
|
|
11
|
-
|
|
10
|
+
SpreeCmCommissioner::Users::IncompleteGuestCheckerService.new(spree_current_user).call
|
|
11
|
+
render_success
|
|
12
12
|
end
|
|
13
13
|
|
|
14
14
|
private
|
|
15
15
|
|
|
16
|
-
def
|
|
17
|
-
spree_current_user.public_metadata['has_incomplete_guest_info'] = false
|
|
18
|
-
spree_current_user.save!
|
|
19
|
-
end
|
|
20
|
-
|
|
21
|
-
def render_success_response
|
|
16
|
+
def render_success
|
|
22
17
|
render_serialized_payload(200) do
|
|
23
18
|
{
|
|
24
19
|
success: true,
|
|
@@ -5,8 +5,8 @@ module Spree
|
|
|
5
5
|
class GuestsController < ::Spree::Api::V2::ResourceController
|
|
6
6
|
include OrderConcern
|
|
7
7
|
|
|
8
|
-
# raise 404 when no order
|
|
9
|
-
before_action :ensure_order
|
|
8
|
+
# raise 404 when no order, except for show
|
|
9
|
+
before_action :ensure_order, except: [:show]
|
|
10
10
|
|
|
11
11
|
# override
|
|
12
12
|
def model_class
|
|
@@ -23,6 +23,11 @@ module Spree
|
|
|
23
23
|
SpreeCmCommissioner::V2::Storefront::GuestSerializer
|
|
24
24
|
end
|
|
25
25
|
|
|
26
|
+
def show
|
|
27
|
+
@guest = SpreeCmCommissioner::Guest.find(params[:id])
|
|
28
|
+
render_serialized_payload { serialize_resource(@guest) }
|
|
29
|
+
end
|
|
30
|
+
|
|
26
31
|
def create
|
|
27
32
|
spree_authorize! :update, spree_current_order, order_token
|
|
28
33
|
|
|
@@ -90,22 +95,15 @@ module Spree
|
|
|
90
95
|
end
|
|
91
96
|
|
|
92
97
|
def process_dynamic_fields(dynamic_fields_attributes)
|
|
93
|
-
dynamic_fields_attributes.each do |
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
if field
|
|
100
|
-
field.assign_attributes(attr.except(:id, :_destroy))
|
|
101
|
-
associate_dynamic_field_option(field) if field.dynamic_field.present?
|
|
102
|
-
field.save!
|
|
103
|
-
end
|
|
104
|
-
else
|
|
105
|
-
field = resource.guest_dynamic_fields.build(attr.except(:id, :_destroy))
|
|
106
|
-
associate_dynamic_field_option(field) if field.dynamic_field.present?
|
|
107
|
-
field.save!
|
|
98
|
+
dynamic_fields_attributes.each do |raw_attributes|
|
|
99
|
+
attributes = raw_attributes.to_h.symbolize_keys
|
|
100
|
+
|
|
101
|
+
if ActiveModel::Type::Boolean.new.cast(attributes[:_destroy])
|
|
102
|
+
destroy_guest_dynamic_field(attributes[:id])
|
|
103
|
+
next
|
|
108
104
|
end
|
|
105
|
+
|
|
106
|
+
upsert_guest_dynamic_field(attributes)
|
|
109
107
|
end
|
|
110
108
|
end
|
|
111
109
|
|
|
@@ -113,7 +111,28 @@ module Spree
|
|
|
113
111
|
return unless field.dynamic_field&.requires_dynamic_field_options?
|
|
114
112
|
|
|
115
113
|
option = field.dynamic_field.dynamic_field_options.find_by(id: field.value)
|
|
116
|
-
field.dynamic_field_option = option
|
|
114
|
+
field.dynamic_field_option = option
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
def destroy_guest_dynamic_field(id)
|
|
118
|
+
return if id.blank?
|
|
119
|
+
|
|
120
|
+
resource.guest_dynamic_fields.find(id).destroy!
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
def upsert_guest_dynamic_field(attributes)
|
|
124
|
+
field = find_or_initialize_guest_dynamic_field(attributes)
|
|
125
|
+
field.assign_attributes(attributes.except(:id, :_destroy))
|
|
126
|
+
associate_dynamic_field_option(field) if field.dynamic_field.present?
|
|
127
|
+
field.save!
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
def find_or_initialize_guest_dynamic_field(attributes)
|
|
131
|
+
if attributes[:id].present?
|
|
132
|
+
resource.guest_dynamic_fields.find(attributes[:id])
|
|
133
|
+
else
|
|
134
|
+
resource.guest_dynamic_fields.find_or_initialize_by(dynamic_field_id: attributes[:dynamic_field_id])
|
|
135
|
+
end
|
|
117
136
|
end
|
|
118
137
|
end
|
|
119
138
|
end
|
|
@@ -8,8 +8,8 @@ module SpreeCmCommissioner
|
|
|
8
8
|
end
|
|
9
9
|
|
|
10
10
|
def recover_user
|
|
11
|
-
updated = context.user.update(account_deletion_at: nil, account_restored_at: Time.current)
|
|
12
|
-
context.fail!(message: user.errors.full_messages.to_sentence) unless updated
|
|
11
|
+
updated = context.user.update(account_deletion_at: nil, account_restored_at: Time.current, confirmed_at: Time.current)
|
|
12
|
+
context.fail!(message: context.user.errors.full_messages.to_sentence) unless updated
|
|
13
13
|
end
|
|
14
14
|
|
|
15
15
|
def validate_user
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
module SpreeCmCommissioner
|
|
2
|
+
class GuestDynamicFieldNotificationSender < BaseInteractor
|
|
3
|
+
def call
|
|
4
|
+
notification = SpreeCmCommissioner::GuestDynamicFieldNotification.with(
|
|
5
|
+
guest: context.guest
|
|
6
|
+
).deliver_later(context.guest.user)
|
|
7
|
+
|
|
8
|
+
context.notification = notification
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
end
|
|
@@ -15,7 +15,9 @@ module SpreeCmCommissioner
|
|
|
15
15
|
end
|
|
16
16
|
|
|
17
17
|
def read_all_user_unread_notifications
|
|
18
|
-
|
|
18
|
+
# mark all unread notifications accept type 'guest_dynamic_field_notification'
|
|
19
|
+
# due to it requires user to fill info before mark as read
|
|
20
|
+
user.notifications.markable_notifications.mark_as_read!
|
|
19
21
|
end
|
|
20
22
|
end
|
|
21
23
|
end
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
module SpreeCmCommissioner
|
|
2
|
+
class TeamMemberAdder < BaseInteractor
|
|
3
|
+
delegate :user_id, :role_ids, :branch_ids, :vendor, :inviter, :service_type, to: :context
|
|
4
|
+
|
|
5
|
+
def call
|
|
6
|
+
find_user
|
|
7
|
+
assign_user_to_vendor
|
|
8
|
+
set_success_message
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
private
|
|
12
|
+
|
|
13
|
+
def find_user
|
|
14
|
+
context.user = Spree::User.find_by(id: user_id)
|
|
15
|
+
|
|
16
|
+
return if context.user
|
|
17
|
+
|
|
18
|
+
context.fail!(
|
|
19
|
+
message: I18n.t('views.manage_team.add.user_not_found')
|
|
20
|
+
)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def assign_user_to_vendor
|
|
24
|
+
SpreeCmCommissioner::UserVendorAssigner.call(
|
|
25
|
+
user: context.user,
|
|
26
|
+
role_ids: role_ids,
|
|
27
|
+
branch_ids: branch_ids,
|
|
28
|
+
vendor: vendor,
|
|
29
|
+
service_type: service_type
|
|
30
|
+
)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def set_success_message
|
|
34
|
+
context.success_message = I18n.t('views.manage_team.add.user_assigned_successfully')
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
module SpreeCmCommissioner
|
|
2
|
+
class TeamMemberCreator < BaseInteractor
|
|
3
|
+
delegate :email, :first_name, :last_name, :password, :role_ids, :branch_ids, :vendor, :inviter, :service_type, to: :context
|
|
4
|
+
|
|
5
|
+
def call
|
|
6
|
+
create_user
|
|
7
|
+
assign_user_to_vendor
|
|
8
|
+
set_success_message
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
private
|
|
12
|
+
|
|
13
|
+
def create_user
|
|
14
|
+
existing_user = Spree::User.find_by(email: normalized_email)
|
|
15
|
+
if existing_user.present?
|
|
16
|
+
context.fail!(
|
|
17
|
+
message: I18n.t('views.manage_team.create.user_already_exists'),
|
|
18
|
+
user: existing_user
|
|
19
|
+
)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
context.user = Spree::User.new(
|
|
23
|
+
email: normalized_email,
|
|
24
|
+
first_name: first_name,
|
|
25
|
+
last_name: last_name,
|
|
26
|
+
password: password,
|
|
27
|
+
password_confirmation: password,
|
|
28
|
+
registered_by: :system_registered,
|
|
29
|
+
primary_service_type: service_type
|
|
30
|
+
)
|
|
31
|
+
|
|
32
|
+
return if context.user.save
|
|
33
|
+
|
|
34
|
+
context.fail!(
|
|
35
|
+
message: context.user.errors.full_messages.to_sentence,
|
|
36
|
+
user: context.user
|
|
37
|
+
)
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def assign_user_to_vendor
|
|
41
|
+
SpreeCmCommissioner::UserVendorAssigner.call(
|
|
42
|
+
user: context.user,
|
|
43
|
+
role_ids: role_ids,
|
|
44
|
+
branch_ids: branch_ids,
|
|
45
|
+
vendor: vendor,
|
|
46
|
+
service_type: service_type
|
|
47
|
+
)
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def set_success_message
|
|
51
|
+
context.success_message = I18n.t('views.manage_team.create.success')
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def normalized_email
|
|
55
|
+
@normalized_email ||= email&.strip&.downcase
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
end
|
|
@@ -40,6 +40,10 @@ module SpreeCmCommissioner
|
|
|
40
40
|
inbound_qty = inbound_line_items.sum(&:quantity)
|
|
41
41
|
|
|
42
42
|
raise StandardError, 'Outbound & inbound line item quantities do not match' if inbound_line_items.any? && outbound_qty != inbound_qty
|
|
43
|
+
|
|
44
|
+
trip_ids = (outbound_legs.map(&:trip_id) + inbound_legs.map(&:trip_id)).uniq
|
|
45
|
+
order.preload_trip_ids = trip_ids
|
|
46
|
+
|
|
43
47
|
raise StandardError, order.errors.full_messages.to_sentence unless order.save
|
|
44
48
|
|
|
45
49
|
order.update_with_updater!
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
# TODO: fix this to remove variant block related code as we already drop the table.
|
|
2
1
|
module SpreeCmCommissioner
|
|
3
2
|
class TripCloneCreator < BaseInteractor
|
|
4
3
|
delegate :vendor, :params, :original_trip, :places, :current_store, :current_vendor, to: :context
|
|
@@ -26,6 +25,7 @@ module SpreeCmCommissioner
|
|
|
26
25
|
return nil unless original_product
|
|
27
26
|
|
|
28
27
|
cloned_product = duplicate_product(original_product)
|
|
28
|
+
cloned_product.short_name = "Copy of #{original_product.short_name}"
|
|
29
29
|
assign_vendor_attributes(cloned_product)
|
|
30
30
|
|
|
31
31
|
cloned_product.save!
|
|
@@ -110,35 +110,16 @@ module SpreeCmCommissioner
|
|
|
110
110
|
# Clone Variants
|
|
111
111
|
def clone_variants(original_trip, cloned_trip)
|
|
112
112
|
original_trip.product.variants.each do |variant|
|
|
113
|
-
|
|
113
|
+
cloned_trip.product.variants.create!(
|
|
114
114
|
price: variant.price,
|
|
115
115
|
option_value_ids: variant.option_value_ids,
|
|
116
116
|
sku: ''
|
|
117
117
|
)
|
|
118
|
-
clone_variant_blocks(variant, new_variant)
|
|
119
118
|
end
|
|
120
119
|
rescue StandardError => e
|
|
121
120
|
raise StandardError, "Failed to clone variants: #{e.message}"
|
|
122
121
|
end
|
|
123
122
|
|
|
124
|
-
# clone variant_block (seat)
|
|
125
|
-
def clone_variant_blocks(origin_variant, new_variant)
|
|
126
|
-
block_data = {
|
|
127
|
-
block_ids: origin_variant.block_ids || []
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
context = SpreeCmCommissioner::VariantBlockUpdater.call(
|
|
131
|
-
variant: new_variant,
|
|
132
|
-
current_store: current_store,
|
|
133
|
-
data: block_data,
|
|
134
|
-
stock_location: current_vendor.stock_locations.first
|
|
135
|
-
)
|
|
136
|
-
|
|
137
|
-
raise StandardError, "Failed to update variant blocks: #{context.message}" unless context.success?
|
|
138
|
-
rescue StandardError => e
|
|
139
|
-
raise StandardError, "Failed to clone variant blocks: #{e.message}"
|
|
140
|
-
end
|
|
141
|
-
|
|
142
123
|
# Helpers
|
|
143
124
|
def departure_time_from_stops(trip)
|
|
144
125
|
first_departure = trip.trip_stops.first&.departure_time
|
|
@@ -6,7 +6,7 @@ module SpreeCmCommissioner
|
|
|
6
6
|
context.user = Spree.user_class.find_user_by_login(login, tenant_id)
|
|
7
7
|
context.fail!(message: I18n.t('authenticator.incorrect_login')) if context.user.nil?
|
|
8
8
|
|
|
9
|
-
if spree_confirmable? && active_for_authentication? && !validate_password(user)
|
|
9
|
+
if spree_confirmable? && active_for_authentication? && !validate_password(context.user)
|
|
10
10
|
context.fail!(message: I18n.t('authenticator.incorrect_password'))
|
|
11
11
|
end
|
|
12
12
|
|
|
@@ -25,7 +25,7 @@ module SpreeCmCommissioner
|
|
|
25
25
|
end
|
|
26
26
|
|
|
27
27
|
def active_for_authentication?
|
|
28
|
-
user.active_for_authentication?
|
|
28
|
+
context.user.active_for_authentication?
|
|
29
29
|
end
|
|
30
30
|
end
|
|
31
31
|
end
|
|
@@ -24,7 +24,7 @@ module SpreeCmCommissioner
|
|
|
24
24
|
# Flag as social network registration to skip presence validation for email, login, phone_number, and user_identity_providers
|
|
25
25
|
# Other validations (uniqueness, format) still run if present
|
|
26
26
|
user.registering_via_social_network = true
|
|
27
|
-
|
|
27
|
+
user.confirmed_at = Time.zone.now
|
|
28
28
|
if user.save
|
|
29
29
|
context.user = user
|
|
30
30
|
else
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
module SpreeCmCommissioner
|
|
2
|
+
class UserVendorAssigner < BaseInteractor
|
|
3
|
+
delegate :user, :role_ids, :branch_ids, :vendor, :service_type, to: :context
|
|
4
|
+
|
|
5
|
+
def call
|
|
6
|
+
assign_roles_to_user
|
|
7
|
+
assign_branches_to_user if should_assign_branches?
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
private
|
|
11
|
+
|
|
12
|
+
def assign_roles_to_user
|
|
13
|
+
SpreeCmCommissioner::UserRolesAssigner.create(
|
|
14
|
+
user_id: user.id,
|
|
15
|
+
role_ids: role_ids,
|
|
16
|
+
vendor_id: vendor.id
|
|
17
|
+
)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def should_assign_branches?
|
|
21
|
+
(service_type == 'transit' || service_type == 'intercity_taxi') && branch_ids.present?
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def assign_branches_to_user
|
|
25
|
+
cleaned_ids = Array(branch_ids).compact_blank.map(&:to_i)
|
|
26
|
+
|
|
27
|
+
return unless cleaned_ids.any?
|
|
28
|
+
|
|
29
|
+
valid_branch_ids = SpreeCmCommissioner::VendorPlace
|
|
30
|
+
.where(id: cleaned_ids, vendor_id: vendor.id, place_type: :branch)
|
|
31
|
+
.pluck(:id)
|
|
32
|
+
|
|
33
|
+
return unless valid_branch_ids.any?
|
|
34
|
+
|
|
35
|
+
user.branch_ids = valid_branch_ids
|
|
36
|
+
user.save
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
module SpreeCmCommissioner
|
|
2
|
+
module Transit
|
|
3
|
+
class RouteFulfilledOrderCountIncrementerJob < ApplicationUniqueJob
|
|
4
|
+
def perform(order_id:)
|
|
5
|
+
order = Spree::Order.find(order_id)
|
|
6
|
+
SpreeCmCommissioner::Transit::RouteFulfilledOrderCountIncrementerService.call(order: order)
|
|
7
|
+
end
|
|
8
|
+
end
|
|
9
|
+
end
|
|
10
|
+
end
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
module SpreeCmCommissioner
|
|
2
|
+
module Transit
|
|
3
|
+
class RouteOrderCountIncrementerJob < ApplicationUniqueJob
|
|
4
|
+
def perform(order_id:)
|
|
5
|
+
order = Spree::Order.find(order_id)
|
|
6
|
+
SpreeCmCommissioner::Transit::RouteOrderCountIncrementerService.call(order: order)
|
|
7
|
+
end
|
|
8
|
+
end
|
|
9
|
+
end
|
|
10
|
+
end
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# Perform the previous-route decrement outside the Trip transaction.
|
|
2
|
+
|
|
3
|
+
module SpreeCmCommissioner
|
|
4
|
+
module Transit
|
|
5
|
+
class RoutePreviousTripCountDecrementerJob < ApplicationUniqueJob
|
|
6
|
+
queue_as :default
|
|
7
|
+
|
|
8
|
+
def perform(previous_route_id:)
|
|
9
|
+
SpreeCmCommissioner::Transit::RoutePreviousTripCountDecrementerService.call(previous_route_id: previous_route_id)
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
end
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
module SpreeCmCommissioner
|
|
2
|
+
module Transit
|
|
3
|
+
class RouteTripCountDecrementerJob < ApplicationUniqueJob
|
|
4
|
+
def perform(trip_id:)
|
|
5
|
+
trip = SpreeCmCommissioner::Trip.find(trip_id)
|
|
6
|
+
SpreeCmCommissioner::Transit::RouteTripCountDecrementerService.call(trip: trip)
|
|
7
|
+
end
|
|
8
|
+
end
|
|
9
|
+
end
|
|
10
|
+
end
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
module SpreeCmCommissioner
|
|
2
|
+
module Transit
|
|
3
|
+
class RouteTripCountIncrementerJob < ApplicationUniqueJob
|
|
4
|
+
def perform(trip_id:)
|
|
5
|
+
trip = SpreeCmCommissioner::Trip.find(trip_id)
|
|
6
|
+
SpreeCmCommissioner::Transit::RouteTripCountIncrementerService.call(trip: trip)
|
|
7
|
+
end
|
|
8
|
+
end
|
|
9
|
+
end
|
|
10
|
+
end
|