spree_cm_commissioner 1.11.0.pre.pre4 → 1.13.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 (175) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/test_and_build_gem.yml +143 -12
  3. data/.gitignore +1 -2
  4. data/Gemfile.lock +1 -22
  5. data/Rakefile +4 -33
  6. data/app/controllers/spree/admin/cms_pages_controller_decorator.rb +32 -0
  7. data/app/controllers/spree/admin/product_places_controller.rb +2 -0
  8. data/app/controllers/spree/admin/stock_managements_controller.rb +1 -62
  9. data/app/controllers/spree/api/v2/organizer/invite_guests_controller.rb +70 -0
  10. data/app/controllers/spree/api/v2/storefront/accommodations_controller.rb +31 -14
  11. data/app/controllers/spree/api/v2/storefront/queue_cart/line_items_controller.rb +2 -2
  12. data/app/controllers/spree/api/v2/storefront/waiting_room_sessions_controller.rb +1 -0
  13. data/app/controllers/spree/api/v2/tenant/account_checker_controller.rb +1 -1
  14. data/app/controllers/spree/api/v2/tenant/account_recovers_controller.rb +2 -2
  15. data/app/controllers/spree/api/v2/tenant/cms_pages_controller.rb +41 -0
  16. data/app/controllers/spree/api/v2/tenant/reset_passwords_controller.rb +1 -1
  17. data/app/controllers/spree/api/v2/tenant/waiting_room_sessions_controller.rb +30 -0
  18. data/app/controllers/spree_cm_commissioner/admin/variants_controller_decorator.rb +17 -0
  19. data/app/controllers/spree_cm_commissioner/api/v2/storefront/cms_pages_controller_decorator.rb +18 -0
  20. data/app/interactors/spree_cm_commissioner/account_recover.rb +2 -2
  21. data/app/interactors/spree_cm_commissioner/create_event.rb +7 -26
  22. data/app/interactors/spree_cm_commissioner/create_ticket.rb +95 -0
  23. data/app/interactors/spree_cm_commissioner/event_line_items_date_syncer.rb +19 -0
  24. data/app/interactors/spree_cm_commissioner/existing_account_checker.rb +1 -1
  25. data/app/interactors/spree_cm_commissioner/order_importer/multi_guest.rb +31 -0
  26. data/app/interactors/spree_cm_commissioner/organizers_transactional_email_notifier.rb +27 -0
  27. data/app/interactors/spree_cm_commissioner/pin_code_sender.rb +3 -3
  28. data/app/interactors/spree_cm_commissioner/product_event_id_to_children_syncer.rb +15 -0
  29. data/app/interactors/spree_cm_commissioner/sms.rb +14 -0
  30. data/app/interactors/spree_cm_commissioner/telegram_debug_pin_code_sender.rb +2 -1
  31. data/app/interactors/spree_cm_commissioner/transactional_email_sender.rb +50 -0
  32. data/app/interactors/spree_cm_commissioner/user_forgotten_password_updater.rb +2 -1
  33. data/app/interactors/spree_cm_commissioner/user_password_authenticator.rb +4 -2
  34. data/app/interactors/spree_cm_commissioner/waiting_room_session_creator.rb +7 -14
  35. data/app/interactors/spree_cm_commissioner/waiting_room_session_firebase_logger.rb +30 -0
  36. data/app/jobs/spree_cm_commissioner/ensure_event_for_product_line_item_guests_job.rb +13 -0
  37. data/app/jobs/spree_cm_commissioner/event_line_items_date_syncer_job.rb +8 -0
  38. data/app/jobs/spree_cm_commissioner/product_event_id_to_children_syncer_job.rb +8 -0
  39. data/app/jobs/spree_cm_commissioner/telegram_debug_pin_code_sender_job.rb +3 -1
  40. data/app/jobs/spree_cm_commissioner/waiting_room_session_firebase_logger_job.rb +13 -0
  41. data/app/mailers/spree_cm_commissioner/event_transactional_mailer.rb +23 -0
  42. data/app/mailers/spree_cm_commissioner/pin_code_mailer.rb +1 -0
  43. data/app/models/concerns/spree_cm_commissioner/kyc_bitwise.rb +2 -0
  44. data/app/models/concerns/spree_cm_commissioner/line_item_durationable.rb +10 -6
  45. data/app/models/concerns/spree_cm_commissioner/order_state_machine.rb +13 -26
  46. data/app/models/concerns/spree_cm_commissioner/product_delegation.rb +4 -3
  47. data/app/models/concerns/spree_cm_commissioner/product_type.rb +0 -10
  48. data/app/models/concerns/spree_cm_commissioner/user_identity.rb +7 -4
  49. data/app/models/concerns/spree_cm_commissioner/variant_options_concern.rb +8 -10
  50. data/app/models/spree_cm_commissioner/cms_page_decorator.rb +9 -0
  51. data/app/models/spree_cm_commissioner/event_ticket_google_wallet.rb +2 -2
  52. data/app/models/spree_cm_commissioner/guest.rb +1 -1
  53. data/app/models/spree_cm_commissioner/invite_guest.rb +23 -0
  54. data/app/models/spree_cm_commissioner/line_item_decorator.rb +10 -16
  55. data/app/models/spree_cm_commissioner/option_type_decorator.rb +6 -0
  56. data/app/models/spree_cm_commissioner/order_decorator.rb +0 -15
  57. data/app/models/spree_cm_commissioner/place.rb +1 -1
  58. data/app/models/spree_cm_commissioner/product_decorator.rb +17 -14
  59. data/app/models/spree_cm_commissioner/product_place.rb +1 -0
  60. data/app/models/spree_cm_commissioner/role_decorator.rb +3 -0
  61. data/app/models/spree_cm_commissioner/stock/availability_checker.rb +25 -27
  62. data/app/models/spree_cm_commissioner/stock/availability_validator_decorator.rb +1 -2
  63. data/app/models/spree_cm_commissioner/stock/line_item_availability_checker.rb +3 -3
  64. data/app/models/spree_cm_commissioner/stock_item_decorator.rb +0 -14
  65. data/app/models/spree_cm_commissioner/taxon_decorator.rb +26 -3
  66. data/app/models/spree_cm_commissioner/transactional_email.rb +6 -0
  67. data/app/models/spree_cm_commissioner/user_decorator.rb +6 -0
  68. data/app/models/spree_cm_commissioner/variant_decorator.rb +27 -34
  69. data/app/models/spree_cm_commissioner/vehicle.rb +0 -7
  70. data/app/models/spree_cm_commissioner/vendor_decorator.rb +9 -1
  71. data/app/overrides/spree/admin/cms_pages/_form/tenant_fields.html.erb.deface +9 -0
  72. data/app/overrides/spree/admin/cms_pages/index/cms_pages_tabs.html.erb.deface +21 -0
  73. data/app/overrides/spree/admin/taxons/_form/assets_form.html.erb.deface +2 -2
  74. data/app/overrides/spree/admin/taxons/_form/available_on.html.erb.deface +3 -1
  75. data/app/overrides/spree/admin/taxons/_form/background_color_and_foreground_color.html.erb.deface +3 -1
  76. data/app/overrides/spree/admin/taxons/_form/custom_redirect_url.html.erb.deface +3 -1
  77. data/app/overrides/spree/admin/taxons/_form/hide_video_banner.html.erb.deface +3 -1
  78. data/app/overrides/spree/admin/taxons/_form/purchasable_on_status.html.erb.deface +3 -1
  79. data/app/overrides/spree/admin/taxons/_form/show_badge_status.html.erb.deface +3 -1
  80. data/app/overrides/spree/admin/taxons/_form/to_date_form_date.html.erb.deface +3 -4
  81. data/app/overrides/spree/admin/users/_form/roles_fields.html.erb.deface +1 -1
  82. data/app/overrides/spree/admin/users/index/body.html.erb.deface +3 -0
  83. data/app/overrides/spree/admin/users/index/headers.html.erb.deface +3 -0
  84. data/app/overrides/spree/admin/variants/_form/kyc_field.html.erb.deface +40 -0
  85. data/app/overrides/spree/admin/variants/edit/variant_status.html.erb.deface +6 -3
  86. data/app/queries/spree_cm_commissioner/variant_availability/non_permanent_stock_query.rb +45 -0
  87. data/app/queries/spree_cm_commissioner/variant_availability/permanent_stock_query.rb +55 -0
  88. data/app/request_schemas/spree_cm_commissioner/accommodation_request_schema.rb +0 -3
  89. data/app/request_schemas/spree_cm_commissioner/application_request_schema.rb +1 -1
  90. data/app/serializers/spree/v2/organizer/invite_guest_serializer.rb +13 -0
  91. data/app/serializers/spree/v2/storefront/accommodation_serializer.rb +0 -2
  92. data/app/serializers/spree/v2/storefront/taxon_serializer_decorator.rb +2 -0
  93. data/app/serializers/spree/v2/tenant/waiting_room_session_serializer.rb +9 -0
  94. data/app/serializers/spree_cm_commissioner/v2/storefront/guest_serializer.rb +2 -1
  95. data/app/services/spree_cm_commissioner/user_authenticator.rb +3 -1
  96. data/app/services/spree_cm_commissioner/user_roles_assigner.rb +62 -0
  97. data/app/views/spree/admin/shared/_cms_pages_tabs.html.erb +20 -0
  98. data/app/views/spree/admin/shared/_taxon_tabs.html.erb +19 -19
  99. data/app/views/spree/admin/stock_managements/_variant_stock_items.html.erb +1 -3
  100. data/app/views/spree/admin/stock_managements/index.html.erb +5 -40
  101. data/app/views/spree/shared/_base_mailer_header.html.erb +10 -2
  102. data/app/views/spree_cm_commissioner/event_transactional_mailer/_event_banner.html.erb +3 -0
  103. data/app/views/spree_cm_commissioner/event_transactional_mailer/_mailer_stylesheets.html.erb +317 -0
  104. data/app/views/spree_cm_commissioner/event_transactional_mailer/_note.html.erb +8 -0
  105. data/app/views/spree_cm_commissioner/event_transactional_mailer/_share_button.html.erb +3 -0
  106. data/app/views/spree_cm_commissioner/event_transactional_mailer/send_to_organizer.html.erb +59 -0
  107. data/app/views/spree_cm_commissioner/event_transactional_mailer/send_to_participant.html.erb +52 -0
  108. data/app/views/spree_cm_commissioner/layouts/event_transactional_mailer.html.erb +14 -0
  109. data/config/initializers/spree_permitted_attributes.rb +0 -5
  110. data/config/locales/en.yml +36 -0
  111. data/config/locales/km.yml +2 -0
  112. data/config/routes.rb +6 -11
  113. data/db/migrate/20250422014417_create_spree_cm_commissioner_invite_guest.rb +21 -0
  114. data/db/migrate/20250509033437_create_spree_cm_commissioner_transactional_emails.rb +12 -0
  115. data/db/migrate/20250509075429_add_max_order_quantity_to_spree_product.rb +5 -0
  116. data/db/migrate/20250512075319_add_tenant_id_to_spree_cms_pages.rb +6 -0
  117. data/db/migrate/20250520042602_add_event_to_spree_products.rb +7 -0
  118. data/db/migrate/20250520044533_add_event_to_spree_line_items.rb +7 -0
  119. data/db/migrate/20250521024345_add_tenant_id_to_cm_waiting_room_sessions.rb +6 -0
  120. data/db/migrate/20250521095539_add_kyc_to_spree_variants.rb +5 -0
  121. data/docker-compose.yml +1 -1
  122. data/lib/generators/spree_cm_commissioner/install/install_generator.rb +3 -11
  123. data/lib/generators/spree_cm_commissioner/install/templates/app/javascript/{spree_dashboard/spree_cm_commissioner → spree_cm_commissioner}/utilities.js +0 -4
  124. data/lib/spree_cm_commissioner/calendar_event.rb +1 -11
  125. data/lib/spree_cm_commissioner/test_helper/factories/homepage_section_relatable_factory.rb +1 -1
  126. data/lib/spree_cm_commissioner/test_helper/factories/line_item_factory.rb +1 -1
  127. data/lib/spree_cm_commissioner/test_helper/factories/product_factory.rb +5 -18
  128. data/lib/spree_cm_commissioner/test_helper/factories/role.rb +7 -0
  129. data/lib/spree_cm_commissioner/test_helper/factories/stock_location_factory.rb +2 -2
  130. data/lib/spree_cm_commissioner/test_helper/factories/taxon_home_banner_factory.rb +5 -0
  131. data/lib/spree_cm_commissioner/test_helper/factories/transactional_email_factory.rb +6 -0
  132. data/lib/spree_cm_commissioner/test_helper/factories/variant_factory.rb +6 -41
  133. data/lib/spree_cm_commissioner/test_helper/factories/vendor_factory.rb +1 -1
  134. data/lib/spree_cm_commissioner/version.rb +1 -1
  135. data/lib/spree_cm_commissioner.rb +0 -34
  136. data/lib/tasks/ensure_event_for_product_line_item_guests.rake +7 -0
  137. data/lib/tasks/update_invalid_self_root_places.rake +9 -0
  138. data/lib/tasks/update_orphan_root_places.rake +1 -0
  139. data/spree_cm_commissioner.gemspec +0 -5
  140. metadata +54 -82
  141. data/app/controllers/spree/api/v2/storefront/accommodations/variants_controller.rb +0 -42
  142. data/app/finders/spree_cm_commissioner/accommodations/find.rb +0 -40
  143. data/app/finders/spree_cm_commissioner/accommodations/find_variant.rb +0 -35
  144. data/app/interactors/spree_cm_commissioner/ensure_correct_product_type.rb +0 -40
  145. data/app/interactors/spree_cm_commissioner/inventory_item_syncer.rb +0 -25
  146. data/app/interactors/spree_cm_commissioner/stock/inventory_items_adjuster.rb +0 -13
  147. data/app/interactors/spree_cm_commissioner/stock/inventory_items_generator.rb +0 -15
  148. data/app/interactors/spree_cm_commissioner/stock/permanent_inventory_items_generator.rb +0 -75
  149. data/app/interactors/spree_cm_commissioner/stock/stock_movement_creator.rb +0 -24
  150. data/app/interactors/spree_cm_commissioner/user_roles_assigner.rb +0 -22
  151. data/app/jobs/spree_cm_commissioner/ensure_correct_product_type_job.rb +0 -7
  152. data/app/jobs/spree_cm_commissioner/inventory_item_syncer_job.rb +0 -7
  153. data/app/jobs/spree_cm_commissioner/stock/inventory_items_adjuster_job.rb +0 -11
  154. data/app/jobs/spree_cm_commissioner/stock/inventory_items_generator_job.rb +0 -11
  155. data/app/jobs/spree_cm_commissioner/stock/permanent_inventory_items_generator_job.rb +0 -9
  156. data/app/models/spree_cm_commissioner/inventory.rb +0 -11
  157. data/app/models/spree_cm_commissioner/inventory_item.rb +0 -56
  158. data/app/models/spree_cm_commissioner/redis_stock/cached_inventory_items_builder.rb +0 -40
  159. data/app/models/spree_cm_commissioner/redis_stock/inventory_updater.rb +0 -126
  160. data/app/models/spree_cm_commissioner/redis_stock/line_items_cached_inventory_items_builder.rb +0 -36
  161. data/app/models/spree_cm_commissioner/redis_stock/variant_cached_inventory_items_builder.rb +0 -27
  162. data/app/models/spree_cm_commissioner/stock/order_availability_checker.rb +0 -44
  163. data/app/request_schemas/spree_cm_commissioner/variant_request_schema.rb +0 -19
  164. data/app/views/spree/admin/stock_managements/_events_popover.html.erb +0 -23
  165. data/app/views/spree/admin/stock_managements/calendar.html.erb +0 -35
  166. data/db/migrate/20250304293518_create_cm_inventory_items.rb +0 -21
  167. data/db/migrate/20250429094228_add_lock_version_to_cm_inventory_items.rb +0 -5
  168. data/db/migrate/20250502025848_add_index_to_spree_products.rb +0 -5
  169. data/db/migrate/20250502030001_add_product_type_to_spree_variants.rb +0 -5
  170. data/db/migrate/20250502030002_add_product_type_to_spree_line_items.rb +0 -5
  171. data/lib/spree_cm_commissioner/cached_inventory_item.rb +0 -23
  172. data/lib/spree_cm_commissioner/test_helper/factories/inventory_item_factory.rb +0 -9
  173. data/lib/tasks/create_default_non_permanent_inventory_items.rake +0 -16
  174. data/lib/tasks/ensure_correct_product_type.rake +0 -7
  175. data/lib/tasks/generate_inventory_items.rake +0 -7
@@ -0,0 +1,13 @@
1
+ module Spree
2
+ module V2
3
+ module Organizer
4
+ class InviteGuestSerializer < BaseSerializer
5
+ attributes :email, :quantity, :token, :invite_type, :claimed_status, :issued_to, :expiration_date,
6
+ :claimed_at, :email_send_at, :created_at, :updated_at, :remark
7
+ belongs_to :variant, serializer: SpreeCmCommissioner::V2::Storefront::EventVariantSerializer
8
+ belongs_to :order, serializer: Spree::V2::Storefront::OrderSerializer
9
+ belongs_to :event, serializer: Spree::V2::Storefront::TaxonSerializer
10
+ end
11
+ end
12
+ end
13
+ 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,6 +25,8 @@ module Spree
25
25
  end
26
26
 
27
27
  base.cache_options store: nil
28
+
29
+ base.attribute :event_url, &:event_url
28
30
  end
29
31
  end
30
32
  end
@@ -0,0 +1,9 @@
1
+ module Spree
2
+ module V2
3
+ module Tenant
4
+ class WaitingRoomSessionSerializer < BaseSerializer
5
+ attributes :jwt_token, :expired_at
6
+ end
7
+ end
8
+ end
9
+ end
@@ -6,7 +6,8 @@ module SpreeCmCommissioner
6
6
 
7
7
  attributes :first_name, :last_name, :dob, :gender, :kyc_fields, :other_occupation, :created_at, :updated_at,
8
8
  :qr_data, :social_contact_platform, :social_contact, :available_social_contact_platforms,
9
- :age, :emergency_contact, :other_organization, :expectation, :upload_later, :address, :formatted_bib_number, :phone_number
9
+ :age, :emergency_contact, :other_organization, :expectation, :upload_later, :address, :formatted_bib_number, :phone_number,
10
+ :token
10
11
 
11
12
  # temporary, once app release after cm-app v1.9.1, we no longer need this.
12
13
  attribute :seat_number do |object|
@@ -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
@@ -0,0 +1,20 @@
1
+ <% content_for(:page_tabs) do %>
2
+ <% if can?(:admin, Spree::CmsPage) %>
3
+ <%= content_tag :li, class: 'nav-item' do %>
4
+ <%= link_to_with_icon 'building.svg',
5
+ Spree::Store.default&.name || Spree.t(:store),
6
+ admin_cms_pages_url(tab: :default),
7
+ class: "nav-link #{'active' if params[:tab].blank? || params[:tab] == 'default'}" %>
8
+ <% end %>
9
+
10
+ <!-- Tenant Tabs -->
11
+ <% SpreeCmCommissioner::Tenant.all.each do |tenant| %>
12
+ <%= content_tag :li, class: 'nav-item' do %>
13
+ <%= link_to_with_icon 'building.svg',
14
+ tenant.name,
15
+ admin_cms_pages_url(tab: :tenants, tenant_id: tenant.id),
16
+ class: "nav-link #{'active' if params[:tenant_id].to_s == tenant.id.to_s}" %>
17
+ <% end %>
18
+ <% end %>
19
+ <% end %>
20
+ <% end %>
@@ -5,43 +5,43 @@
5
5
  Spree.t(:details),
6
6
  edit_admin_taxonomy_taxon_url(@taxonomy.id, @taxon.id),
7
7
  class: "nav-link #{'active' if current == :details}" %>
8
- <% end if can?(:admin, Spree::Taxonomy) %>
8
+ <% end if can?(:manage, Spree::Taxonomy) %>
9
9
 
10
10
  <%= content_tag :li, class: 'nav-item' do %>
11
11
  <%= link_to_with_icon 'store.svg',
12
12
  Spree.t(:vendors),
13
13
  admin_taxonomy_taxon_taxon_vendors_url(@taxonomy.id, @taxon.id),
14
14
  class: "nav-link #{'active' if current == :vendors}" %>
15
- <% end if can?(:admin,SpreeCmCommissioner::TaxonVendor)%>
16
- <% if @taxon.depth != 1 %>
15
+ <% end if can?(:manage, SpreeCmCommissioner::TaxonVendor) && @taxon.depth == 2 %>
17
16
 
18
- <%= content_tag :li, class: 'nav-item' do %>
19
- <%= link_to_with_icon 'inbox.svg',
20
- Spree.t(:products),
21
- admin_taxonomy_taxon_classifications_url(@taxonomy.id, @taxon.id),
22
- class: "nav-link #{'active' if current == :products}" %>
23
- <% end if can?(:admin, Spree::Classification)%>
24
- <%else%>
17
+ <% if @taxon.depth != 1 %>
18
+ <%= content_tag :li, class: 'nav-item' do %>
19
+ <%= link_to_with_icon 'inbox.svg',
20
+ Spree.t(:products),
21
+ admin_taxonomy_taxon_classifications_url(@taxonomy.id, @taxon.id),
22
+ class: "nav-link #{'active' if current == :products}" %>
23
+ <% end if can?(:manage, Spree::Classification)%>
24
+ <% else %>
25
25
  <%= content_tag :li, class: 'nav-item' do %>
26
- <%= link_to_with_icon 'store.svg',
27
- Spree.t(:sections),
28
- admin_taxonomy_taxon_taxon_childrens_url(@taxonomy.id, @taxon.id),
29
- class: "nav-link #{'active' if current == :sections}" %>
30
- <% end if can?(:admin,Spree::Taxon)%>
31
- <%end%>
26
+ <%= link_to_with_icon 'store.svg',
27
+ Spree.t(:sections),
28
+ admin_taxonomy_taxon_taxon_childrens_url(@taxonomy.id, @taxon.id),
29
+ class: "nav-link #{'active' if current == :sections}" %>
30
+ <% end if can?(:manage, Spree::Taxon)%>
31
+ <% end %>
32
32
 
33
+ <%# user event only show for event %>
33
34
  <%= content_tag :li, class: 'nav-item' do %>
34
35
  <%= link_to_with_icon 'user.svg',
35
36
  Spree.t(:user_events),
36
- # admin_taxonomy_taxon_user_taxons_url(@taxonomy, @taxon.id),
37
37
  admin_user_events_path(params: {taxon_id: @taxon.id, taxonomy_id: @taxonomy}),
38
38
  class: "nav-link #{'active' if current == :user_events}" %>
39
- <% end if can?(:admin, SpreeCmCommissioner::UserTaxon) %>
39
+ <% end if can?(:manage, SpreeCmCommissioner::UserTaxon) && @taxon.event? && @taxon.depth == 1 %>
40
40
 
41
41
  <%= content_tag :li, class: 'nav-item' do %>
42
42
  <%= link_to_with_icon 'store.svg',
43
43
  Spree.t(:guest_card_classes),
44
44
  admin_taxonomy_taxon_guest_card_classes_url(@taxonomy.id, @taxon.id),
45
45
  class: "nav-link #{'active' if current == :guest_card_classes}" %>
46
- <% end if can?(:admin,SpreeCmCommissioner::GuestCardClasses)%>
46
+ <% end if can?(:manage, SpreeCmCommissioner::GuestCardClasses) && @taxon.event? && @taxon.depth == 1 %>
47
47
  <% end %>
@@ -17,11 +17,9 @@
17
17
  </td>
18
18
  <td class="text-center d-flex flex-column align-items-center justify-content-center">
19
19
  <div style="width: 90px;">
20
- <%= form_tag admin_product_stock_managements_path(product_id: params[:product_id], variant_id: variant.id, stock_location_id: stock_location.id), method: :post do %>
20
+ <%= form_tag admin_stock_items_path(variant_id: variant.id, stock_location_id: stock_location.id), method: :post do %>
21
21
  <div class="input-group input-group-sm">
22
22
  <%= number_field_tag 'stock_movement[quantity]', 0, class: 'form-control text-center p-0' %>
23
- <%= hidden_field_tag 'stock_movement[originator_id]', spree_current_user.id %>
24
- <%= hidden_field_tag 'stock_movement[originator_type]', spree_current_user.class.name %>
25
23
  <div class="input-group-append">
26
24
  <%= button_tag(class: 'btn btn-outline-success pl-2 pr-1') do %>
27
25
  <%= svg_icon(name: 'arrow-left-right.svg', classes: "icon", width: 14, height: 14) %>
@@ -19,7 +19,10 @@
19
19
  <% @variants.each do |variant| %>
20
20
  <tr id="<%= spree_dom_id variant %>" data-hook="admin_product_stock_management_index_rows">
21
21
  <td class="image text-center">
22
- <%= small_image(variant) %>
22
+ <%= small_image(variant) %>
23
+ <div class="mt-4">
24
+ Reserved Stock: <%= @reserved_stocks[variant.id] || 0 %></strong>
25
+ </div>
23
26
  </td>
24
27
  <td>
25
28
  <%= variant.sku_and_options_text %>
@@ -32,46 +35,14 @@
32
35
  <% end %>
33
36
  </div>
34
37
  <% end if can?(:update, @product) && can?(:update, variant) %>
35
-
36
- <% if defined?(@reserved_stocks) %>
37
- <div>
38
- <span type="button" data-toggle="popover" data-trigger="hover" data-placement="right" data-content="This product stock will renew every day">
39
- <%= svg_icon name: "cart-check.svg", width: '14', height: '14' %>
40
- </span>
41
- <%= label_tag "reserved_stock#{variant.id}", "Reserved Stock: #{@reserved_stocks[variant.id] || 0}", class: "m-0" %>
42
- </div>
43
- <% end %>
44
-
45
38
  <% if variant.permanent_stock? %>
46
39
  <div>
47
40
  <span type="button" data-toggle="popover" data-trigger="hover" data-placement="right" data-content="This product stock will renew every day">
48
41
  <%= svg_icon name: "info-circle-fill.svg", width: '14', height: '14' %>
49
42
  </span>
50
- <%= label_tag "permanent_stock_#{ variant.id }", Spree.t(:permanent_stock), class: "m-0" %>
43
+ <%= label_tag "permanent_stock_#{ variant.id }", Spree.t(:permanent_stock) %>
51
44
  </div>
52
45
  <% end %>
53
-
54
- <% if defined?(@inventory_items) %>
55
- <% @inventory_items[variant.id]&.each do |inventory_item| %>
56
- <div>
57
- <%= svg_icon name: "handbag.svg", width: '14', height: '14' %>
58
- <%= label_tag "max_capacity_#{ inventory_item.id }", "Max capacity: #{inventory_item.max_capacity}", class: "m-0" %>
59
- </div>
60
- <div>
61
- <%= svg_icon name: "approve.svg", width: '14', height: '14' %>
62
- <%= label_tag "quantity_available_#{ inventory_item.id }", "Quantity available: #{inventory_item.quantity_available}", class: "m-0" %>
63
-
64
- <% synced = inventory_item.quantity_available == @cached_inventory_items[inventory_item.id].quantity_available %>
65
- <span type="button" data-toggle="popover" data-trigger="hover" data-placement="right" data-content="<%= inventory_item_message(inventory_item, @cached_inventory_items[inventory_item.id]) %>">
66
- <% if synced %>
67
- <%= svg_icon name: "cloud-check.svg", width: '14', height: '14', classes: 'text-success' %>
68
- <% else %>
69
- <%= svg_icon name: "cloud-slash.svg", width: '14', height: '14', classes: 'text-danger' %>
70
- <% end %>
71
- </span>
72
- </div>
73
- <% end %>
74
- <% end %>
75
46
  </td>
76
47
 
77
48
  <td colspan="3" class="stock_location_info">
@@ -82,9 +53,3 @@
82
53
  </tbody>
83
54
  </table>
84
55
  </div>
85
-
86
- <%= turbo_frame_tag "calendar", src: calendar_admin_product_stock_managements_path(year: params[:year]) do %>
87
- <div class="spinner-border mt-2" role="status">
88
- <span class="sr-only">Loading...</span>
89
- </div>
90
- <% end if @product.permanent_stock? %>
@@ -1,11 +1,19 @@
1
1
  <!-- override base_mailer_header.html.erb -->
2
2
  <tr>
3
3
  <td class="email-masthead">
4
- <%= link_to @sender_name, class: 'template-label' do %>
4
+ <% if defined?(@tenant) && @tenant.present? %>
5
5
  <% if @logo_path.present? %>
6
6
  <%= image_tag @logo_path, class: 'logo', alt: @sender_name, title: @sender_name %>
7
7
  <% else %>
8
- <%= @sender_name %>
8
+ <span class="template-label"><%= @sender_name %></span>
9
+ <% end %>
10
+ <% else %>
11
+ <%= link_to current_store.url, class: 'template-label' do %>
12
+ <% if @logo_path.present? %>
13
+ <%= image_tag @logo_path, class: 'logo', alt: current_store.name, title: current_store.name %>
14
+ <% else %>
15
+ <%= current_store.name %>
16
+ <% end %>
9
17
  <% end %>
10
18
  <% end %>
11
19
  </td>
@@ -0,0 +1,3 @@
1
+ <div class="banner">
2
+ <%= image_tag(main_app.rails_blob_url(@event.home_banner.attachment), class: "banner-image", alt: t('mail.event_engagement_mailer.organizer.header_title')) %>
3
+ </div>
@@ -0,0 +1,317 @@
1
+ <style>
2
+ body {
3
+ margin-top: 20px;
4
+ padding: 0;
5
+ font-family: 'Poppins', Arial, sans-serif;
6
+ line-height: 1.6;
7
+ background-color: #f4f4f4;
8
+ }
9
+
10
+ table {
11
+ border-collapse: collapse;
12
+ width: 100%;
13
+ max-width: 640px;
14
+ margin: 0 auto;
15
+ }
16
+
17
+ img {
18
+ border: 0;
19
+ line-height: 100%;
20
+ outline: none;
21
+ text-decoration: none;
22
+ max-width: 100%;
23
+ height: auto;
24
+ }
25
+
26
+ a {
27
+ color: #6444D8;
28
+ }
29
+
30
+ .container {
31
+ background-color: #ffffff;
32
+ border-radius: 8px;
33
+ box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
34
+ padding: 24px;
35
+ margin: 16px auto;
36
+ }
37
+
38
+ .header {
39
+ text-align: left;
40
+ margin-bottom: 20px;
41
+ }
42
+
43
+ .header .icon {
44
+ font-size: 24px;
45
+ margin-bottom: 12px;
46
+ }
47
+
48
+ .main-title {
49
+ color: #6444D8;
50
+ }
51
+
52
+ .header h1 {
53
+ font-size: 24px;
54
+ font-weight: bold;
55
+ margin: 0;
56
+ }
57
+
58
+ .header h2 {
59
+ font-size: 18px;
60
+ margin: 8px 0 0;
61
+ }
62
+
63
+ .intro p {
64
+ color: #1f2937;
65
+ font-size: 14px;
66
+ margin: 0 0 8px;
67
+ text-align: left;
68
+ }
69
+
70
+ .impact-section {
71
+ background-color: #F1F2FE;
72
+ border-radius: 8px;
73
+ padding: 20px;
74
+ margin: 20px 0;
75
+ }
76
+
77
+ .impact-section h3 {
78
+ font-size: 14px;
79
+ font-weight: 600;
80
+ margin: 0 0 12px;
81
+ color: #1f2937;
82
+ text-align: left;
83
+ }
84
+
85
+ .impact-list {
86
+ list-style: none;
87
+ padding: 0;
88
+ margin: 0;
89
+ }
90
+
91
+ .impact-list li {
92
+ display: flex;
93
+ align-items: flex-start;
94
+ margin-bottom: 12px;
95
+ }
96
+
97
+ .impact-list span {
98
+ margin-right: 8px;
99
+ font-size: 14px;
100
+ flex-shrink: 0;
101
+ }
102
+
103
+ .impact-list div {
104
+ font-size: 14px;
105
+ color: #1f2937;
106
+ text-align: left;
107
+ }
108
+
109
+ .closing p {
110
+ font-size: 14px;
111
+ color: #1f2937;
112
+ margin: 0 0 8px;
113
+ text-align: left;
114
+ }
115
+
116
+ .closing p:last-child {
117
+ font-weight: 600;
118
+ }
119
+
120
+ .button-wrapper {
121
+ text-align: center;
122
+ margin: 20px 0;
123
+ }
124
+
125
+ .cta-button {
126
+ display: inline-block;
127
+ background-color: #6444D8;
128
+ color: #ffffff;
129
+ padding: 12px 24px;
130
+ border-radius: 24px;
131
+ text-decoration: none;
132
+ font-weight: 500;
133
+ font-size: 14px;
134
+ width: 10rem;
135
+ max-width: 90%;
136
+ }
137
+
138
+ .cta-button:hover {
139
+ background-color: #7b5ce0;
140
+ text-decoration: none;
141
+ }
142
+
143
+ .signature {
144
+ text-align: left;
145
+ color: #4b5563;
146
+ margin: 20px 0;
147
+ }
148
+
149
+ .signature p {
150
+ margin: 0;
151
+ font-size: 14px;
152
+ }
153
+
154
+ .social-icons {
155
+ display: flex;
156
+ justify-content: flex-start;
157
+ gap: 16px;
158
+ margin: 12px 0 0;
159
+ }
160
+
161
+ .social-icons a {
162
+ font-size: 18px;
163
+ text-decoration: none;
164
+ color: #4b5563;
165
+ transition: color 0.3s ease;
166
+ }
167
+
168
+ .social-icons a:hover {
169
+ color: #6444D8;
170
+ }
171
+
172
+ .footer {
173
+ text-align: center;
174
+ color: #6b7280;
175
+ font-size: 12px;
176
+ padding: 16px;
177
+ }
178
+
179
+ .footer-content {
180
+ max-width: 100%;
181
+ }
182
+
183
+ .footer-brand {
184
+ font-size: 14px;
185
+ color: #1f2937;
186
+ margin: 0 0 8px;
187
+ }
188
+
189
+ .footer-text {
190
+ margin: 0 0 8px;
191
+ color: #6b7280;
192
+ }
193
+
194
+ .footer-links {
195
+ margin: 0 0 8px;
196
+ }
197
+
198
+ .footer-links a {
199
+ color: #6444D8;
200
+ text-decoration: none;
201
+ margin-right: 12px;
202
+ }
203
+
204
+ .footer-links a:hover {
205
+ text-decoration: underline;
206
+ }
207
+
208
+ .footer a {
209
+ color: #6444D8;
210
+ text-decoration: none;
211
+ }
212
+
213
+ .footer a:hover {
214
+ text-decoration: underline;
215
+ }
216
+
217
+ .footer-logo {
218
+ font-weight: bold;
219
+ color: #1f2937;
220
+ }
221
+
222
+ .footer-logo-icon {
223
+ font-weight: bold;
224
+ color: #6444D8;
225
+ }
226
+
227
+ .banner {
228
+ margin-bottom: 16px;
229
+ text-align: center;
230
+ }
231
+
232
+ .banner-image {
233
+ max-width: 100%;
234
+ height: auto;
235
+ border-radius: 8px;
236
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
237
+ }
238
+
239
+ @media only screen and (max-width: 600px) {
240
+ .container {
241
+ padding: 16px;
242
+ margin: 8px;
243
+ border-radius: 4px;
244
+ }
245
+
246
+ .header .icon {
247
+ font-size: 20px;
248
+ }
249
+
250
+ .header h1 {
251
+ font-size: 20px;
252
+ }
253
+
254
+ .header h2 {
255
+ font-size: 16px;
256
+ }
257
+
258
+ .intro p {
259
+ font-size: 13px;
260
+ }
261
+
262
+ .impact-section {
263
+ padding: 16px;
264
+ }
265
+
266
+ .impact-section h3 {
267
+ font-size: 13px;
268
+ }
269
+
270
+ .impact-list span {
271
+ font-size: 13px;
272
+ }
273
+
274
+ .impact-list div {
275
+ font-size: 13px;
276
+ }
277
+
278
+ .closing p {
279
+ font-size: 13px;
280
+ }
281
+
282
+ .cta-button {
283
+ padding: 10px 20px;
284
+ font-size: 13px;
285
+ }
286
+
287
+ .signature p {
288
+ font-size: 13px;
289
+ }
290
+
291
+ .social-icons a {
292
+ font-size: 16px;
293
+ }
294
+
295
+ .footer {
296
+ font-size: 11px;
297
+ padding: 12px;
298
+ }
299
+
300
+ .footer-brand {
301
+ font-size: 13px;
302
+ }
303
+
304
+ .footer-text {
305
+ font-size: 11px;
306
+ }
307
+
308
+ .footer-links a {
309
+ font-size: 11px;
310
+ margin-right: 8px;
311
+ }
312
+
313
+ .banner-image {
314
+ border-radius: 4px;
315
+ }
316
+ }
317
+ </style>
@@ -0,0 +1,8 @@
1
+
2
+ <td class="footer">
3
+ <div class="footer-content">
4
+ <p class="footer-text">This email was sent by <span class="footer-logo"><i>BookMe</i><span class="footer-logo-icon">+</span></span>
5
+ For support, contact us at <a href="mailto:info@bookme.plus">Info@bookme.plus</a>.
6
+ </p>
7
+ </div>
8
+ </td>
@@ -0,0 +1,3 @@
1
+ <div class="button-wrapper">
2
+ <a href="<%= @event.event_url %>" class="cta-button"><%= t('mail.event_engagement_mailer.organizer.share_now') %></a>
3
+ </div