spree_cm_commissioner 2.5.0.pre.pre7 → 2.5.0.pre.pre9

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.
Files changed (70) hide show
  1. checksums.yaml +4 -4
  2. data/.bundle/config +3 -2
  3. data/.github/workflows/test_and_build_gem.yml +123 -57
  4. data/Gemfile.lock +1 -1
  5. data/Rakefile +55 -29
  6. data/app/controllers/spree/admin/base_controller_decorator.rb +3 -3
  7. data/app/controllers/spree/admin/base_import_orders_controller.rb +6 -1
  8. data/app/controllers/spree/admin/classifications_controller.rb +1 -1
  9. data/app/controllers/spree/admin/notification_sender_controller.rb +1 -1
  10. data/app/controllers/spree/api/v2/storefront/popular_route_places_controller.rb +7 -1
  11. data/app/controllers/spree/api/v2/storefront/queue_cart/line_items_controller.rb +6 -6
  12. data/app/controllers/spree/api/v2/storefront/route_places_controller.rb +9 -9
  13. data/app/finders/spree_cm_commissioner/places/find_with_route.rb +10 -10
  14. data/app/finders/spree_cm_commissioner/routes/find_popular.rb +10 -14
  15. data/app/interactors/spree_cm_commissioner/create_event.rb +1 -1
  16. data/app/interactors/spree_cm_commissioner/customer_notification_cron_executor.rb +1 -1
  17. data/app/interactors/spree_cm_commissioner/stock/stock_movement_creator.rb +3 -2
  18. data/app/jobs/spree_cm_commissioner/conversion_pre_calculator_job.rb +2 -2
  19. data/app/jobs/spree_cm_commissioner/customer_notification_sender_job.rb +3 -3
  20. data/app/jobs/spree_cm_commissioner/enqueue_cart/add_item_job.rb +7 -7
  21. data/app/jobs/spree_cm_commissioner/ensure_event_for_product_line_item_guests_job.rb +1 -1
  22. data/app/jobs/spree_cm_commissioner/event_line_items_date_syncer_job.rb +2 -2
  23. data/app/jobs/spree_cm_commissioner/export_csv_job.rb +2 -2
  24. data/app/jobs/spree_cm_commissioner/import_order_job.rb +5 -5
  25. data/app/jobs/spree_cm_commissioner/invalidate_cache_request_job.rb +2 -2
  26. data/app/jobs/spree_cm_commissioner/inventory_item_syncer_job.rb +8 -2
  27. data/app/jobs/spree_cm_commissioner/option_type_variants_public_metadata_updater_job.rb +7 -3
  28. data/app/jobs/spree_cm_commissioner/option_value_variants_public_metadata_updater_job.rb +6 -2
  29. data/app/jobs/spree_cm_commissioner/order_complete_telegram_sender_job.rb +2 -2
  30. data/app/jobs/spree_cm_commissioner/product_event_id_to_children_syncer_job.rb +2 -2
  31. data/app/jobs/spree_cm_commissioner/reports_assigner_job.rb +2 -2
  32. data/app/jobs/spree_cm_commissioner/sms_pin_code_job.rb +1 -1
  33. data/app/jobs/spree_cm_commissioner/state_job.rb +2 -2
  34. data/app/jobs/spree_cm_commissioner/stock/inventory_items_adjuster_job.rb +4 -1
  35. data/app/jobs/spree_cm_commissioner/stock/inventory_items_generator_job.rb +2 -2
  36. data/app/jobs/spree_cm_commissioner/transit/route_fulfilled_order_count_incrementer_job.rb +2 -2
  37. data/app/jobs/spree_cm_commissioner/transit/route_order_count_incrementer_job.rb +2 -2
  38. data/app/jobs/spree_cm_commissioner/transit/route_previous_trip_count_decrementer_job.rb +2 -2
  39. data/app/jobs/spree_cm_commissioner/transit/route_trip_count_decrementer_job.rb +2 -2
  40. data/app/jobs/spree_cm_commissioner/transit/route_trip_count_incrementer_job.rb +2 -2
  41. data/app/jobs/spree_cm_commissioner/vendor_creation_telegram_alert_sender_job.rb +2 -2
  42. data/app/jobs/spree_cm_commissioner/vendor_job.rb +2 -2
  43. data/app/jobs/spree_cm_commissioner/waiting_room_session_firebase_logger_job.rb +1 -1
  44. data/app/models/concerns/spree_cm_commissioner/option_type_attr_type.rb +1 -1
  45. data/app/models/concerns/spree_cm_commissioner/option_value_attr_type.rb +1 -1
  46. data/app/models/concerns/spree_cm_commissioner/order_state_machine.rb +2 -2
  47. data/app/models/concerns/spree_cm_commissioner/tenant_preference.rb +3 -0
  48. data/app/models/spree_cm_commissioner/export.rb +1 -1
  49. data/app/models/spree_cm_commissioner/product_decorator.rb +1 -1
  50. data/app/models/spree_cm_commissioner/redis_stock/inventory_updater.rb +4 -1
  51. data/app/models/spree_cm_commissioner/stock_item_decorator.rb +4 -4
  52. data/app/models/spree_cm_commissioner/taxon_decorator.rb +1 -1
  53. data/app/models/spree_cm_commissioner/vendor_decorator.rb +2 -2
  54. data/app/request_schemas/spree_cm_commissioner/popular_route_places_request_schema.rb +12 -0
  55. data/app/request_schemas/spree_cm_commissioner/route_places_request_schema.rb +5 -0
  56. data/app/services/spree_cm_commissioner/integrations/stadium_x_v1/inventory/unstock_inventory.rb +1 -1
  57. data/app/views/spree/admin/tenants/_form.html.erb +18 -0
  58. data/app/views/spree/admin/tenants/form/_footer.html.erb +31 -0
  59. data/app/views/spree/admin/tenants/form/_social.html.erb +31 -0
  60. data/app/views/spree/order_mailer/confirm_email.html.erb +1 -1
  61. data/app/views/spree_cm_commissioner/layouts/order_mailer.html.erb +1 -1
  62. data/app/views/spree_cm_commissioner/order_mailer/tenant/_footer.html.erb +13 -6
  63. data/app/views/spree_cm_commissioner/order_mailer/tenant/_support_contact.html.erb +23 -24
  64. data/bin/run_spec_group +101 -0
  65. data/db/migrate/20251209022924_add_contact_fields_to_cm_tenants.rb +9 -0
  66. data/lib/cm_app_logger.rb +28 -14
  67. data/lib/spree_cm_commissioner/test_helper/factories/vendor_factory.rb +1 -0
  68. data/lib/spree_cm_commissioner/test_helper/factories/vendor_place_factory.rb +3 -2
  69. data/lib/spree_cm_commissioner/version.rb +1 -1
  70. metadata +7 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: cd65c0e3f9c574eac1886f0dd7872516ee4b06ce9de12c91cd56e9101ea37914
4
- data.tar.gz: 223b2e1bc19876a282cf764cbfd45da3aeb3e13b671a9bafeaf697bed5938380
3
+ metadata.gz: ea2a829c1d2491dbd13af86ebaa5ebe0a8731dc07b3f8ffe7349a243d2f143f1
4
+ data.tar.gz: 5ed54a23f9138d529fd3023daad09ee00b0dc8f51d8a827104147b2a89e37ca5
5
5
  SHA512:
6
- metadata.gz: 959b4855a961019439474b8dc5fb987650e65ecb96c6e3b9a12355d3487d6d067c5824317cc825c882c858cee64c23e21695448999c3caf6b852e7c7d73fbfdc
7
- data.tar.gz: c3fe124a224836d629669bf723d80162253e1e732512870d1ddfbaf8bd2c115bb081eb058e7f9dc2acc1bdbe23b425bf9ad19ad2134d31c523c11163016eee0f
6
+ metadata.gz: 69a48d10783b6c7bb5310653aa6237ef0f9846bec57c8b29ba167e6a6a062feb788ef62b25b48244a6063373c6bb2be4025f71f4429b1db506e73f0052ba7975
7
+ data.tar.gz: 686be50cd3f6c12396a0ef534011abf8e99cc15800ff5ad56a1ae25f730e92ab5c54646bf9fda6dc8141852dc0dab5852ab3ebf57e8710f829bf8d03b180dbe7
data/.bundle/config CHANGED
@@ -1,3 +1,4 @@
1
1
  ---
2
- BUNDLE_RETRY: "3"
3
- BUNDLE_JOBS: "4"
2
+ BUNDLE_PATH: "/home/runner/work/commissioner/commissioner/vendor/bundle"
3
+ BUNDLE_DEPLOYMENT: "true"
4
+ BUNDLE_JOBS: "2"
@@ -5,12 +5,11 @@ on:
5
5
  pull_request:
6
6
  types:
7
7
  - opened
8
- - edited
9
8
  - synchronize
10
9
  - reopened
11
10
  branches:
12
11
  - develop
13
- - 3114-external-integration-milestone
12
+ - "*-milestone" # matches any branch with suffix *-milestone, eg. external-integration-milestone
14
13
  push:
15
14
  tags:
16
15
  - "*"
@@ -20,7 +19,7 @@ jobs:
20
19
 
21
20
  steps:
22
21
  - name: Check PR title format
23
- if: github.event_name == 'pull_request'
22
+ if: github.event_name == 'pull_request' && !contains(github.head_ref, '-milestone')
24
23
  uses: actions/github-script@v7
25
24
  with:
26
25
  script: |
@@ -38,8 +37,7 @@ jobs:
38
37
  console.log("PR title format is correct.");
39
38
  }
40
39
  - name: Check commit messages format
41
- # skip validation if the PR is from the milestone-77-scalable-design branch for temporary
42
- if: github.event_name == 'pull_request' && github.head_ref != 'milestone-77-scalable-design'
40
+ if: github.event_name == 'pull_request' && !contains(github.head_ref, '-milestone')
43
41
  uses: actions/github-script@v7
44
42
  with:
45
43
  script: |
@@ -71,7 +69,7 @@ jobs:
71
69
  console.log("All commit messages are correctly formatted.");
72
70
  }
73
71
  - name: Check for unresolved review threads
74
- if: github.event_name == 'pull_request'
72
+ if: github.event_name == 'pull_request' && !contains(github.head_ref, '-milestone')
75
73
  uses: actions/github-script@v7
76
74
  with:
77
75
  script: |
@@ -117,9 +115,8 @@ jobs:
117
115
  console.log("✅ All review threads are resolved.");
118
116
  }
119
117
 
120
- test_and_build_gem:
118
+ setup:
121
119
  needs: [validate-commits]
122
- # if: github.head_ref != '2572-enforce-pr-workflow' || github.base_ref != 'develop'
123
120
  runs-on: ubuntu-latest
124
121
 
125
122
  services:
@@ -152,22 +149,10 @@ jobs:
152
149
  steps:
153
150
  - uses: actions/checkout@v3
154
151
 
155
- # - uses: borales/actions-yarn@v2.0.0
156
- # with:
157
- # cmd: install
158
-
159
152
  - uses: ruby/setup-ruby@v1
160
153
  with:
161
154
  ruby-version: "3.2.0"
162
-
163
- # bundle-cache might cause problem when upgrading ruby. Disable it when upgrading to solve the problem.
164
- # bundler-cache: true
165
-
166
- - name: Install dependencies
167
- run: |
168
- sudo apt-get -yqq install libpq-dev
169
- gem install bundler
170
- bundle install --jobs 4 --retry 3
155
+ bundler-cache: true
171
156
 
172
157
  - name: Quality
173
158
  env:
@@ -181,56 +166,137 @@ jobs:
181
166
  run: |
182
167
  bundle exec brakeman
183
168
 
184
- - name: Run test
169
+ test:
170
+ needs: [setup]
171
+ runs-on: ubuntu-latest
172
+ if: github.event_name == 'pull_request'
173
+
174
+ strategy:
175
+ fail-fast: false
176
+ matrix:
177
+ spec_group: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
178
+
179
+ services:
180
+ db:
181
+ image: postgres:12
182
+ env:
183
+ POSTGRES_HOST_AUTH_METHOD: trust
184
+ POSTGRES_USER: myuser
185
+ POSTGRES_PASSWORD: mypassword
186
+ POSTGRES_DB: test_db
187
+ ports: ["5432:5432"]
188
+ options: >-
189
+ --health-cmd pg_isready
190
+ --health-interval 10s
191
+ --health-timeout 5s
192
+ --health-retries 5
193
+
194
+ redis:
195
+ image: redis
196
+ options: >-
197
+ --health-cmd "redis-cli ping"
198
+ --health-interval 10s
199
+ --health-timeout 5s
200
+ --health-retries 5
201
+ ports:
202
+ - 6379:6379
203
+
204
+ steps:
205
+ - uses: actions/checkout@v3
206
+
207
+ - name: Install system dependencies
208
+ run: |
209
+ sudo apt-get update -qq
210
+ sudo apt-get install -yqq libpq-dev
211
+
212
+ - uses: ruby/setup-ruby@v1
213
+ with:
214
+ ruby-version: "3.2.0"
215
+ bundler-cache: true
216
+
217
+ # Cache Strategy: Speed up test runs by ~40 seconds
218
+ # ================================================
219
+ # We split test app setup into 2 parts:
220
+ # 1. Generate files (slow ~40s, cacheable) - rake test_app:generate
221
+ # 2. Setup database (fast ~20s, always run) - rake test_app:db
222
+ #
223
+ # Cache Key: test-app-{OS}-{hash of Gemfile.lock + db/migrate files}
224
+ # - If Gemfile.lock or migrations change → new cache key → regenerate files
225
+ # - If unchanged → restore cached spec/dummy → skip generation
226
+ #
227
+ # Example:
228
+ # First run: Generate files (40s) + Setup DB (20s) = 60s total
229
+ # Cache hit: Restore cache (5s) + Setup DB (20s) = 25s total
230
+ # Savings: ~35-40 seconds per test job (10 parallel jobs = 350-400s saved!)
231
+ #
232
+ # What's cached: spec/dummy directory containing:
233
+ # - Generated Rails app files
234
+ # - Spree installation files
235
+ # - Extension installation files
236
+ # - Config files (database.yml, routes.rb, etc.)
237
+ #
238
+ # What's NOT cached (always regenerated):
239
+ # - Database itself (PostgreSQL data)
240
+ # - Test results
241
+ # - Coverage reports
242
+ - name: Cache test app files
243
+ uses: actions/cache@v3
244
+ with:
245
+ path: spec/dummy
246
+ key: test-app-${{ runner.os }}-${{ hashFiles('Gemfile.lock', 'db/migrate/*.rb') }}
247
+ restore-keys: |
248
+ test-app-${{ runner.os }}-
249
+
250
+ # Generate dummy Rails app for testing (cacheable part)
251
+ # This step checks if spec/dummy exists and skips generation if found
252
+ # Defined in: gems/spree_cm_commissioner/Rakefile (test_app:generate task)
253
+ - name: Generate test app files
185
254
  env:
186
255
  DATABASE_URL: postgres://myuser:mypassword@localhost:5432/test_db
187
256
  REDIS_URL: redis://localhost:6379/0
257
+ run: |
258
+ bundle exec rake test_app:generate
188
259
 
189
- if: github.event_name == 'pull_request'
260
+ # Setup database (always runs, fast ~20s)
261
+ # Drops/creates database and runs migrations
262
+ # Defined in: gems/spree_cm_commissioner/Rakefile (test_app:db task)
263
+ - name: Setup database
264
+ env:
265
+ DATABASE_URL: postgres://myuser:mypassword@localhost:5432/test_db
266
+ REDIS_URL: redis://localhost:6379/0
190
267
  run: |
191
- bundle exec rake
192
-
193
- # 2405-build-and-publish-gem
194
- # - name: Rename long migration files
195
- # env:
196
- # DATABASE_URL: postgres://myuser:mypassword@localhost:5432/test_db
197
- # # if: startsWith(github.ref, 'refs/tags/') # Only on tag pushes
198
- # if: github.ref == 'refs/heads/2405-build-and-publish-gem'
199
-
200
- # run: |
201
- # cd db/migrate
202
- # for file in *.rb; do
203
- # if [ ${#file} -gt 60 ]; then # Adjust threshold if needed
204
- # # Extract timestamp (first 14 chars) and shorten the rest
205
- # timestamp=${file:0:14}
206
- # suffix=$(echo "$file" | sed 's/^[0-9]\{14\}_//' | sed 's/\.rb$//')
207
- # short_suffix=$(echo "$suffix" | cut -c1-40) # Limit suffix to 40 chars
208
- # new_name="${timestamp}_${short_suffix}.rb"
209
- # mv "$file" "$new_name"
210
- # echo "Renamed $file to $new_name"
211
- # fi
212
- # done
268
+ bundle exec rake test_app:db
213
269
 
214
- # Build the gem
215
- - name: Build gem
270
+ # Run specs in parallel groups (1-12)
271
+ # Each group runs ~1/12th of total spec files
272
+ # Script: bin/run_spec_group shows which files are in each group
273
+ - name: Run test (Group ${{ matrix.spec_group }}/12)
216
274
  env:
217
275
  DATABASE_URL: postgres://myuser:mypassword@localhost:5432/test_db
276
+ REDIS_URL: redis://localhost:6379/0
277
+ run: |
278
+ bin/run_spec_group ${{ matrix.spec_group }} 12
279
+
280
+ build_and_publish:
281
+ needs: [setup]
282
+ runs-on: ubuntu-latest
283
+ if: startsWith(github.ref, 'refs/tags/')
284
+
285
+ steps:
286
+ - uses: actions/checkout@v3
218
287
 
219
- # if: startsWith(github.ref, 'refs/tags/') # Only on tag pushes
220
- if: |
221
- startsWith(github.ref, 'refs/tags/')
288
+ - uses: ruby/setup-ruby@v1
289
+ with:
290
+ ruby-version: "3.2.0"
291
+ bundler-cache: true
292
+
293
+ # Build the gem
294
+ - name: Build gem
222
295
  run: |
223
296
  gem build *.gemspec
224
297
 
225
298
  # Publish the gem
226
299
  - name: Publish gem
227
- env:
228
- DATABASE_URL: postgres://myuser:mypassword@localhost:5432/test_db
229
-
230
- # if: startsWith(github.ref, 'refs/tags/') # Only on tag pushes
231
- # (github.event_name == 'push' && github.ref == 'refs/heads/2405-build-and-publish-gem')
232
- if: |
233
- startsWith(github.ref, 'refs/tags/')
234
300
  run: |
235
301
  mkdir -p ~/.gem
236
302
  echo ":rubygems_api_key: ${{ secrets.RUBYGEMS_API_KEY }}" > ~/.gem/credentials
data/Gemfile.lock CHANGED
@@ -34,7 +34,7 @@ GIT
34
34
  PATH
35
35
  remote: .
36
36
  specs:
37
- spree_cm_commissioner (2.5.0.pre.pre7)
37
+ spree_cm_commissioner (2.5.0.pre.pre9)
38
38
  activerecord-multi-tenant
39
39
  activerecord_json_validator (~> 2.1, >= 2.1.3)
40
40
  aws-sdk-cloudfront
data/Rakefile CHANGED
@@ -17,34 +17,60 @@ end
17
17
  # Copied from:
18
18
  # spree_core:lib/spree/testing_support/common_rake.rb
19
19
  # But refactored to skip frontend & backend setup.
20
+
21
+ namespace :test_app do
22
+ desc 'Generate dummy app files (cacheable)'
23
+ task :generate do
24
+ require 'spree_cm_commissioner'
25
+ require "generators/spree_cm_commissioner/install/install_generator"
26
+
27
+ Rails.env = ENV['RAILS_ENV'] = 'test'
28
+
29
+ # Skip if already generated
30
+ if Dir.exist?('spec/dummy') && File.exist?('spec/dummy/config/database.yml')
31
+ puts '✓ Test app files already exist, skipping generation...'
32
+ else
33
+ puts 'Generating test app files...'
34
+ Spree::DummyGeneratorHelper.inject_extension_requirements = true
35
+ Spree::DummyGenerator.start ["--lib_name=spree_cm_commissioner", '--quiet']
36
+ Spree::InstallGenerator.start [
37
+ "--lib_name=spree_cm_commissioner",
38
+ '--auto-accept',
39
+ '--migrate=false',
40
+ '--seed=false',
41
+ '--sample=false',
42
+ '--quiet',
43
+ '--copy_storefront=false',
44
+ "--install_storefront=false",
45
+ "--install_admin=false",
46
+ "--user_class=Spree::User"
47
+ ]
48
+
49
+ puts 'Generating dummy model...'
50
+ Spree::DummyModelGenerator.start
51
+
52
+ puts 'Running extension installation generator...'
53
+ SpreeCmCommissioner::Generators::InstallGenerator.start(['--auto-run-migrations'])
54
+
55
+ puts '✓ Test app files generated'
56
+ end
57
+ end
58
+
59
+ desc 'Setup database'
60
+ task :db do
61
+ Rails.env = ENV['RAILS_ENV'] = 'test'
62
+
63
+ puts 'Setting up dummy database...'
64
+ Dir.chdir('spec/dummy') do
65
+ system('RAILS_ENV=test bundle exec rake db:drop db:create')
66
+ system('RAILS_ENV=test bundle exec rake db:migrate')
67
+ puts '✓ Database setup complete'
68
+ end
69
+ end
70
+ end
71
+
20
72
  desc 'Generates a dummy app for testing'
21
- task :test_app do |_t, args|
22
- require 'spree_cm_commissioner'
23
- require "generators/spree_cm_commissioner/install/install_generator"
24
-
25
- Rails.env = ENV['RAILS_ENV'] = 'test'
26
-
27
- Spree::DummyGeneratorHelper.inject_extension_requirements = true
28
- Spree::DummyGenerator.start ["--lib_name=spree_cm_commissioner", '--quiet']
29
- Spree::InstallGenerator.start [
30
- "--lib_name=spree_cm_commissioner",
31
- '--auto-accept',
32
- '--migrate=false',
33
- '--seed=false',
34
- '--sample=false',
35
- '--quiet',
36
- '--copy_storefront=false',
37
- "--install_storefront=false",
38
- "--install_admin=false",
39
- "--user_class=Spree::User"
40
- ]
41
-
42
- puts 'Setting up dummy database...'
43
- system('bin/rails db:environment:set RAILS_ENV=test')
44
- system('bundle exec rake db:drop db:create')
45
- Spree::DummyModelGenerator.start
46
- system('bundle exec rake db:migrate')
47
-
48
- puts 'Running extension installation generator...'
49
- SpreeCmCommissioner::Generators::InstallGenerator.start(['--auto-run-migrations'])
73
+ task :test_app do
74
+ Rake::Task['test_app:generate'].invoke
75
+ Rake::Task['test_app:db'].invoke
50
76
  end
@@ -61,11 +61,11 @@ module Spree
61
61
  api_patterns = api_patterns_map[model]
62
62
 
63
63
  if api_patterns.is_a?(Array)
64
- api_patterns.each { |pattern| SpreeCmCommissioner::InvalidateCacheRequestJob.perform_later(pattern) }
64
+ api_patterns.each { |pattern| SpreeCmCommissioner::InvalidateCacheRequestJob.perform_later(pattern: pattern) }
65
65
  elsif api_patterns.is_a?(String)
66
- SpreeCmCommissioner::InvalidateCacheRequestJob.perform_later(api_patterns)
66
+ SpreeCmCommissioner::InvalidateCacheRequestJob.perform_later(pattern: api_patterns)
67
67
  elsif params[:api_pattern].present?
68
- SpreeCmCommissioner::InvalidateCacheRequestJob.perform_later(params[:api_pattern])
68
+ SpreeCmCommissioner::InvalidateCacheRequestJob.perform_later(pattern: params[:api_pattern])
69
69
  end
70
70
  end
71
71
  redirect_back fallback_location: admin_root_path
@@ -17,7 +17,12 @@ module Spree
17
17
  import_order = build_import_order(name, imported_file)
18
18
 
19
19
  if import_order.save
20
- SpreeCmCommissioner::ImportOrderJob.perform_later(import_order.id, spree_current_user.id, import_order.import_type)
20
+ SpreeCmCommissioner::ImportOrderJob.perform_later(
21
+ import_order_id: import_order.id,
22
+ import_by_user_id: spree_current_user.id,
23
+
24
+ import_type: import_order.import_type
25
+ )
21
26
  flash[:success] = I18n.t('import_orders.success_message')
22
27
  else
23
28
  flash[:error] = I18n.t('import_orders.error_message')
@@ -5,7 +5,7 @@ module Spree
5
5
 
6
6
  def recalculate_conversions
7
7
  @taxon.products.each do |product|
8
- SpreeCmCommissioner::ConversionPreCalculatorJob.perform_later(product.id)
8
+ SpreeCmCommissioner::ConversionPreCalculatorJob.perform_later(product_id: product.id)
9
9
  end
10
10
 
11
11
  flash[:success] = flash_message_for(@taxon, :successfully_updated)
@@ -5,7 +5,7 @@ module Spree
5
5
  customer_notification_id = params[:notification_id]
6
6
  user_ids = params[:send_all] == 'true' ? nil : params[:user_ids]
7
7
 
8
- SpreeCmCommissioner::CustomerNotificationSenderJob.perform_later(customer_notification_id, user_ids)
8
+ SpreeCmCommissioner::CustomerNotificationSenderJob.perform_later(customer_notification_id: customer_notification_id, user_ids: user_ids)
9
9
 
10
10
  redirect_to admin_customer_notifications_path
11
11
  end
@@ -19,7 +19,8 @@ module Spree
19
19
  # override
20
20
  def collection
21
21
  @collection ||= collection_finder.new.execute(
22
- route_type: params[:route_type]
22
+ route_type: params[:route_type],
23
+ query: params[:query]
23
24
  )
24
25
  end
25
26
 
@@ -51,6 +52,11 @@ module Spree
51
52
  )
52
53
  end
53
54
 
55
+ # override
56
+ def required_schema
57
+ SpreeCmCommissioner::PopularRoutePlacesRequestSchema
58
+ end
59
+
54
60
  def include_vendors?
55
61
  resource_includes.include?(:vendors) || false
56
62
  end
@@ -19,12 +19,12 @@ module Spree
19
19
  end
20
20
 
21
21
  job = SpreeCmCommissioner::EnqueueCart::AddItemJob.perform_later(
22
- spree_current_order.id,
23
- @variant.id,
24
- add_item_params[:quantity],
25
- add_item_params[:public_metadata],
26
- add_item_params[:private_metadata],
27
- add_item_params[:options]
22
+ order_id: spree_current_order.id,
23
+ variant_id: @variant.id,
24
+ quantity: add_item_params[:quantity],
25
+ public_metadata: add_item_params[:public_metadata],
26
+ private_metadata: add_item_params[:private_metadata],
27
+ options: add_item_params[:options]
28
28
  )
29
29
 
30
30
  return render_error_payload('Failed to enqueue the job') unless job
@@ -3,22 +3,22 @@
3
3
  # GET /api/v2/storefront/route_places
4
4
  #
5
5
  # Finds places (origins or destinations) that are connected to a given place through existing routes.
6
- # Optionally filters results by keyword or route_type. Supports two modes:
6
+ # Optionally filters results by query or route_type. Supports two modes:
7
7
  #
8
8
  # Usage 1: Connected places (requires place_id)
9
9
  # - Finds places connected to a specific place via routes
10
10
  # - Returns origins/destinations that have routes with the specified place
11
11
  #
12
- # Usage 2: Keyword search (requires query, place_id optional)
13
- # - Searches all route places by keyword
14
- # - Returns all origins/destinations matching the keyword
12
+ # Usage 2: query search (requires query, place_id optional)
13
+ # - Searches all route places by query
14
+ # - Returns all origins/destinations matching the query
15
15
  #
16
16
  # Query Parameters:
17
17
  # - place_type: [String] Required. Type of route place: 'origin' or 'destination'
18
18
  # * 'origin': returns origins that have routes TO the specified place (if place_id provided)
19
19
  # * 'destination': returns destinations that have routes FROM the specified place (if place_id provided)
20
20
  # - place_id: [Integer] Optional. The place ID to find connected places for
21
- # - query: [String] Optional. Keyword to filter place names (case-insensitive)
21
+ # - query: [String] Optional. query to filter place names (case-insensitive)
22
22
  # - include: Optional comma-separated list (e.g., 'vendors,nearby_places')
23
23
  #
24
24
  # Response: Collection of places serialized with PlaceSerializer
@@ -27,15 +27,15 @@
27
27
  # - Returns empty collection if place_type is invalid
28
28
  # - If place_id provided: returns places connected to that place
29
29
  # - If place_id blank: returns all origins/destinations
30
- # - Filters results by keyword or route_type if provided
30
+ # - Filters results by query or route_type if provided
31
31
  #
32
32
  # @example Mode 1: Find destinations connected to origin place ID 123
33
33
  # GET /api/v2/storefront/route_places?place_id=123&place_type=destination
34
34
  #
35
- # @example Mode 2: Search all destination places by keyword
35
+ # @example Mode 2: Search all destination places by query
36
36
  # GET /api/v2/storefront/route_places?place_type=destination&query=Phnom
37
37
  #
38
- # @example Combined: Find origins connected to place 456, filtered by keyword
38
+ # @example Combined: Find origins connected to place 456, filtered by query
39
39
  # GET /api/v2/storefront/route_places?place_id=456&place_type=origin&query=Siem
40
40
  module Spree
41
41
  module Api
@@ -49,7 +49,7 @@ module Spree
49
49
  @collection ||= collection_finder.new(
50
50
  place_type: params[:place_type],
51
51
  place_id: params[:place_id],
52
- keyword: params[:query],
52
+ query: params[:query],
53
53
  route_type: params[:route_type]
54
54
  ).execute
55
55
  end
@@ -2,14 +2,14 @@
2
2
  #
3
3
  # @param place_type [String] Required. 'origin' or 'destination'
4
4
  # @param place_id [Integer] Optional. Filter by connected place ID
5
- # @param keyword [String] Optional. Filter by place name (case-insensitive)
5
+ # @param query [String] Optional. Filter by place name (case-insensitive)
6
6
  # @param route_type [Symbol, String] Optional. Filter by route type from associated trips (e.g., :ferry, :bus)
7
7
  #
8
8
  # @return [ActiveRecord::Relation<SpreeCmCommissioner::Place>]
9
9
  #
10
10
  # Modes:
11
11
  # - place_id only: returns connected places (origins TO or destinations FROM given place)
12
- # - keyword only: filters by name
12
+ # - query only: filters by name
13
13
  # - route_type only: filters by trip route types on those routes
14
14
  # - combinations: connected places filtered by name and/or route type
15
15
  # - neither: all origins/destinations in routes
@@ -17,17 +17,17 @@
17
17
  # @example Origins with ferry trips to place 123
18
18
  # FindWithRoute.new(place_type: 'origin', place_id: 123, route_type: :ferry).execute
19
19
  #
20
- # @example Destinations filtered by keyword and route type
21
- # FindWithRoute.new(place_type: 'destination', keyword: 'Phnom', route_type: :bus).execute
20
+ # @example Destinations filtered by query and route type
21
+ # FindWithRoute.new(place_type: 'destination', query: 'Phnom', route_type: :bus).execute
22
22
  module SpreeCmCommissioner
23
23
  module Places
24
24
  class FindWithRoute
25
- attr_reader :place_type, :place_id, :keyword, :route_type
25
+ attr_reader :place_type, :place_id, :query, :route_type
26
26
 
27
- def initialize(place_type:, place_id: nil, keyword: nil, route_type: nil)
27
+ def initialize(place_type:, place_id: nil, query: nil, route_type: nil)
28
28
  @place_type = place_type
29
29
  @place_id = place_id
30
- @keyword = keyword
30
+ @query = query
31
31
  @route_type = route_type
32
32
  end
33
33
 
@@ -36,7 +36,7 @@ module SpreeCmCommissioner
36
36
  return SpreeCmCommissioner::Place.none if place_id.present? && !SpreeCmCommissioner::Place.exists?(place_id)
37
37
 
38
38
  result = scope
39
- result = apply_keyword_filter(result) if keyword.present?
39
+ result = apply_query_filter(result) if query.present?
40
40
  result = apply_route_type_filter(result) if route_type.present?
41
41
  result
42
42
  end
@@ -57,8 +57,8 @@ module SpreeCmCommissioner
57
57
  end
58
58
  end
59
59
 
60
- def apply_keyword_filter(result)
61
- result.where('cm_places.name ILIKE ?', "%#{keyword}%")
60
+ def apply_query_filter(result)
61
+ result.where('cm_places.name ILIKE ?', "%#{query}%")
62
62
  end
63
63
 
64
64
  def apply_route_type_filter(result)
@@ -24,26 +24,22 @@
24
24
  module SpreeCmCommissioner
25
25
  module Routes
26
26
  class FindPopular
27
- def execute(route_type: nil)
28
- scope(route_type: route_type)
27
+ def execute(route_type: nil, query: nil)
28
+ scope(route_type: route_type, query: query)
29
29
  end
30
30
 
31
31
  private
32
32
 
33
- def scope(route_type: nil)
34
- result = SpreeCmCommissioner::Route
35
- .includes(:origin_place, :destination_place)
33
+ def scope(route_type:, query:)
34
+ includes_associations = %i[origin_place destination_place]
35
+ includes_associations << :trips if route_type.present?
36
+ result = SpreeCmCommissioner::Route.includes(*includes_associations)
36
37
 
37
- if route_type.present?
38
- # Filter routes that have trips with the specified route_type
39
- route_scope = SpreeCmCommissioner::Route
40
- .joins(:trips)
41
- .where(cm_trips: { route_type: route_type.to_sym })
42
- result = result.where(id: route_scope.select(:id))
43
- end
38
+ result = result.joins(:trips).where(cm_trips: { route_type: route_type.to_sym }) if route_type.present?
44
39
 
45
- result.order(Arel.sql('COALESCE(fulfilled_order_count, 0) DESC'))
46
- .order(Arel.sql('COALESCE(order_count, 0) DESC'))
40
+ result = result.where('cm_routes.route_name ILIKE ?', "%#{query}%") if query.present?
41
+
42
+ result.distinct.order(fulfilled_order_count: :desc, order_count: :desc)
47
43
  end
48
44
  end
49
45
  end
@@ -94,7 +94,7 @@ module SpreeCmCommissioner
94
94
  end
95
95
 
96
96
  def generate_reports
97
- SpreeCmCommissioner::ReportsAssignerJob.perform_later(@parent_taxon.id, @parent_taxon.class.to_s)
97
+ SpreeCmCommissioner::ReportsAssignerJob.perform_later(queryable_id: @parent_taxon.id, queryable_type: @parent_taxon.class.to_s)
98
98
  end
99
99
  end
100
100
  end
@@ -11,7 +11,7 @@ module SpreeCmCommissioner
11
11
  end
12
12
 
13
13
  def enqueue_customer_notification_alert(customer_notification)
14
- SpreeCmCommissioner::CustomerNotificationSenderJob.perform_later(customer_notification.id)
14
+ SpreeCmCommissioner::CustomerNotificationSenderJob.perform_later(customer_notification_id: customer_notification.id)
15
15
  end
16
16
  end
17
17
  end
@@ -23,8 +23,9 @@ module SpreeCmCommissioner
23
23
  private
24
24
 
25
25
  def adjust_inventory_items_async(variant_id, quantity)
26
- CmAppLogger.log(label: "#{self.class.name}#adjust_inventory_items_async", data: { variant_id: variant_id, quantity: quantity }) do
27
- SpreeCmCommissioner::Stock::InventoryItemsAdjusterJob.perform_later(variant_id: variant_id, quantity: quantity)
26
+ args = { variant_id: variant_id, quantity: quantity }
27
+ CmAppLogger.log(label: "#{self.class.name}#adjust_inventory_items_async", data: args) do
28
+ SpreeCmCommissioner::Stock::InventoryItemsAdjusterJob.perform_later(**args)
28
29
  end
29
30
  end
30
31
  end
@@ -2,8 +2,8 @@ module SpreeCmCommissioner
2
2
  class ConversionPreCalculatorJob < ApplicationUniqueJob
3
3
  queue_as :default
4
4
 
5
- def perform(product_id)
6
- product = Spree::Product.find(product_id)
5
+ def perform(options = {})
6
+ product = Spree::Product.find(options[:product_id])
7
7
  product.classification_ids.each do |classification_id|
8
8
  SpreeCmCommissioner::ConversionPreCalculator.call(product_taxon: Spree::Classification.find(classification_id))
9
9
  end