diff --git a/app/controllers/spree/api/v2/storefront/events_controller.rb b/app/controllers/spree/api/v2/storefront/events_controller.rb
new file mode 100644
index 000000000..4db383936
--- /dev/null
+++ b/app/controllers/spree/api/v2/storefront/events_controller.rb
@@ -0,0 +1,27 @@
+module Spree
+ module Api
+ module V2
+ module Storefront
+ class EventsController < Spree::Api::V2::ResourceController
+ def collection
+ events_query.events.page(params[:page]).per(params[:per_page])
+ end
+
+ def collection_serializer
+ Spree::V2::Storefront::TaxonSerializer
+ end
+
+ private
+
+ def events_query
+ SpreeCmCommissioner::OrganizerProfileEventQuery.new(
+ vendor_id: params[:vendor_id],
+ section: params.fetch(:section, 'upcoming'),
+ start_from_date: params[:start_from_date] || nil
+ )
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/app/overrides/spree/admin/taxons/_form/vendor.html.erb.deface b/app/overrides/spree/admin/taxons/_form/vendor.html.erb.deface
new file mode 100644
index 000000000..0eba3a10f
--- /dev/null
+++ b/app/overrides/spree/admin/taxons/_form/vendor.html.erb.deface
@@ -0,0 +1,11 @@
+
+
+<% if @taxon.depth == 1 %>
+
+ <%= f.field_container :vendor_id do %>
+ <%= label_tag :vendor_id, Spree.t(:vendors) %>
+ <%= f.select :vendor_id, Spree::Vendor.pluck(:name, :id), { include_blank: true }, { class: 'select2-clear js-filterable' } %>
+ <%= f.error_message_on :vendor_id, class: 'error-message' %>
+ <% end %>
+
+<% end %>
diff --git a/app/queries/spree_cm_commissioner/organizer_profile_event_query.rb b/app/queries/spree_cm_commissioner/organizer_profile_event_query.rb
new file mode 100644
index 000000000..9c03666b7
--- /dev/null
+++ b/app/queries/spree_cm_commissioner/organizer_profile_event_query.rb
@@ -0,0 +1,28 @@
+module SpreeCmCommissioner
+ class OrganizerProfileEventQuery
+ attr_reader :vendor_id, :section, :start_from_date
+
+ # user_id: user ID, vendor_id: vendor ID, section: 'upcoming', 'previous' or 'all'
+ def initialize(vendor_id:, section:, start_from_date: nil)
+ @vendor_id = vendor_id
+ @section = section
+ @start_from_date = start_from_date || Time.zone.now
+ end
+
+ def events
+ taxons = Spree::Taxon.where(vendor_id: vendor_id)
+
+ case section
+ when 'upcoming'
+ taxons.where('to_date >= ?', start_from_date)
+ .order(from_date: :asc)
+ when 'previous'
+ taxons.where('to_date < ?', start_from_date)
+ .order(to_date: :desc)
+ else
+ taxons.where('to_date >= ? OR to_date < ?', start_from_date, start_from_date)
+ .order(from_date: :asc)
+ end
+ end
+ end
+end
diff --git a/app/serializers/spree/v2/storefront/taxon_serializer_decorator.rb b/app/serializers/spree/v2/storefront/taxon_serializer_decorator.rb
index d8c2c627e..9a904dd31 100644
--- a/app/serializers/spree/v2/storefront/taxon_serializer_decorator.rb
+++ b/app/serializers/spree/v2/storefront/taxon_serializer_decorator.rb
@@ -11,7 +11,8 @@ def self.prepended(base)
base.has_one :web_banner, serializer: ::SpreeCmCommissioner::V2::Storefront::AssetSerializer
base.has_one :home_banner, serializer: ::SpreeCmCommissioner::V2::Storefront::AssetSerializer
- base.attributes :custom_redirect_url, :kind, :subtitle, :from_date, :to_date, :background_color, :foreground_color, :show_badge_status
+ base.attributes :custom_redirect_url, :kind, :subtitle, :from_date, :to_date,
+ :background_color, :foreground_color, :show_badge_status, :vendor_id
end
end
end
diff --git a/config/initializers/spree_permitted_attributes.rb b/config/initializers/spree_permitted_attributes.rb
index 3a0706909..5ee061533 100644
--- a/config/initializers/spree_permitted_attributes.rb
+++ b/config/initializers/spree_permitted_attributes.rb
@@ -26,6 +26,7 @@ module PermittedAttributes
preferred_background_color
preferred_foreground_color
show_badge_status
+ vendor_id
]
@@store_attributes += [
diff --git a/config/routes.rb b/config/routes.rb
index f5f0ae94a..bcb10ba1a 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -428,6 +428,7 @@
resources :vendors do
resources :nearby_places, only: %i[index]
resources :vendor_photos
+ resources :events
end
resource :homepage_data, only: [:show]
resources :homepage_sections, only: [:index]
diff --git a/db/migrate/20240926044328_add_vendor_to_spree_taxon.rb b/db/migrate/20240926044328_add_vendor_to_spree_taxon.rb
new file mode 100644
index 000000000..18ebbe11b
--- /dev/null
+++ b/db/migrate/20240926044328_add_vendor_to_spree_taxon.rb
@@ -0,0 +1,5 @@
+class AddVendorToSpreeTaxon < ActiveRecord::Migration[7.0]
+ def change
+ add_reference :spree_taxons, :vendor, index: true, foreign_key: { to_table: :spree_vendors }, if_not_exists: true
+ end
+end
diff --git a/spec/queries/spree_cm_commissioner/organizer_profile_event_query_spec.rb b/spec/queries/spree_cm_commissioner/organizer_profile_event_query_spec.rb
new file mode 100644
index 000000000..5ac4a27f0
--- /dev/null
+++ b/spec/queries/spree_cm_commissioner/organizer_profile_event_query_spec.rb
@@ -0,0 +1,43 @@
+require 'spec_helper'
+
+RSpec.describe SpreeCmCommissioner::OrganizerProfileEventQuery do
+ let(:vendor) { create(:vendor) }
+ let(:start_from_date) { Time.zone.now }
+ let!(:upcoming_taxon) { create(:taxon, vendor_id: vendor.id, from_date: 1.day.from_now, to_date: 5.days.from_now) }
+ let!(:previous_taxon) { create(:taxon, vendor_id: vendor.id, from_date: 10.days.ago, to_date: 1.day.ago) }
+
+ describe '#events' do
+ context 'when section is upcoming' do
+ it 'returns only upcoming events for the vendor' do
+ query = described_class.new(vendor_id: vendor.id, section: 'upcoming', start_from_date: start_from_date)
+ expect(query.events).to contain_exactly(upcoming_taxon)
+ end
+ end
+
+ context 'when section is previous' do
+ it 'returns only previous events for the vendor' do
+ query = described_class.new(vendor_id: vendor.id, section: 'previous', start_from_date: start_from_date)
+
+ expect(query.events).to contain_exactly(previous_taxon)
+ end
+ end
+
+ context 'when start_from_date is not provided' do
+ it 'defaults to the current time' do
+ travel_to(Time.zone.now) do
+ query = described_class.new(vendor_id: vendor.id, section: 'upcoming')
+
+ expect(query.start_from_date.to_i).to be_within(1).of(Time.zone.now.to_i)
+ end
+ end
+ end
+
+ context 'when section is all' do
+ it 'returns all events for the vendor, both upcoming and previous' do
+ query = described_class.new(vendor_id: vendor.id, section: 'all', start_from_date: start_from_date)
+
+ expect(query.events).to match_array([upcoming_taxon, previous_taxon])
+ end
+ end
+ end
+end
diff --git a/spec/serializers/spree/v2/storefront/taxon_serializer_spec.rb b/spec/serializers/spree/v2/storefront/taxon_serializer_spec.rb
index 4f180eb30..b4cd6cb6b 100644
--- a/spec/serializers/spree/v2/storefront/taxon_serializer_spec.rb
+++ b/spec/serializers/spree/v2/storefront/taxon_serializer_spec.rb
@@ -47,7 +47,8 @@
:to_date,
:background_color,
:foreground_color,
- :show_badge_status
+ :show_badge_status,
+ :vendor_id
)
end