spree_cm_commissioner 1.11.0.pre.pre3 → 1.12.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/.github/workflows/test_and_build_gem.yml +143 -12
- data/.gitignore +1 -2
- data/Gemfile.lock +1 -22
- data/Rakefile +4 -33
- data/app/controllers/spree/admin/cms_pages_controller_decorator.rb +32 -0
- data/app/controllers/spree/admin/stock_managements_controller.rb +1 -62
- data/app/controllers/spree/api/v2/storefront/accommodations_controller.rb +31 -14
- data/app/controllers/spree/api/v2/storefront/queue_cart/line_items_controller.rb +2 -2
- data/app/controllers/spree/api/v2/storefront/waiting_room_sessions_controller.rb +1 -0
- data/app/controllers/spree/api/v2/tenant/account_checker_controller.rb +1 -1
- data/app/controllers/spree/api/v2/tenant/account_recovers_controller.rb +2 -2
- data/app/controllers/spree/api/v2/tenant/cms_pages_controller.rb +41 -0
- data/app/controllers/spree/api/v2/tenant/reset_passwords_controller.rb +1 -1
- data/app/controllers/spree/api/v2/tenant/waiting_room_sessions_controller.rb +30 -0
- data/app/controllers/spree_cm_commissioner/admin/variants_controller_decorator.rb +17 -0
- data/app/controllers/spree_cm_commissioner/api/v2/storefront/cms_pages_controller_decorator.rb +18 -0
- data/app/interactors/spree_cm_commissioner/account_recover.rb +2 -2
- data/app/interactors/spree_cm_commissioner/create_event.rb +7 -26
- data/app/interactors/spree_cm_commissioner/create_ticket.rb +95 -0
- data/app/interactors/spree_cm_commissioner/event_line_items_date_syncer.rb +19 -0
- data/app/interactors/spree_cm_commissioner/existing_account_checker.rb +1 -1
- data/app/interactors/spree_cm_commissioner/organizers_transactional_email_notifier.rb +27 -0
- data/app/interactors/spree_cm_commissioner/pin_code_sender.rb +3 -3
- data/app/interactors/spree_cm_commissioner/product_event_id_to_children_syncer.rb +15 -0
- data/app/interactors/spree_cm_commissioner/sms.rb +14 -0
- data/app/interactors/spree_cm_commissioner/telegram_debug_pin_code_sender.rb +2 -1
- data/app/interactors/spree_cm_commissioner/transactional_email_sender.rb +50 -0
- data/app/interactors/spree_cm_commissioner/user_forgotten_password_updater.rb +2 -1
- data/app/interactors/spree_cm_commissioner/user_password_authenticator.rb +4 -2
- data/app/interactors/spree_cm_commissioner/waiting_room_session_creator.rb +7 -14
- data/app/interactors/spree_cm_commissioner/waiting_room_session_firebase_logger.rb +30 -0
- data/app/jobs/spree_cm_commissioner/ensure_event_for_product_line_item_guests_job.rb +13 -0
- data/app/jobs/spree_cm_commissioner/event_line_items_date_syncer_job.rb +8 -0
- data/app/jobs/spree_cm_commissioner/product_event_id_to_children_syncer_job.rb +8 -0
- data/app/jobs/spree_cm_commissioner/telegram_debug_pin_code_sender_job.rb +3 -1
- data/app/jobs/spree_cm_commissioner/waiting_room_session_firebase_logger_job.rb +13 -0
- data/app/mailers/spree_cm_commissioner/event_transactional_mailer.rb +23 -0
- data/app/mailers/spree_cm_commissioner/pin_code_mailer.rb +1 -0
- data/app/models/concerns/spree_cm_commissioner/kyc_bitwise.rb +2 -0
- data/app/models/concerns/spree_cm_commissioner/line_item_durationable.rb +10 -6
- data/app/models/concerns/spree_cm_commissioner/order_state_machine.rb +14 -26
- data/app/models/concerns/spree_cm_commissioner/product_delegation.rb +4 -3
- data/app/models/concerns/spree_cm_commissioner/product_type.rb +0 -10
- data/app/models/concerns/spree_cm_commissioner/user_identity.rb +7 -4
- data/app/models/concerns/spree_cm_commissioner/variant_options_concern.rb +8 -10
- data/app/models/spree_cm_commissioner/cms_page_decorator.rb +9 -0
- data/app/models/spree_cm_commissioner/event_ticket_google_wallet.rb +2 -2
- data/app/models/spree_cm_commissioner/guest.rb +1 -1
- data/app/models/spree_cm_commissioner/line_item_decorator.rb +10 -16
- data/app/models/spree_cm_commissioner/option_type_decorator.rb +6 -0
- data/app/models/spree_cm_commissioner/order_decorator.rb +0 -15
- data/app/models/spree_cm_commissioner/product_decorator.rb +17 -14
- data/app/models/spree_cm_commissioner/role_decorator.rb +3 -0
- data/app/models/spree_cm_commissioner/stock/availability_checker.rb +25 -27
- data/app/models/spree_cm_commissioner/stock/availability_validator_decorator.rb +1 -2
- data/app/models/spree_cm_commissioner/stock/line_item_availability_checker.rb +3 -3
- data/app/models/spree_cm_commissioner/stock_item_decorator.rb +0 -14
- data/app/models/spree_cm_commissioner/taxon_decorator.rb +24 -3
- data/app/models/spree_cm_commissioner/transactional_email.rb +6 -0
- data/app/models/spree_cm_commissioner/user_decorator.rb +6 -0
- data/app/models/spree_cm_commissioner/variant_decorator.rb +27 -34
- data/app/models/spree_cm_commissioner/vehicle.rb +0 -7
- data/app/models/spree_cm_commissioner/vendor_decorator.rb +9 -1
- data/app/overrides/spree/admin/cms_pages/_form/tenant_fields.html.erb.deface +9 -0
- data/app/overrides/spree/admin/cms_pages/index/cms_pages_tabs.html.erb.deface +21 -0
- data/app/overrides/spree/admin/taxons/_form/assets_form.html.erb.deface +2 -2
- data/app/overrides/spree/admin/taxons/_form/available_on.html.erb.deface +3 -1
- data/app/overrides/spree/admin/taxons/_form/background_color_and_foreground_color.html.erb.deface +3 -1
- data/app/overrides/spree/admin/taxons/_form/custom_redirect_url.html.erb.deface +3 -1
- data/app/overrides/spree/admin/taxons/_form/hide_video_banner.html.erb.deface +3 -1
- data/app/overrides/spree/admin/taxons/_form/purchasable_on_status.html.erb.deface +3 -1
- data/app/overrides/spree/admin/taxons/_form/show_badge_status.html.erb.deface +3 -1
- data/app/overrides/spree/admin/taxons/_form/to_date_form_date.html.erb.deface +3 -4
- data/app/overrides/spree/admin/users/_form/roles_fields.html.erb.deface +1 -1
- data/app/overrides/spree/admin/users/index/body.html.erb.deface +3 -0
- data/app/overrides/spree/admin/users/index/headers.html.erb.deface +3 -0
- data/app/overrides/spree/admin/variants/_form/kyc_field.html.erb.deface +40 -0
- data/app/overrides/spree/admin/variants/edit/variant_status.html.erb.deface +6 -3
- data/app/queries/spree_cm_commissioner/variant_availability/non_permanent_stock_query.rb +45 -0
- data/app/queries/spree_cm_commissioner/variant_availability/permanent_stock_query.rb +55 -0
- data/app/request_schemas/spree_cm_commissioner/accommodation_request_schema.rb +0 -3
- data/app/request_schemas/spree_cm_commissioner/application_request_schema.rb +1 -1
- data/app/serializers/spree/v2/storefront/accommodation_serializer.rb +0 -2
- data/app/serializers/spree/v2/storefront/taxon_serializer_decorator.rb +2 -0
- data/app/serializers/spree/v2/tenant/waiting_room_session_serializer.rb +9 -0
- data/app/services/spree_cm_commissioner/user_authenticator.rb +3 -1
- data/app/services/spree_cm_commissioner/user_roles_assigner.rb +62 -0
- data/app/views/spree/admin/shared/_cms_pages_tabs.html.erb +20 -0
- data/app/views/spree/admin/shared/_taxon_tabs.html.erb +19 -19
- data/app/views/spree/admin/stock_managements/_variant_stock_items.html.erb +1 -3
- data/app/views/spree/admin/stock_managements/index.html.erb +5 -40
- data/app/views/spree/shared/_base_mailer_header.html.erb +10 -2
- data/app/views/spree_cm_commissioner/event_transactional_mailer/_event_banner.html.erb +3 -0
- data/app/views/spree_cm_commissioner/event_transactional_mailer/_mailer_stylesheets.html.erb +315 -0
- data/app/views/spree_cm_commissioner/event_transactional_mailer/_note.html.erb +8 -0
- data/app/views/spree_cm_commissioner/event_transactional_mailer/_share_button.html.erb +3 -0
- data/app/views/spree_cm_commissioner/event_transactional_mailer/send_to_organizer.html.erb +59 -0
- data/app/views/spree_cm_commissioner/event_transactional_mailer/send_to_participant.html.erb +52 -0
- data/app/views/spree_cm_commissioner/layouts/event_transactional_mailer.html.erb +14 -0
- data/config/initializers/spree_permitted_attributes.rb +0 -5
- data/config/locales/en.yml +36 -0
- data/config/locales/km.yml +2 -0
- data/config/routes.rb +5 -11
- data/db/migrate/20250509033437_create_spree_cm_commissioner_transactional_emails.rb +12 -0
- data/db/migrate/20250509075429_add_max_order_quantity_to_spree_product.rb +5 -0
- data/db/migrate/20250512075319_add_tenant_id_to_spree_cms_pages.rb +6 -0
- data/db/migrate/20250520042602_add_event_to_spree_products.rb +7 -0
- data/db/migrate/20250520044533_add_event_to_spree_line_items.rb +7 -0
- data/db/migrate/20250521024345_add_tenant_id_to_cm_waiting_room_sessions.rb +6 -0
- data/db/migrate/20250521095539_add_kyc_to_spree_variants.rb +5 -0
- data/docker-compose.yml +1 -1
- data/lib/generators/spree_cm_commissioner/install/install_generator.rb +3 -11
- data/lib/generators/spree_cm_commissioner/install/templates/app/javascript/{spree_dashboard/spree_cm_commissioner → spree_cm_commissioner}/utilities.js +0 -4
- data/lib/spree_cm_commissioner/calendar_event.rb +1 -11
- data/lib/spree_cm_commissioner/test_helper/factories/homepage_section_relatable_factory.rb +1 -1
- data/lib/spree_cm_commissioner/test_helper/factories/line_item_factory.rb +1 -1
- data/lib/spree_cm_commissioner/test_helper/factories/product_factory.rb +5 -18
- data/lib/spree_cm_commissioner/test_helper/factories/role.rb +7 -0
- data/lib/spree_cm_commissioner/test_helper/factories/stock_location_factory.rb +2 -2
- data/lib/spree_cm_commissioner/test_helper/factories/taxon_home_banner_factory.rb +5 -0
- data/lib/spree_cm_commissioner/test_helper/factories/transactional_email_factory.rb +6 -0
- data/lib/spree_cm_commissioner/test_helper/factories/variant_factory.rb +6 -41
- data/lib/spree_cm_commissioner/test_helper/factories/vendor_factory.rb +1 -1
- data/lib/spree_cm_commissioner/version.rb +1 -1
- data/lib/spree_cm_commissioner.rb +0 -34
- data/lib/tasks/ensure_event_for_product_line_item_guests.rake +7 -0
- data/lib/tasks/update_invalid_self_root_places.rake +9 -0
- data/lib/tasks/update_orphan_root_places.rake +1 -0
- data/spree_cm_commissioner.gemspec +0 -5
- metadata +49 -82
- data/app/controllers/spree/api/v2/storefront/accommodations/variants_controller.rb +0 -42
- data/app/finders/spree_cm_commissioner/accommodations/find.rb +0 -40
- data/app/finders/spree_cm_commissioner/accommodations/find_variant.rb +0 -35
- data/app/interactors/spree_cm_commissioner/ensure_correct_product_type.rb +0 -40
- data/app/interactors/spree_cm_commissioner/inventory_item_syncer.rb +0 -25
- data/app/interactors/spree_cm_commissioner/stock/inventory_items_adjuster.rb +0 -13
- data/app/interactors/spree_cm_commissioner/stock/inventory_items_generator.rb +0 -15
- data/app/interactors/spree_cm_commissioner/stock/permanent_inventory_items_generator.rb +0 -75
- data/app/interactors/spree_cm_commissioner/stock/stock_movement_creator.rb +0 -24
- data/app/interactors/spree_cm_commissioner/user_roles_assigner.rb +0 -22
- data/app/jobs/spree_cm_commissioner/ensure_correct_product_type_job.rb +0 -7
- data/app/jobs/spree_cm_commissioner/inventory_item_syncer_job.rb +0 -7
- data/app/jobs/spree_cm_commissioner/stock/inventory_items_adjuster_job.rb +0 -11
- data/app/jobs/spree_cm_commissioner/stock/inventory_items_generator_job.rb +0 -11
- data/app/jobs/spree_cm_commissioner/stock/permanent_inventory_items_generator_job.rb +0 -9
- data/app/models/spree_cm_commissioner/inventory.rb +0 -11
- data/app/models/spree_cm_commissioner/inventory_item.rb +0 -56
- data/app/models/spree_cm_commissioner/redis_stock/cached_inventory_items_builder.rb +0 -40
- data/app/models/spree_cm_commissioner/redis_stock/inventory_updater.rb +0 -126
- data/app/models/spree_cm_commissioner/redis_stock/line_items_cached_inventory_items_builder.rb +0 -36
- data/app/models/spree_cm_commissioner/redis_stock/variant_cached_inventory_items_builder.rb +0 -27
- data/app/models/spree_cm_commissioner/stock/order_availability_checker.rb +0 -44
- data/app/request_schemas/spree_cm_commissioner/variant_request_schema.rb +0 -19
- data/app/views/spree/admin/stock_managements/_events_popover.html.erb +0 -23
- data/app/views/spree/admin/stock_managements/calendar.html.erb +0 -35
- data/db/migrate/20250304293518_create_cm_inventory_items.rb +0 -21
- data/db/migrate/20250429094228_add_lock_version_to_cm_inventory_items.rb +0 -5
- data/db/migrate/20250502025848_add_index_to_spree_products.rb +0 -5
- data/db/migrate/20250502030001_add_product_type_to_spree_variants.rb +0 -5
- data/db/migrate/20250502030002_add_product_type_to_spree_line_items.rb +0 -5
- data/lib/spree_cm_commissioner/cached_inventory_item.rb +0 -23
- data/lib/spree_cm_commissioner/test_helper/factories/inventory_item_factory.rb +0 -9
- data/lib/tasks/create_default_non_permanent_inventory_items.rake +0 -16
- data/lib/tasks/ensure_correct_product_type.rake +0 -7
- data/lib/tasks/generate_inventory_items.rake +0 -7
@@ -134,6 +134,12 @@ module SpreeCmCommissioner
|
|
134
134
|
def update_otp_enabled
|
135
135
|
self.otp_enabled = otp_email || otp_phone_number
|
136
136
|
end
|
137
|
+
|
138
|
+
def update_tracked_fields!(request)
|
139
|
+
ActiveRecord::Base.connected_to(role: :writing) do
|
140
|
+
super(request)
|
141
|
+
end
|
142
|
+
end
|
137
143
|
end
|
138
144
|
end
|
139
145
|
|
@@ -1,14 +1,16 @@
|
|
1
1
|
module SpreeCmCommissioner
|
2
2
|
module VariantDecorator
|
3
|
-
def self.prepended(base)
|
4
|
-
base.include SpreeCmCommissioner::ProductType
|
3
|
+
def self.prepended(base)
|
5
4
|
base.include SpreeCmCommissioner::ProductDelegation
|
6
5
|
base.include SpreeCmCommissioner::VariantOptionsConcern
|
6
|
+
base.include SpreeCmCommissioner::KycBitwise
|
7
|
+
|
7
8
|
base.after_commit :update_vendor_price
|
8
9
|
base.validate :validate_option_types
|
9
10
|
base.before_save -> { self.track_inventory = false }, if: :subscribable?
|
10
11
|
|
11
12
|
base.belongs_to :vendor, class_name: 'Spree::Vendor'
|
13
|
+
base.has_one :event, class_name: 'Spree::Taxon', through: :product
|
12
14
|
|
13
15
|
base.has_many :taxons, class_name: 'Spree::Taxon', through: :product
|
14
16
|
base.has_many :visible_option_values, lambda {
|
@@ -21,19 +23,11 @@ module SpreeCmCommissioner
|
|
21
23
|
base.has_many :variant_guest_card_class, class_name: 'SpreeCmCommissioner::VariantGuestCardClass'
|
22
24
|
base.has_many :guest_card_classes, class_name: 'SpreeCmCommissioner::GuestCardClass', through: :variant_guest_card_class
|
23
25
|
|
24
|
-
base.has_many :inventory_items, class_name: 'SpreeCmCommissioner::InventoryItem'
|
25
|
-
|
26
26
|
base.scope :subscribable, -> { active.joins(:product).where(product: { subscribable: true, status: :active }) }
|
27
|
-
base.scope :with_permanent_stock, -> { where(product_type: base::PERMANENT_STOCK_PRODUCT_TYPES) }
|
28
|
-
base.scope :with_non_permanent_stock, -> { where.not(product_type: base::PERMANENT_STOCK_PRODUCT_TYPES) }
|
29
|
-
|
30
27
|
base.has_one :trip,
|
31
28
|
class_name: 'SpreeCmCommissioner::Trip'
|
32
29
|
base.has_many :trip_stops, class_name: 'SpreeCmCommissioner::TripStop', dependent: :destroy, foreign_key: :trip_id
|
33
30
|
base.accepts_nested_attributes_for :option_values
|
34
|
-
|
35
|
-
base.before_save -> { self.product_type = product.product_type }, if: -> { product_type.nil? }
|
36
|
-
|
37
31
|
base.after_commit :sync_trip, if: :transit?
|
38
32
|
base.accepts_nested_attributes_for :trip_stops, allow_destroy: true
|
39
33
|
base.after_commit :create_trip_stops, if: :transit?
|
@@ -59,24 +53,8 @@ module SpreeCmCommissioner
|
|
59
53
|
super || product.discontinued?
|
60
54
|
end
|
61
55
|
|
62
|
-
def
|
63
|
-
|
64
|
-
end
|
65
|
-
|
66
|
-
def default_inventory_item_exist?
|
67
|
-
inventory_items.exists?(inventory_date: nil)
|
68
|
-
end
|
69
|
-
|
70
|
-
def create_default_non_permanent_inventory_item!(quantity_available: nil, max_capacity: nil)
|
71
|
-
return if product_type.blank? # handle in case product not exist for variant.
|
72
|
-
return unless should_track_inventory?
|
73
|
-
return if default_inventory_item_exist?
|
74
|
-
|
75
|
-
inventory_items.create!(
|
76
|
-
product_type: product_type,
|
77
|
-
quantity_available: [0, quantity_available || total_on_hand].max,
|
78
|
-
max_capacity: [0, max_capacity || total_on_hand].max
|
79
|
-
)
|
56
|
+
def permanent_stock?
|
57
|
+
accommodation?
|
80
58
|
end
|
81
59
|
|
82
60
|
# override
|
@@ -94,18 +72,33 @@ module SpreeCmCommissioner
|
|
94
72
|
"#{display_sku} - #{display_price}"
|
95
73
|
end
|
96
74
|
|
75
|
+
def transit?
|
76
|
+
product.product_type == 'transit'
|
77
|
+
end
|
78
|
+
|
97
79
|
# override
|
98
|
-
def in_stock?
|
99
|
-
|
80
|
+
def in_stock?
|
81
|
+
available_quantity.positive?
|
100
82
|
end
|
101
83
|
|
102
84
|
private
|
103
85
|
|
86
|
+
def total_purchases
|
87
|
+
Spree::LineItem.complete.where(variant_id: id).sum(:quantity).to_i
|
88
|
+
end
|
89
|
+
|
90
|
+
def available_quantity
|
91
|
+
stock_count = stock_items.sum(&:count_on_hand)
|
92
|
+
return stock_count if delivery_required?
|
93
|
+
|
94
|
+
stock_count - total_purchases
|
95
|
+
end
|
96
|
+
|
104
97
|
def update_vendor_price
|
105
|
-
return unless vendor.present? && product_type == vendor&.primary_product_type
|
98
|
+
return unless vendor.present? && product&.product_type == vendor&.primary_product_type
|
106
99
|
|
107
|
-
vendor.update(min_price: price) if price < vendor.min_price
|
108
|
-
vendor.update(max_price: price) if price > vendor.max_price
|
100
|
+
vendor.update(min_price: price) if vendor.min_price.nil? || price < vendor.min_price
|
101
|
+
vendor.update(max_price: price) if vendor.max_price.nil? || price > vendor.max_price
|
109
102
|
end
|
110
103
|
|
111
104
|
def validate_option_types
|
@@ -128,7 +121,7 @@ module SpreeCmCommissioner
|
|
128
121
|
end
|
129
122
|
|
130
123
|
def sync_trip
|
131
|
-
return unless transit
|
124
|
+
return unless product.product_type == 'transit'
|
132
125
|
|
133
126
|
trip = SpreeCmCommissioner::Trip.find_or_initialize_by(variant_id: id)
|
134
127
|
|
@@ -8,7 +8,6 @@ module SpreeCmCommissioner
|
|
8
8
|
has_one :primary_photo, -> { order(position: :asc) }, class_name: 'SpreeCmCommissioner::VehiclePhoto', as: :viewable, dependent: :destroy
|
9
9
|
belongs_to :vendor, class_name: 'Spree::Vendor'
|
10
10
|
|
11
|
-
before_save :set_attributes
|
12
11
|
after_commit :create_vehicle_option_value
|
13
12
|
|
14
13
|
has_many :vehicle_photo, class_name: 'SpreeCmCommissioner::VehiclePhoto', as: :viewable, dependent: :destroy
|
@@ -17,12 +16,6 @@ module SpreeCmCommissioner
|
|
17
16
|
validates :code, uniqueness: { scope: :vendor_id }, presence: true
|
18
17
|
validates :license_plate, uniqueness: {}, allow_blank: true
|
19
18
|
|
20
|
-
def set_attributes
|
21
|
-
self.route_type = vehicle_type.route_type
|
22
|
-
self.number_of_seats = vehicle_type.vehicle_seats_count
|
23
|
-
self.allow_seat_selection = vehicle_type.allow_seat_selection
|
24
|
-
end
|
25
|
-
|
26
19
|
def create_vehicle_option_value
|
27
20
|
SpreeCmCommissioner::VehicleOptionValueCreator.call(self)
|
28
21
|
end
|
@@ -79,7 +79,8 @@ module SpreeCmCommissioner
|
|
79
79
|
dependent: :destroy, inverse_of: :relatable
|
80
80
|
|
81
81
|
base.has_many :vehicle_types, class_name: 'SpreeCmCommissioner::VehicleType', dependent: :destroy
|
82
|
-
base.has_many :vehicles,
|
82
|
+
base.has_many :vehicles, class_name: 'SpreeCmCommissioner::Vehicle', dependent: :destroy
|
83
|
+
# base.has_many :vehicles, through: :vehicle_types, class_name: 'SpreeCmCommissioner::Vehicle', dependent: :destroy
|
83
84
|
|
84
85
|
base.validates :account_name, :account_number, presence: true, if: lambda {
|
85
86
|
payment_qrcode.present? && Spree::Store.default.code.include?('billing')
|
@@ -181,6 +182,13 @@ module SpreeCmCommissioner
|
|
181
182
|
def organizer_url
|
182
183
|
"#{Spree::Store.default.formatted_url}/organizers/#{slug}"
|
183
184
|
end
|
185
|
+
|
186
|
+
def vendor_rules
|
187
|
+
rules_option_type = Spree::OptionType.rules_option_type
|
188
|
+
return vendor_kind_option_values.none if rules_option_type.nil?
|
189
|
+
|
190
|
+
vendor_kind_option_values.where(option_type_id: rules_option_type.id)
|
191
|
+
end
|
184
192
|
end
|
185
193
|
end
|
186
194
|
|
@@ -0,0 +1,9 @@
|
|
1
|
+
<!-- insert_before "erb[loud]:contains('f.field_container :title')" -->
|
2
|
+
|
3
|
+
<%= f.field_container :tenant_id, class: ['col-12'] do %>
|
4
|
+
<%= f.label :tenant_id, raw(Spree.t(:tenant) + ' (optional)') %>
|
5
|
+
<%= f.collection_select :tenant_id, SpreeCmCommissioner::Tenant.all, :id, :name,
|
6
|
+
{ prompt: Spree.t('select_tenant'), include_blank: Spree.t('default_store') },
|
7
|
+
{ class: 'form-control select2' } %>
|
8
|
+
<%= f.error_message_on :tenant_id %>
|
9
|
+
<% end %>
|
@@ -0,0 +1,21 @@
|
|
1
|
+
<!-- insert_before "erb[silent]:contains('content_for :page_actions')" -->
|
2
|
+
|
3
|
+
<%= render partial: 'spree/admin/shared/cms_pages_tabs' %>
|
4
|
+
|
5
|
+
<% if params[:tab] == 'default' %>
|
6
|
+
<div class="alert alert-info mb-3">
|
7
|
+
<%= svg_icon name: "info-circle.svg", classes: 'mr-2', width: '16', height: '16' %>
|
8
|
+
CMS Pages for the default store. These pages are shared globally and are not tied to any specific tenant.
|
9
|
+
</div>
|
10
|
+
<% elsif params[:tab] == 'tenants' && params[:tenant_id].present? %>
|
11
|
+
<div class="alert alert-info mb-3">
|
12
|
+
<%= svg_icon name: "info-circle.svg", classes: 'mr-2', width: '16', height: '16' %>
|
13
|
+
CMS Pages for the tenant: <strong><%= SpreeCmCommissioner::Tenant.find(params[:tenant_id]).name %></strong>.
|
14
|
+
These pages are displayed only to users associated with this tenant.
|
15
|
+
</div>
|
16
|
+
<% elsif params[:tab] == 'tenants' %>
|
17
|
+
<div class="alert alert-info mb-3">
|
18
|
+
<%= svg_icon name: "info-circle.svg", classes: 'mr-2', width: '16', height: '16' %>
|
19
|
+
CMS Pages for all tenants. These pages are displayed only to users associated with specific tenants.
|
20
|
+
</div>
|
21
|
+
<% end %>
|
@@ -1,7 +1,8 @@
|
|
1
1
|
<!-- replace "erb[loud]:contains('assets_form')" -->
|
2
2
|
|
3
|
+
<%# Sections don't use assets, so we hide the form here to avoid confusing admin. %>
|
3
4
|
|
4
|
-
<div class="row">
|
5
|
+
<div class="row <%= "d-none" unless @taxon.depth == 1 %>">
|
5
6
|
<%# "@taxon.icon is not used yet" %>
|
6
7
|
<%# render 'shared/asset_field',
|
7
8
|
field: :icon,
|
@@ -67,4 +68,3 @@
|
|
67
68
|
<% end %>
|
68
69
|
<% end %>
|
69
70
|
</div>
|
70
|
-
|
@@ -1,6 +1,8 @@
|
|
1
1
|
<!-- insert_before "erb[loud]:contains('field_container :parent_id')" -->
|
2
2
|
|
3
|
-
|
3
|
+
<%# Sections don't use available_on, so we hide the form here to avoid confusing admin. %>
|
4
|
+
|
5
|
+
<div class="form-group <%= "d-none" unless @taxon.depth == 1 %>">
|
4
6
|
<%= label_tag nil, Spree.t(:available_on) %>
|
5
7
|
<div class="input-group datePickerFrom"
|
6
8
|
data-wrap="true"
|
data/app/overrides/spree/admin/taxons/_form/background_color_and_foreground_color.html.erb.deface
CHANGED
@@ -1,6 +1,8 @@
|
|
1
1
|
<!-- insert_before "erb[loud]:contains('field_container :meta_title')" -->
|
2
2
|
|
3
|
-
|
3
|
+
<%# Sections don't use colors, so we hide the form here to avoid confusing admin. %>
|
4
|
+
|
5
|
+
<div class="row <%= "d-none" unless @taxon.depth == 1 %>">
|
4
6
|
<div class="col-md-6">
|
5
7
|
<%= f.label :preferred_background_color, Spree.t('background_color'), class: 'form-label' %>
|
6
8
|
<%= f.text_field :preferred_background_color, class: 'form-control color-picker', placeholder: '#FFFFFF', value: @object.preferred_background_color %>
|
@@ -1,6 +1,8 @@
|
|
1
1
|
<!-- insert_after "erb[loud]:contains('field_container :permalink')" -->
|
2
2
|
|
3
|
+
<%# Sections don't use custom_redirect_url, so we hide the form here to avoid confusing admin. %>
|
4
|
+
|
3
5
|
<%= f.field_container :custom_redirect_url do %>
|
4
6
|
<%= f.label :custom_redirect_url, Spree.t(:custom_redirect_url) %>
|
5
7
|
<%= f.text_field :custom_redirect_url, class: 'form-control', rows: 6 %>
|
6
|
-
<% end %>
|
8
|
+
<% end if @taxon.depth == 1 %>
|
@@ -1,7 +1,9 @@
|
|
1
1
|
<!-- insert_before "erb[loud]:contains('field_container :hide_from_nav')" -->
|
2
2
|
|
3
|
+
<%# Sections don't use video banner, so we hide the form here to avoid confusing admin. %>
|
4
|
+
|
3
5
|
<%= f.field_container :hide_video_banner, class: ['custom-control', 'custom-checkbox', 'my-4'] do %>
|
4
6
|
<%= f.check_box :hide_video_banner, class: 'custom-control-input' %>
|
5
7
|
<%= f.label :hide_video_banner, Spree.t(:hide_video_banner), class: 'custom-control-label' %>
|
6
8
|
<%= f.error_message_on :hide_video_banner %>
|
7
|
-
<% end %>
|
9
|
+
<% end if @taxon.depth == 1 %> %>
|
@@ -1,5 +1,7 @@
|
|
1
1
|
<!-- insert_before "erb[loud]:contains('field_container :parent_id')" -->
|
2
2
|
|
3
|
+
<%# Sections don't use purchasable_on, so we hide the form here to avoid confusing admin. %>
|
4
|
+
|
3
5
|
<%= f.field_container :purchasable_on do %>
|
4
6
|
<%= f.label :purchasable_on, Spree.t('purchasable_on'), class: 'form-label' %>
|
5
7
|
<%= f.select :purchasable_on,
|
@@ -7,4 +9,4 @@
|
|
7
9
|
{ },
|
8
10
|
{ class: 'select2 form-control' } %>
|
9
11
|
<%= f.error_message_on :purchasable_on, class: 'text-danger' %>
|
10
|
-
<% end %>
|
12
|
+
<% end if @taxon.depth == 1 %>
|
@@ -1,5 +1,7 @@
|
|
1
1
|
<!-- insert_before "erb[loud]:contains('field_container :parent_id')" -->
|
2
2
|
|
3
|
+
<%# Sections don't use show_badge_status, so we hide the form here to avoid confusing admin. %>
|
4
|
+
|
3
5
|
<%= f.field_container :show_badge_status do %>
|
4
6
|
<%= f.label :show_badge_status, Spree.t('show_badge_status'), class: 'form-label' %>
|
5
7
|
<%= f.select :show_badge_status,
|
@@ -7,5 +9,5 @@
|
|
7
9
|
{ },
|
8
10
|
{ class: 'select2 form-control' } %>
|
9
11
|
<%= f.error_message_on :show_badge_status, class: 'text-danger' %>
|
10
|
-
<% end %>
|
12
|
+
<% end if @taxon.depth == 1 %>
|
11
13
|
|
@@ -1,6 +1,8 @@
|
|
1
1
|
<!-- insert_after "erb[loud]:contains('field_container :permalink')" -->
|
2
2
|
|
3
|
-
|
3
|
+
<%# Beside event, from_date & to_date aren't used inside the system elsewhere. Hide them from UI to avoid confusion %>
|
4
|
+
|
5
|
+
<div class="form-group date-range-filter <%= "d-none" unless @object.event? && @object.depth == 1 %>">
|
4
6
|
<div class="date-range-filter row">
|
5
7
|
<div class="col-12 col-md-6 mb-3 mb-md-0">
|
6
8
|
<%= label_tag nil, Spree.t(:from_date) %>
|
@@ -35,6 +37,3 @@
|
|
35
37
|
</div>
|
36
38
|
</div>
|
37
39
|
</div>
|
38
|
-
|
39
|
-
|
40
|
-
|
@@ -1,2 +1,2 @@
|
|
1
1
|
<!-- replace 'erb[loud]:contains("f.collection_check_boxes :spree_role_ids")' -->
|
2
|
-
<%= f.collection_check_boxes :spree_role_ids, Spree::Role.non_vendor, :id, :name do |role_form| %>
|
2
|
+
<%= f.collection_check_boxes :spree_role_ids, Spree::Role.non_vendor, :id, :name do |role_form| %>
|
@@ -19,6 +19,9 @@
|
|
19
19
|
<th>
|
20
20
|
<%= sort_link @search, :phone_number, I18n.t('activerecord.attributes.spree/order.phone_number'), {}, {title: 'phone_number_title'} %>
|
21
21
|
</th>
|
22
|
+
<th>
|
23
|
+
<%= Spree.t(:tenant) %>
|
24
|
+
</th>
|
22
25
|
<th>
|
23
26
|
<%= sort_link @search, :created_at, Spree.t(:create_at), {}, {title: 'create_at_title'} %>
|
24
27
|
</th>
|
@@ -0,0 +1,40 @@
|
|
1
|
+
<!-- insert_bottom "[data-hook='admin_variant_form_additional_fields']" -->
|
2
|
+
|
3
|
+
<p>Guest Information Fields</p>
|
4
|
+
|
5
|
+
<div class="form-check mb-3">
|
6
|
+
<%= f.check_box :use_product_kyc, id: "toggleGuestInfo", class: 'form-check-input mr-2', checked: (@variant.kyc == nil) %>
|
7
|
+
<label for="toggleGuestInfo" class="form-check-label">
|
8
|
+
Use Product KYC
|
9
|
+
</label>
|
10
|
+
</div>
|
11
|
+
|
12
|
+
<div id="guestInfoForm" <% if @variant.kyc == nil %>style="display: none;"<% end %>">
|
13
|
+
<small class="form-text text-muted mb-4">
|
14
|
+
<%= raw I18n.t('kyc.variant_note') %>
|
15
|
+
</small>
|
16
|
+
<div class="row row-cols-2 row-cols-md-3">
|
17
|
+
<% @variant.class::BIT_FIELDS.each do |key, value| %>
|
18
|
+
<div class="col">
|
19
|
+
<div class="form-check form-check-inline">
|
20
|
+
<%= f.field_container key do %>
|
21
|
+
<%= f.check_box key, class: 'form-check-input', checked: @variant.kyc_value_enabled?(value) %>
|
22
|
+
<%= f.label key, key.to_s.sub(/^guest_/, '').titleize, class: 'form-check-label' %>
|
23
|
+
<%= f.error_message_on key, class: 'text-danger' %>
|
24
|
+
<% end %>
|
25
|
+
</div>
|
26
|
+
</div>
|
27
|
+
<% end %>
|
28
|
+
</div>
|
29
|
+
</div>
|
30
|
+
|
31
|
+
<script>
|
32
|
+
document.addEventListener("turbo:load", function () {
|
33
|
+
const checkbox = document.getElementById("toggleGuestInfo");
|
34
|
+
const guestForm = document.getElementById("guestInfoForm");
|
35
|
+
|
36
|
+
checkbox.addEventListener("change", function () {
|
37
|
+
guestForm.style.display = this.checked ? "none" : "block";
|
38
|
+
});
|
39
|
+
});
|
40
|
+
</script>
|
@@ -2,12 +2,15 @@
|
|
2
2
|
|
3
3
|
<% unless f.object.accommodation? %>
|
4
4
|
<div class="m-3 mb-0">
|
5
|
-
<%
|
5
|
+
<% from_date = f.object.start_date_time || f.object.event&.from_date %>
|
6
|
+
<% to_date = f.object.end_date_time || f.object.event&.to_date %>
|
7
|
+
|
8
|
+
<% valid_duration = from_date.present? && to_date.present? %>
|
6
9
|
<% alert_class = valid_duration ? 'alert-success' : 'alert-warning' %>
|
7
10
|
|
8
11
|
<div class="alert <%= alert_class %> mb-0">
|
9
12
|
<%= svg_icon(name: valid_duration ? "check2-circle.svg" : 'cancel.svg', width: '16', height: '16') %>
|
10
|
-
This variant have start date: <strong><%= pretty_time(
|
13
|
+
This variant have start date: <strong><%= pretty_time(from_date).presence || 'N/A' %></strong> and end date: <strong><%= pretty_time(to_date).presence || 'N/A' %></strong>
|
11
14
|
</div>
|
12
15
|
|
13
16
|
<div class="mb-1"></div>
|
@@ -16,7 +19,7 @@
|
|
16
19
|
<% option_types = Spree::OptionType.where(name: ["start-date", "end-date", "start-time", "end-time", "reminder-in-hours", "duration-in-hours", "duration-in-minutes", "duration-in-seconds"]) %>
|
17
20
|
<% event_link = f.object.event.present? ? edit_admin_taxonomy_taxon_url(f.object.event.taxonomy.id, f.object.event.id) : edit_admin_product_url(f.object.product) %>
|
18
21
|
|
19
|
-
Duration can be set by either adding <%= link_to 'event
|
22
|
+
Duration can be set by either adding <%= link_to 'event date', event_link, target: '_blank' %> or add option type such as <%= option_types.pluck(:presentation).to_sentence %>
|
20
23
|
</small>
|
21
24
|
</div>
|
22
25
|
<% end %>
|
@@ -0,0 +1,45 @@
|
|
1
|
+
module SpreeCmCommissioner
|
2
|
+
module VariantAvailability
|
3
|
+
class NonPermanentStockQuery
|
4
|
+
attr_reader :variant, :except_line_item_id, :error_message
|
5
|
+
|
6
|
+
def initialize(variant:, except_line_item_id: nil)
|
7
|
+
@variant = variant
|
8
|
+
@except_line_item_id = except_line_item_id
|
9
|
+
@error_message = nil
|
10
|
+
end
|
11
|
+
|
12
|
+
def available?(quantity)
|
13
|
+
reserve_variants =
|
14
|
+
Spree::LineItem
|
15
|
+
.complete
|
16
|
+
.select('(SUM(DISTINCT spree_stock_items.count_on_hand) - SUM(spree_line_items.quantity)) AS available_quantity')
|
17
|
+
.joins(variant: :stock_items)
|
18
|
+
.where(variant_id: variant.id)
|
19
|
+
.where.not(id: except_line_item_id)
|
20
|
+
.group(:variant_id)
|
21
|
+
|
22
|
+
# there is a case when variant does not have any purchaces yet, it will return empty & always available true.
|
23
|
+
# in this case, we check with stock items directly.
|
24
|
+
|
25
|
+
available_quantity = if reserve_variants.any?
|
26
|
+
reserve_variants.sum(&:available_quantity)
|
27
|
+
else
|
28
|
+
variant.stock_items.sum(:count_on_hand)
|
29
|
+
end
|
30
|
+
if available_quantity >= quantity
|
31
|
+
true
|
32
|
+
elsif available_quantity == 1
|
33
|
+
@error_message = I18n.t('variant_availability.item_available_instock')
|
34
|
+
false
|
35
|
+
elsif available_quantity <= 0
|
36
|
+
@error_message = I18n.t('variant_availability.items_out_of_stock')
|
37
|
+
false
|
38
|
+
else
|
39
|
+
@error_message = I18n.t('variant_availability.items_available_instock', available_quantity: available_quantity)
|
40
|
+
false
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
module SpreeCmCommissioner
|
2
|
+
module VariantAvailability
|
3
|
+
class PermanentStockQuery
|
4
|
+
attr_reader :variant, :from_date, :to_date, :except_line_item_id
|
5
|
+
|
6
|
+
def initialize(variant:, from_date:, to_date:, except_line_item_id: nil)
|
7
|
+
@variant = variant
|
8
|
+
@from_date = from_date
|
9
|
+
@to_date = to_date
|
10
|
+
@except_line_item_id = except_line_item_id
|
11
|
+
end
|
12
|
+
|
13
|
+
def available?(quantity)
|
14
|
+
(from_date..from_date).all? do |booking_date|
|
15
|
+
booked_date_quantity[booking_date].nil? ||
|
16
|
+
(booked_date_quantity[booking_date] - quantity) >= 0
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def booked_date_quantity
|
21
|
+
dates_sql = ApplicationRecord.sanitize_sql_array(
|
22
|
+
[
|
23
|
+
'SELECT date FROM generate_series(?::date, ?::date, ?) AS date',
|
24
|
+
from_date,
|
25
|
+
to_date,
|
26
|
+
date_interval
|
27
|
+
]
|
28
|
+
)
|
29
|
+
|
30
|
+
@booked_variants ||=
|
31
|
+
Spree::LineItem
|
32
|
+
.complete
|
33
|
+
.select(
|
34
|
+
'(SUM(DISTINCT spree_stock_items.count_on_hand) - SUM(spree_line_items.quantity)) AS available_quantity',
|
35
|
+
'dates.date AS reservation_date'
|
36
|
+
)
|
37
|
+
.joins(variant: :stock_items)
|
38
|
+
.where(variant_id: variant.id)
|
39
|
+
.where.not(id: except_line_item_id)
|
40
|
+
.joins("INNER JOIN (#{dates_sql}) dates ON dates.date >= spree_line_items.from_date AND dates.date < spree_line_items.to_date")
|
41
|
+
.group(:variant_id, :reservation_date)
|
42
|
+
.order(:reservation_date)
|
43
|
+
.each_with_object({}) do |record, hash|
|
44
|
+
hash[record.reservation_date.to_date] = record.available_quantity
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
# override this for product that have
|
49
|
+
# different date time interval than 1 day.
|
50
|
+
def date_interval
|
51
|
+
'1 day'
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -9,12 +9,10 @@ module Spree
|
|
9
9
|
|
10
10
|
attributes :total_inventory, :service_availabilities
|
11
11
|
|
12
|
-
# Deprecated
|
13
12
|
attribute :total_booking do |vendor|
|
14
13
|
vendor.respond_to?(:total_booking) ? vendor.total_booking : 0
|
15
14
|
end
|
16
15
|
|
17
|
-
# Deprecated
|
18
16
|
attribute :remaining do |vendor|
|
19
17
|
vendor.respond_to?(:remaining) ? vendor.remaining : vendor.total_inventory
|
20
18
|
end
|
@@ -25,9 +25,11 @@ module SpreeCmCommissioner
|
|
25
25
|
end
|
26
26
|
|
27
27
|
def self.auth_context(params)
|
28
|
+
tenant_id = find_oauth_application(params)&.tenant_id
|
29
|
+
|
28
30
|
case flow_type(params)
|
29
31
|
when 'login_auth'
|
30
|
-
options = { login: params[:username], password: params[:password] }
|
32
|
+
options = { login: params[:username], password: params[:password], tenant_id: tenant_id }
|
31
33
|
SpreeCmCommissioner::UserPasswordAuthenticator.call(options)
|
32
34
|
when 'social_auth'
|
33
35
|
options = { id_token: params[:id_token] }
|
@@ -0,0 +1,62 @@
|
|
1
|
+
module SpreeCmCommissioner
|
2
|
+
class UserRolesAssigner
|
3
|
+
attr_reader :user_id, :email, :role_ids, :vendor_id, :user
|
4
|
+
|
5
|
+
def self.create(user_id: nil, email: nil, role_ids: nil, vendor_id: nil)
|
6
|
+
new(user_id: user_id, email: email, role_ids: role_ids, vendor_id: vendor_id).create
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.update(user_id: nil, email: nil, role_ids: nil, vendor_id: nil)
|
10
|
+
new(user_id: user_id, email: email, role_ids: role_ids, vendor_id: vendor_id).update
|
11
|
+
end
|
12
|
+
|
13
|
+
def initialize(user_id: nil, email: nil, role_ids: nil, vendor_id: nil)
|
14
|
+
@user_id = user_id
|
15
|
+
@email = email
|
16
|
+
@role_ids = role_ids
|
17
|
+
@vendor_id = vendor_id
|
18
|
+
@user = find_user
|
19
|
+
end
|
20
|
+
|
21
|
+
def create
|
22
|
+
return { success: false, message: I18n.t('user_roles_assigner.user_not_found') } unless user
|
23
|
+
return { success: false, message: I18n.t('user_roles_assigner.user_already_assigned') } if user.vendors.exists?(id: vendor_id)
|
24
|
+
return { success: false, message: I18n.t('user_roles_assigner.roles_required') } if role_ids.blank?
|
25
|
+
|
26
|
+
create_roles
|
27
|
+
{ success: true }
|
28
|
+
end
|
29
|
+
|
30
|
+
def update
|
31
|
+
return { success: false, message: I18n.t('user_roles_assigner.roles_required') } if role_ids.blank?
|
32
|
+
|
33
|
+
update_roles
|
34
|
+
{ success: true }
|
35
|
+
end
|
36
|
+
|
37
|
+
private
|
38
|
+
|
39
|
+
def find_user
|
40
|
+
return Spree::User.find_by(id: user_id) if user_id.present?
|
41
|
+
return Spree::User.find_by(email: email) if email.present?
|
42
|
+
|
43
|
+
nil
|
44
|
+
end
|
45
|
+
|
46
|
+
def users_role
|
47
|
+
roles = Spree::Role.filter_by_vendor(vendor_id)
|
48
|
+
user.role_users.where(role: roles)
|
49
|
+
end
|
50
|
+
|
51
|
+
def create_roles
|
52
|
+
vendor = Spree::Vendor.find_by(id: vendor_id)
|
53
|
+
user.vendors << vendor unless user.vendors.include?(vendor)
|
54
|
+
role_ids.each { |role_id| users_role.find_or_create_by(role_id: role_id) }
|
55
|
+
end
|
56
|
+
|
57
|
+
def update_roles
|
58
|
+
users_role.where.not(role_id: role_ids).destroy_all
|
59
|
+
role_ids.each { |role_id| users_role.find_or_create_by(role_id: role_id) }
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|