spree_cm_commissioner 1.10.0.pre.pre → 1.10.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.
Files changed (61) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/test_and_build_gem.yml +0 -2
  3. data/.gitignore +1 -2
  4. data/Gemfile.lock +1 -22
  5. data/app/controllers/spree/admin/stock_managements_controller.rb +1 -17
  6. data/app/controllers/spree/api/v2/storefront/accommodations_controller.rb +31 -14
  7. data/app/interactors/spree_cm_commissioner/vattanac_bank_initiator.rb +6 -25
  8. data/app/models/concerns/spree_cm_commissioner/option_type_attr_type.rb +3 -2
  9. data/app/models/concerns/spree_cm_commissioner/order_state_machine.rb +0 -26
  10. data/app/models/concerns/spree_cm_commissioner/product_type.rb +0 -10
  11. data/app/models/spree_cm_commissioner/line_item_decorator.rb +0 -1
  12. data/app/models/spree_cm_commissioner/order_decorator.rb +0 -15
  13. data/app/models/spree_cm_commissioner/product_decorator.rb +0 -1
  14. data/app/models/spree_cm_commissioner/stock/availability_checker.rb +25 -27
  15. data/app/models/spree_cm_commissioner/stock/availability_validator_decorator.rb +1 -2
  16. data/app/models/spree_cm_commissioner/stock/line_item_availability_checker.rb +3 -3
  17. data/app/models/spree_cm_commissioner/trip_connection.rb +1 -0
  18. data/app/models/spree_cm_commissioner/trip_stop.rb +2 -2
  19. data/app/models/spree_cm_commissioner/variant_decorator.rb +20 -24
  20. data/app/models/spree_cm_commissioner/variant_options.rb +0 -14
  21. data/app/queries/spree_cm_commissioner/trip_query.rb +11 -11
  22. data/app/queries/spree_cm_commissioner/variant_availability/non_permanent_stock_query.rb +45 -0
  23. data/app/queries/spree_cm_commissioner/variant_availability/permanent_stock_query.rb +55 -0
  24. data/app/request_schemas/spree_cm_commissioner/accommodation_request_schema.rb +0 -3
  25. data/app/request_schemas/spree_cm_commissioner/application_request_schema.rb +1 -1
  26. data/app/serializers/spree/v2/storefront/accommodation_serializer.rb +0 -2
  27. data/app/views/spree/admin/stock_managements/index.html.erb +5 -31
  28. data/config/routes.rb +2 -11
  29. data/docker-compose.yml +1 -1
  30. data/lib/generators/spree_cm_commissioner/install/install_generator.rb +2 -2
  31. data/lib/generators/spree_cm_commissioner/install/templates/app/javascript/{spree_dashboard/spree_cm_commissioner → spree_cm_commissioner}/utilities.js +0 -4
  32. data/lib/spree_cm_commissioner/calendar_event.rb +1 -11
  33. data/lib/spree_cm_commissioner/test_helper/factories/variant_factory.rb +6 -28
  34. data/lib/spree_cm_commissioner/version.rb +1 -1
  35. data/lib/spree_cm_commissioner.rb +0 -34
  36. data/spree_cm_commissioner.gemspec +0 -5
  37. metadata +7 -71
  38. data/app/controllers/spree/api/v2/storefront/accommodations/variants_controller.rb +0 -42
  39. data/app/finders/spree_cm_commissioner/accommodations/find.rb +0 -40
  40. data/app/finders/spree_cm_commissioner/accommodations/find_variant.rb +0 -35
  41. data/app/interactors/spree_cm_commissioner/inventory_item_syncer.rb +0 -25
  42. data/app/interactors/spree_cm_commissioner/stock/permanent_inventory_items_generator.rb +0 -71
  43. data/app/jobs/spree_cm_commissioner/inventory_item_syncer_job.rb +0 -7
  44. data/app/jobs/spree_cm_commissioner/stock/permanent_inventory_items_generator_job.rb +0 -9
  45. data/app/models/spree_cm_commissioner/inventory.rb +0 -11
  46. data/app/models/spree_cm_commissioner/inventory_item.rb +0 -37
  47. data/app/models/spree_cm_commissioner/redis_stock/cached_inventory_items_builder.rb +0 -40
  48. data/app/models/spree_cm_commissioner/redis_stock/inventory_updater.rb +0 -114
  49. data/app/models/spree_cm_commissioner/redis_stock/line_items_cached_inventory_items_builder.rb +0 -42
  50. data/app/models/spree_cm_commissioner/redis_stock/variant_cached_inventory_items_builder.rb +0 -27
  51. data/app/models/spree_cm_commissioner/stock/order_availability_checker.rb +0 -44
  52. data/app/models/spree_cm_commissioner/stock_movement_decorator.rb +0 -34
  53. data/app/request_schemas/spree_cm_commissioner/variant_request_schema.rb +0 -19
  54. data/app/views/spree/admin/stock_managements/_events_popover.html.erb +0 -17
  55. data/app/views/spree/admin/stock_managements/calendar.html.erb +0 -32
  56. data/db/migrate/20250304293518_create_cm_inventory_items.rb +0 -21
  57. data/db/migrate/20250429094228_add_lock_version_to_cm_inventory_items.rb +0 -5
  58. data/lib/spree_cm_commissioner/cached_inventory_item.rb +0 -23
  59. data/lib/spree_cm_commissioner/test_helper/factories/inventory_item_factory.rb +0 -9
  60. data/lib/tasks/create_default_non_permanent_inventory_items.rake +0 -16
  61. data/lib/tasks/generate_inventory_items.rake +0 -7
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.10.0.pre.pre
4
+ version: 1.10.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-04-30 00:00:00.000000000 Z
11
+ date: 2025-05-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: spree
@@ -464,48 +464,6 @@ dependencies:
464
464
  - - "~>"
465
465
  - !ruby/object:Gem::Version
466
466
  version: '3.2'
467
- - !ruby/object:Gem::Dependency
468
- name: redis
469
- requirement: !ruby/object:Gem::Requirement
470
- requirements:
471
- - - ">="
472
- - !ruby/object:Gem::Version
473
- version: '0'
474
- type: :runtime
475
- prerelease: false
476
- version_requirements: !ruby/object:Gem::Requirement
477
- requirements:
478
- - - ">="
479
- - !ruby/object:Gem::Version
480
- version: '0'
481
- - !ruby/object:Gem::Dependency
482
- name: redis-rails
483
- requirement: !ruby/object:Gem::Requirement
484
- requirements:
485
- - - ">="
486
- - !ruby/object:Gem::Version
487
- version: '0'
488
- type: :runtime
489
- prerelease: false
490
- version_requirements: !ruby/object:Gem::Requirement
491
- requirements:
492
- - - ">="
493
- - !ruby/object:Gem::Version
494
- version: '0'
495
- - !ruby/object:Gem::Dependency
496
- name: connection_pool
497
- requirement: !ruby/object:Gem::Requirement
498
- requirements:
499
- - - ">="
500
- - !ruby/object:Gem::Version
501
- version: '0'
502
- type: :runtime
503
- prerelease: false
504
- version_requirements: !ruby/object:Gem::Requirement
505
- requirements:
506
- - - ">="
507
- - !ruby/object:Gem::Version
508
- version: '0'
509
467
  - !ruby/object:Gem::Dependency
510
468
  name: pg
511
469
  requirement: !ruby/object:Gem::Requirement
@@ -830,7 +788,6 @@ files:
830
788
  - app/controllers/spree/api/v2/platform/seat_number_layouts_controller.rb
831
789
  - app/controllers/spree/api/v2/platform/taxons_controller_decorator.rb
832
790
  - app/controllers/spree/api/v2/resource_controller_decorator.rb
833
- - app/controllers/spree/api/v2/storefront/accommodations/variants_controller.rb
834
791
  - app/controllers/spree/api/v2/storefront/accommodations_controller.rb
835
792
  - app/controllers/spree/api/v2/storefront/account/orders_controller_decorator.rb
836
793
  - app/controllers/spree/api/v2/storefront/account/preferred_payment_method_controller.rb
@@ -1001,8 +958,6 @@ files:
1001
958
  - app/exception_notifier/spree_cm_commissioner/telegram_notifier.rb
1002
959
  - app/factory/spree_cm_commissioner/order_telegram_message_factory.rb
1003
960
  - app/factory/spree_cm_commissioner/telegram_message_factory.rb
1004
- - app/finders/spree_cm_commissioner/accommodations/find.rb
1005
- - app/finders/spree_cm_commissioner/accommodations/find_variant.rb
1006
961
  - app/finders/spree_cm_commissioner/line_items/find_by_variant_decorator.rb
1007
962
  - app/finders/spree_cm_commissioner/orders/find.rb
1008
963
  - app/finders/spree_cm_commissioner/orders/find_by_state.rb
@@ -1060,7 +1015,6 @@ files:
1060
1015
  - app/interactors/spree_cm_commissioner/imported_csv_downloader.rb
1061
1016
  - app/interactors/spree_cm_commissioner/international_mobile_formatter.rb
1062
1017
  - app/interactors/spree_cm_commissioner/invalidate_cache_request.rb
1063
- - app/interactors/spree_cm_commissioner/inventory_item_syncer.rb
1064
1018
  - app/interactors/spree_cm_commissioner/invoice_creator.rb
1065
1019
  - app/interactors/spree_cm_commissioner/media/signed_cookie_generator.rb
1066
1020
  - app/interactors/spree_cm_commissioner/media/signed_path_generator.rb
@@ -1090,7 +1044,6 @@ files:
1090
1044
  - app/interactors/spree_cm_commissioner/sms.rb
1091
1045
  - app/interactors/spree_cm_commissioner/sqs/media_convert_job_status.rb
1092
1046
  - app/interactors/spree_cm_commissioner/state_updater.rb
1093
- - app/interactors/spree_cm_commissioner/stock/permanent_inventory_items_generator.rb
1094
1047
  - app/interactors/spree_cm_commissioner/subscriptions_order_creator.rb
1095
1048
  - app/interactors/spree_cm_commissioner/subscriptions_order_cron_executor.rb
1096
1049
  - app/interactors/spree_cm_commissioner/subscriptions_prepaid_order_creator.rb
@@ -1143,7 +1096,6 @@ files:
1143
1096
  - app/jobs/spree_cm_commissioner/firebase_email_fetcher_job.rb
1144
1097
  - app/jobs/spree_cm_commissioner/import_order_job.rb
1145
1098
  - app/jobs/spree_cm_commissioner/invalidate_cache_request_job.rb
1146
- - app/jobs/spree_cm_commissioner/inventory_item_syncer_job.rb
1147
1099
  - app/jobs/spree_cm_commissioner/option_type_variants_public_metadata_updater_job.rb
1148
1100
  - app/jobs/spree_cm_commissioner/option_value_variants_public_metadata_updater_job.rb
1149
1101
  - app/jobs/spree_cm_commissioner/order_complete_telegram_sender_job.rb
@@ -1151,7 +1103,6 @@ files:
1151
1103
  - app/jobs/spree_cm_commissioner/sms_job.rb
1152
1104
  - app/jobs/spree_cm_commissioner/sms_pin_code_job.rb
1153
1105
  - app/jobs/spree_cm_commissioner/state_job.rb
1154
- - app/jobs/spree_cm_commissioner/stock/permanent_inventory_items_generator_job.rb
1155
1106
  - app/jobs/spree_cm_commissioner/subscription_order_executor_job.rb
1156
1107
  - app/jobs/spree_cm_commissioner/telegram_debug_pin_code_sender_job.rb
1157
1108
  - app/jobs/spree_cm_commissioner/telegram_notification_sender_job.rb
@@ -1244,8 +1195,6 @@ files:
1244
1195
  - app/models/spree_cm_commissioner/image_methods_decorator.rb
1245
1196
  - app/models/spree_cm_commissioner/import.rb
1246
1197
  - app/models/spree_cm_commissioner/imports/import_order.rb
1247
- - app/models/spree_cm_commissioner/inventory.rb
1248
- - app/models/spree_cm_commissioner/inventory_item.rb
1249
1198
  - app/models/spree_cm_commissioner/invite.rb
1250
1199
  - app/models/spree_cm_commissioner/invite_user_event.rb
1251
1200
  - app/models/spree_cm_commissioner/invite_user_taxon.rb
@@ -1295,10 +1244,6 @@ files:
1295
1244
  - app/models/spree_cm_commissioner/promotion_decorator.rb
1296
1245
  - app/models/spree_cm_commissioner/property_decorator.rb
1297
1246
  - app/models/spree_cm_commissioner/prototype_decorator.rb
1298
- - app/models/spree_cm_commissioner/redis_stock/cached_inventory_items_builder.rb
1299
- - app/models/spree_cm_commissioner/redis_stock/inventory_updater.rb
1300
- - app/models/spree_cm_commissioner/redis_stock/line_items_cached_inventory_items_builder.rb
1301
- - app/models/spree_cm_commissioner/redis_stock/variant_cached_inventory_items_builder.rb
1302
1247
  - app/models/spree_cm_commissioner/role_decorator.rb
1303
1248
  - app/models/spree_cm_commissioner/role_permission.rb
1304
1249
  - app/models/spree_cm_commissioner/s3_presigned_url.rb
@@ -1311,10 +1256,8 @@ files:
1311
1256
  - app/models/spree_cm_commissioner/stock/availability_validator_decorator.rb
1312
1257
  - app/models/spree_cm_commissioner/stock/inventory_unit_builder_decorator.rb
1313
1258
  - app/models/spree_cm_commissioner/stock/line_item_availability_checker.rb
1314
- - app/models/spree_cm_commissioner/stock/order_availability_checker.rb
1315
1259
  - app/models/spree_cm_commissioner/stock_item_decorator.rb
1316
1260
  - app/models/spree_cm_commissioner/stock_location_decorator.rb
1317
- - app/models/spree_cm_commissioner/stock_movement_decorator.rb
1318
1261
  - app/models/spree_cm_commissioner/stop.rb
1319
1262
  - app/models/spree_cm_commissioner/store_decorator.rb
1320
1263
  - app/models/spree_cm_commissioner/subscription.rb
@@ -1517,12 +1460,13 @@ files:
1517
1460
  - app/queries/spree_cm_commissioner/trip_search_query.rb
1518
1461
  - app/queries/spree_cm_commissioner/trip_seat_layout_query.rb
1519
1462
  - app/queries/spree_cm_commissioner/users_by_event_fetcher_query.rb
1463
+ - app/queries/spree_cm_commissioner/variant_availability/non_permanent_stock_query.rb
1464
+ - app/queries/spree_cm_commissioner/variant_availability/permanent_stock_query.rb
1520
1465
  - app/request_schemas/spree_cm_commissioner/accommodation_request_schema.rb
1521
1466
  - app/request_schemas/spree_cm_commissioner/application_request_schema.rb
1522
1467
  - app/request_schemas/spree_cm_commissioner/profile_image_request_schema.rb
1523
1468
  - app/request_schemas/spree_cm_commissioner/user_account_linkage_request_schema.rb
1524
1469
  - app/request_schemas/spree_cm_commissioner/user_profile_request_schema.rb
1525
- - app/request_schemas/spree_cm_commissioner/variant_request_schema.rb
1526
1470
  - app/serializables/spree_cm_commissioner/event_ticket_aggregator.rb
1527
1471
  - app/serializables/spree_cm_commissioner/pie_chart_event_aggregator.rb
1528
1472
  - app/serializables/spree_cm_commissioner/queue_item.rb
@@ -1847,9 +1791,7 @@ files:
1847
1791
  - app/views/spree/admin/shared/_video_on_demand_helper_script.html.erb
1848
1792
  - app/views/spree/admin/shared/sub_menu/_calendar.html.erb
1849
1793
  - app/views/spree/admin/shared/sub_menu/_homepage.html.erb
1850
- - app/views/spree/admin/stock_managements/_events_popover.html.erb
1851
1794
  - app/views/spree/admin/stock_managements/_variant_stock_items.html.erb
1852
- - app/views/spree/admin/stock_managements/calendar.html.erb
1853
1795
  - app/views/spree/admin/stock_managements/index.html.erb
1854
1796
  - app/views/spree/admin/system/show.html.erb
1855
1797
  - app/views/spree/admin/taxon_childrens/index.html.erb
@@ -2415,7 +2357,6 @@ files:
2415
2357
  - db/migrate/20250304101907_create_spree_cm_commissioner_invite.rb
2416
2358
  - db/migrate/20250304101946_create_spree_cm_commissioner_invite_user_taxon.rb
2417
2359
  - db/migrate/20250304155234_add_meta_data_to_spree_vendors.rb
2418
- - db/migrate/20250304293518_create_cm_inventory_items.rb
2419
2360
  - db/migrate/20250307013422_add_parent_id_to_cm_place.rb
2420
2361
  - db/migrate/20250307073003_add_tenant_id_to_cm_customer_notifications.rb
2421
2362
  - db/migrate/20250307083809_remove_tenant_id_from_cm_notifications.rb
@@ -2434,7 +2375,6 @@ files:
2434
2375
  - db/migrate/20250425084929_add_description_to_spree_prototypes.rb
2435
2376
  - db/migrate/20250425085938_add_preferences_to_spree_prototypes.rb
2436
2377
  - db/migrate/20250428025645_add_slug_to_spree_prototypes.rb
2437
- - db/migrate/20250429094228_add_lock_version_to_cm_inventory_items.rb
2438
2378
  - docker-compose.yml
2439
2379
  - docs/option_types/attr_types.md
2440
2380
  - docs/private_key.pem
@@ -2449,12 +2389,11 @@ files:
2449
2389
  - docs/webhook/sqs/params_job_submitted.json
2450
2390
  - lib/cm_app_logger.rb
2451
2391
  - lib/generators/spree_cm_commissioner/install/install_generator.rb
2452
- - lib/generators/spree_cm_commissioner/install/templates/app/javascript/spree_dashboard/spree_cm_commissioner/utilities.js
2392
+ - lib/generators/spree_cm_commissioner/install/templates/app/javascript/spree_cm_commissioner/utilities.js
2453
2393
  - lib/generators/spree_cm_commissioner/install/templates/config/data/nationalities.yml
2454
2394
  - lib/generators/spree_cm_commissioner/install/templates/vendor/assets/javascript/spree_cm_commissioner/telegram/all.js
2455
2395
  - lib/generators/spree_cm_commissioner/install/templates/vendor/assets/stylesheets/spree_cm_commissioner/telegram/all.css
2456
2396
  - lib/spree_cm_commissioner.rb
2457
- - lib/spree_cm_commissioner/cached_inventory_item.rb
2458
2397
  - lib/spree_cm_commissioner/calendar_event.rb
2459
2398
  - lib/spree_cm_commissioner/engine.rb
2460
2399
  - lib/spree_cm_commissioner/factories.rb
@@ -2489,7 +2428,6 @@ files:
2489
2428
  - lib/spree_cm_commissioner/test_helper/factories/homepage_section_relatable_factory.rb
2490
2429
  - lib/spree_cm_commissioner/test_helper/factories/id_card_factory.rb
2491
2430
  - lib/spree_cm_commissioner/test_helper/factories/image_factory.rb
2492
- - lib/spree_cm_commissioner/test_helper/factories/inventory_item_factory.rb
2493
2431
  - lib/spree_cm_commissioner/test_helper/factories/invite_factory.rb
2494
2432
  - lib/spree_cm_commissioner/test_helper/factories/invite_user_event_factory.rb
2495
2433
  - lib/spree_cm_commissioner/test_helper/factories/line_item_factory.rb
@@ -2544,12 +2482,10 @@ files:
2544
2482
  - lib/spree_cm_commissioner/trip_seat_layout_result.rb
2545
2483
  - lib/spree_cm_commissioner/user_session_jwt_token.rb
2546
2484
  - lib/spree_cm_commissioner/version.rb
2547
- - lib/tasks/create_default_non_permanent_inventory_items.rake
2548
2485
  - lib/tasks/customer_notification_cron_scheduler.rake
2549
2486
  - lib/tasks/ensure_event_for_guests.rake
2550
2487
  - lib/tasks/ensure_number_for_line_items.rake
2551
2488
  - lib/tasks/fetch_email.rake
2552
- - lib/tasks/generate_inventory_items.rake
2553
2489
  - lib/tasks/kh_location_option_values.rake
2554
2490
  - lib/tasks/kh_provinces.rake
2555
2491
  - lib/tasks/remove_duplicate_device_tokens.rake
@@ -2582,9 +2518,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
2582
2518
  version: '2.7'
2583
2519
  required_rubygems_version: !ruby/object:Gem::Requirement
2584
2520
  requirements:
2585
- - - ">"
2521
+ - - ">="
2586
2522
  - !ruby/object:Gem::Version
2587
- version: 1.3.1
2523
+ version: '0'
2588
2524
  requirements:
2589
2525
  - none
2590
2526
  rubygems_version: 3.4.1
@@ -1,42 +0,0 @@
1
- module Spree
2
- module Api
3
- module V2
4
- module Storefront
5
- class Accommodations::VariantsController < ::Spree::Api::V2::ResourceController
6
- private
7
-
8
- # override
9
- def collection
10
- @collection ||= SpreeCmCommissioner::Accommodations::FindVariant.new(
11
- from_date: params[:from_date]&.to_date,
12
- to_date: params[:to_date]&.to_date,
13
- vendor_id: params[:accommodation_id],
14
- number_of_adults: params[:number_of_adults].to_i,
15
- number_of_kids: params[:number_of_kids].to_i
16
- ).execute
17
- end
18
-
19
- # override
20
- def resource
21
- @resource ||= collection.find(params[:id])
22
- end
23
-
24
- # override
25
- def resource_serializer
26
- Spree::V2::Storefront::VariantSerializer
27
- end
28
-
29
- # override
30
- def collection_serializer
31
- Spree::V2::Storefront::VariantSerializer
32
- end
33
-
34
- # override
35
- def required_schema
36
- SpreeCmCommissioner::VariantRequestSchema
37
- end
38
- end
39
- end
40
- end
41
- end
42
- end
@@ -1,40 +0,0 @@
1
- module SpreeCmCommissioner
2
- module Accommodations
3
- class Find
4
- attr_reader :from_date, :to_date, :state_id, :number_of_guests
5
-
6
- def initialize(from_date:, to_date:, state_id:, number_of_adults:, number_of_kids:)
7
- @from_date = from_date
8
- @to_date = to_date
9
- @state_id = state_id
10
- @number_of_guests = number_of_adults.to_i + number_of_kids.to_i
11
- end
12
-
13
- def execute
14
- scope
15
- .where(default_state_id: state_id)
16
- .where(inventory_items: { inventory_date: date_range_excluding_checkout })
17
- .where('CAST(spree_variants.public_metadata->\'cm_options\'->>\'number-of-adults\' AS INTEGER) +
18
- CAST(spree_variants.public_metadata->\'cm_options\'->>\'number-of-kids\' AS INTEGER) >= ?', number_of_guests
19
- )
20
- .where('inventory_items.quantity_available > 0')
21
- .distinct
22
- end
23
-
24
- private
25
-
26
- def scope
27
- Spree::Vendor
28
- .joins(variants: :inventory_items)
29
- .where(primary_product_type: :accommodation, state: :active)
30
- end
31
-
32
- # Why? check_out date is not considered to be charged
33
- # For example, if you check in on 2023-10-01 and check out on 2023-10-02,
34
- # you will be charged for one night (2023-10-01).
35
- def date_range_excluding_checkout
36
- from_date..to_date.prev_day
37
- end
38
- end
39
- end
40
- end
@@ -1,35 +0,0 @@
1
- module SpreeCmCommissioner
2
- module Accommodations
3
- class FindVariant
4
- attr_reader :vendor_id, :from_date, :to_date, :number_of_guests
5
-
6
- def initialize(vendor_id:, from_date:, to_date:, number_of_adults:, number_of_kids:)
7
- @vendor_id = vendor_id
8
- @from_date = from_date
9
- @to_date = to_date
10
- @number_of_guests = number_of_adults.to_i + number_of_kids.to_i
11
- end
12
-
13
- def execute
14
- Spree::Variant
15
- .joins(:inventory_items)
16
- .where(vendor_id: vendor_id)
17
- .where(inventory_items: { inventory_date: date_range_excluding_checkout })
18
- .where('CAST(public_metadata->\'cm_options\'->>\'number-of-adults\' AS INTEGER) +
19
- CAST(public_metadata->\'cm_options\'->>\'number-of-kids\' AS INTEGER) >= ?', number_of_guests
20
- )
21
- .where('inventory_items.quantity_available > 0')
22
- .distinct
23
- end
24
-
25
- private
26
-
27
- # Why? check_out date is not considered to be charged
28
- # For example, if you check in on 2023-10-01 and check out on 2023-10-02,
29
- # you will be charged for one night (2023-10-01).
30
- def date_range_excluding_checkout
31
- from_date..to_date.prev_day
32
- end
33
- end
34
- end
35
- end
@@ -1,25 +0,0 @@
1
- module SpreeCmCommissioner
2
- class InventoryItemSyncer < BaseInteractor
3
- # inventory_id_and_quantities = [{ inventory_id: inventory_item1.id, quantity: 5 } ]
4
- delegate :inventory_id_and_quantities, to: :context
5
-
6
- def call
7
- ActiveRecord::Base.transaction do
8
- inventory_items.each do |inventory_item|
9
- quantity = inventory_id_and_quantities.find { |item| item[:inventory_id] == inventory_item.id }&.dig(:quantity) || 0
10
- adjust_quantity_available(inventory_item, quantity)
11
- end
12
- end
13
- end
14
-
15
- private
16
-
17
- def adjust_quantity_available(inventory_item, quantity)
18
- inventory_item.update!(quantity_available: inventory_item.quantity_available + quantity)
19
- end
20
-
21
- def inventory_items
22
- @inventory_items ||= InventoryItem.where(id: inventory_id_and_quantities.pluck(:inventory_id))
23
- end
24
- end
25
- end
@@ -1,71 +0,0 @@
1
- module SpreeCmCommissioner
2
- module Stock
3
- class PermanentInventoryItemsGenerator < BaseInteractor
4
- delegate :variant_ids, to: :context
5
-
6
- def variants_per_batch = 1000
7
-
8
- def call
9
- variants.in_batches(of: variants_per_batch) do |batch|
10
- generate_inventory_items_for_batch(batch)
11
- end
12
- end
13
-
14
- private
15
-
16
- def generate_inventory_items_for_batch(batch)
17
- total_on_hand_by_variant = total_on_hand_for(batch)
18
- batch.each do |variant|
19
- count_on_hand = total_on_hand_by_variant[variant.id] || 0
20
- generate_inventory_items_for_variant(variant, count_on_hand)
21
- end
22
- end
23
-
24
- def generate_inventory_items_for_variant(variant, count_on_hand)
25
- inventory_dates_for(variant).each do |inventory_date|
26
- next if inventory_exist?(variant, inventory_date)
27
-
28
- create_inventory_item(variant, inventory_date, count_on_hand)
29
- end
30
- end
31
-
32
- def inventory_dates_for(variant)
33
- start_date = Time.zone.tomorrow
34
- end_date = Time.zone.today + variant.pre_inventory_days
35
-
36
- (start_date..end_date)
37
- end
38
-
39
- def inventory_exist?(variant, inventory_date)
40
- variant.inventory_items.exists?(inventory_date: inventory_date)
41
- end
42
-
43
- def create_inventory_item(variant, inventory_date, count_on_hand)
44
- variant.inventory_items.create!(
45
- inventory_date: inventory_date,
46
- quantity_available: count_on_hand,
47
- max_capacity: count_on_hand,
48
- product_type: variant.product_type
49
- )
50
- end
51
-
52
- # Returns a hash: { variant_id => total_on_hand, ... }
53
- def total_on_hand_for(variants)
54
- variant_ids = variants.pluck(:id)
55
-
56
- Spree::StockItem
57
- .joins(:stock_location)
58
- .where(deleted_at: nil, variant_id: variant_ids)
59
- .where(spree_stock_locations: { active: true })
60
- .group(:variant_id)
61
- .sum(:count_on_hand)
62
- end
63
-
64
- def variants
65
- scope = Spree::Variant.active.with_permanent_stock.where(is_master: false).includes(:product)
66
- scope = scope.where(id: variant_ids) if variant_ids.present?
67
- scope
68
- end
69
- end
70
- end
71
- end
@@ -1,7 +0,0 @@
1
- module SpreeCmCommissioner
2
- class InventoryItemSyncerJob < ApplicationUniqueJob
3
- def perform(inventory_id_and_quantities:)
4
- InventoryItemSyncer.call(inventory_id_and_quantities:)
5
- end
6
- end
7
- end
@@ -1,9 +0,0 @@
1
- module SpreeCmCommissioner
2
- module Stock
3
- class PermanentInventoryItemsGeneratorJob < ApplicationUniqueJob
4
- def perform
5
- SpreeCmCommissioner::Stock::PermanentInventoryItemsGenerator.call
6
- end
7
- end
8
- end
9
- end
@@ -1,11 +0,0 @@
1
- module SpreeCmCommissioner
2
- class Inventory
3
- include ActiveModel::Model
4
-
5
- attr_accessor :variant_id, :inventory_date, :quantity_available, :max_capacity, :product_type
6
-
7
- validates :variant_id, presence: true
8
- validates :quantity_available, numericality: { only_integer: true, greater_than_or_equal_to: 0 }, allow_nil: true
9
- validates :max_capacity, numericality: { only_integer: true, greater_than_or_equal_to: 0 }, allow_nil: true
10
- end
11
- end
@@ -1,37 +0,0 @@
1
- module SpreeCmCommissioner
2
- class InventoryItem < ApplicationRecord
3
- include SpreeCmCommissioner::ProductType
4
-
5
- # Association
6
- belongs_to :variant, class_name: 'Spree::Variant'
7
-
8
- # Validation
9
- validates :quantity_available, numericality: { greater_than_or_equal_to: 0 }
10
- validates :max_capacity, numericality: { greater_than_or_equal_to: 0 } # Originally inventory of each variant.
11
- validates :inventory_date, presence: true, if: -> { permanent_stock? }
12
- validates :variant_id, uniqueness: { scope: :inventory_date, message: -> (object, _data) { "The variant is taken on #{object.inventory_date}" } }
13
-
14
- # Scope
15
- scope :for_product, -> (type) { where(product_type: type) }
16
- scope :active, -> { where(inventory_date: nil).or(where('inventory_date >= ?', Time.zone.today)) }
17
-
18
- def adjust_quantity!(quantity)
19
- with_lock do
20
- self.max_capacity = max_capacity + quantity
21
- self.quantity_available = quantity_available + quantity
22
-
23
- save!
24
- end
25
- end
26
-
27
- def active?
28
- inventory_date.nil? || inventory_date >= Time.zone.today
29
- end
30
-
31
- def redis_expired_in
32
- expired_in = 31_536_000 # 1 year for normal stock
33
- expired_in = Time.parse(inventory_date.to_s).end_of_day.to_i - Time.zone.now.to_i if inventory_date.present?
34
- [expired_in, 0].max
35
- end
36
- end
37
- end
@@ -1,40 +0,0 @@
1
- module SpreeCmCommissioner
2
- module RedisStock
3
- class CachedInventoryItemsBuilder
4
- attr_reader :inventory_items
5
-
6
- def initialize(inventory_items)
7
- @inventory_items = inventory_items
8
- end
9
-
10
- # output: [ CachedInventoryItem(...), CachedInventoryItem(...) ]
11
- def call
12
- keys = inventory_items.map { |item| "inventory:#{item.id}" }
13
- return [] unless keys.any?
14
-
15
- counts = SpreeCmCommissioner.redis_pool.with { |redis| redis.mget(*keys) }
16
- inventory_items.map.with_index do |inventory_item, i|
17
- ::SpreeCmCommissioner::CachedInventoryItem.new(
18
- inventory_key: keys[i],
19
- active: inventory_item.active?,
20
- quantity_available: cache_inventory(keys[i], inventory_item, counts[i]),
21
- inventory_item_id: inventory_item.id,
22
- variant_id: inventory_item.variant_id
23
- )
24
- end
25
- end
26
-
27
- private
28
-
29
- def cache_inventory(key, inventory_item, count_in_redis)
30
- return count_in_redis.to_i if count_in_redis.present?
31
-
32
- SpreeCmCommissioner.redis_pool.with do |redis|
33
- redis.set(key, inventory_item.quantity_available, ex: inventory_item.redis_expired_in)
34
- end
35
-
36
- inventory_item.quantity_available
37
- end
38
- end
39
- end
40
- end
@@ -1,114 +0,0 @@
1
- module SpreeCmCommissioner
2
- module RedisStock
3
- class InventoryUpdater
4
- class UnableToRestock < StandardError; end
5
- class UnableToUnstock < StandardError; end
6
-
7
- def initialize(line_item_ids)
8
- @line_item_ids = line_item_ids
9
- end
10
-
11
- def unstock!
12
- keys, quantities, inventory_ids = extract_inventory_data
13
-
14
- raise UnableToUnstock, Spree.t(:insufficient_stock_lines_present) unless unstock(keys, quantities)
15
-
16
- inventory_id_and_quantities = inventory_ids.map.with_index do |inventory_id, i|
17
- { inventory_id: inventory_id, quantity: -quantities[i] }
18
- end
19
-
20
- schedule_sync_inventory(inventory_id_and_quantities)
21
- end
22
-
23
- def restock!
24
- keys, quantities, inventory_ids = extract_inventory_data
25
-
26
- raise UnableToRestock unless restock(keys, quantities)
27
-
28
- inventory_id_and_quantities = inventory_ids.map.with_index do |inventory_id, i|
29
- { inventory_id: inventory_id, quantity: quantities[i] }
30
- end
31
-
32
- schedule_sync_inventory(inventory_id_and_quantities)
33
- end
34
-
35
- private
36
-
37
- def line_items
38
- @line_items ||= Spree::LineItem.where(id: @line_item_ids)
39
- end
40
-
41
- def unstock(keys, quantities)
42
- SpreeCmCommissioner.redis_pool.with do |redis|
43
- redis.eval(unstock_redis_script, keys: keys, argv: quantities)
44
- end.positive?
45
- end
46
-
47
- def restock(keys, quantities)
48
- SpreeCmCommissioner.redis_pool.with do |redis|
49
- redis.eval(restock_redis_script, keys: keys, argv: quantities)
50
- end.positive?
51
- end
52
-
53
- # Return: [CachedInventoryItem(...), CachedInventoryItem(...)]
54
- def cached_inventory_items
55
- @cached_inventory_items ||= SpreeCmCommissioner::RedisStock::LineItemsCachedInventoryItemsBuilder.new(line_item_ids: @line_item_ids)
56
- .call.values.flatten
57
- end
58
-
59
- def extract_inventory_data
60
- keys = []
61
- quantities = []
62
- inventory_ids = []
63
-
64
- cached_inventory_items.each do |cached_inventory_item|
65
- keys << cached_inventory_item.inventory_key
66
- quantities << line_items.find { |item| item.variant_id == cached_inventory_item.variant_id }.quantity
67
- inventory_ids << cached_inventory_item.inventory_item_id
68
- end
69
-
70
- [keys, quantities, inventory_ids]
71
- end
72
-
73
- def unstock_redis_script
74
- <<~LUA
75
- local keys = KEYS
76
- local quantities = ARGV
77
-
78
- -- Check availability first
79
- for i, key in ipairs(keys) do
80
- local current = tonumber(redis.call('GET', key) or 0)
81
- if current - tonumber(quantities[i]) < 0 then
82
- return 0
83
- end
84
- end
85
-
86
- -- Apply updates
87
- for i, key in ipairs(keys) do
88
- redis.call('DECRBY', key, tonumber(quantities[i]))
89
- end
90
-
91
- return 1
92
- LUA
93
- end
94
-
95
- def restock_redis_script
96
- <<~LUA
97
- local keys = KEYS
98
- local quantities = ARGV
99
-
100
- -- Apply restock updates
101
- for i, key in ipairs(keys) do
102
- redis.call('INCRBY', key, tonumber(quantities[i]))
103
- end
104
-
105
- return 1
106
- LUA
107
- end
108
-
109
- def schedule_sync_inventory(inventory_id_and_quantities)
110
- SpreeCmCommissioner::InventoryItemSyncerJob.perform_later(inventory_id_and_quantities:)
111
- end
112
- end
113
- end
114
- end