-- -- data model for events module -- -- re-written by bryanche@arsdigita.com on Feb 02, 2000 -- to support group-based registrations -- created by bryanche@arsdigita.com on Jan 13, 2000 -- adapted from register.photo.net's chautauqua code -- we store the ISO code in lower case, e.g,. 'us' -- if detail_url does not start with "HTTP://" then we assume -- it is a stub for information on our server and we grab it -- from the file system, starting at [ns_info pageroot] -- Ported to Postgres by Ben Adida (ben@adida.net) --- create the administration group for the Events module select administration_group_add ('Events Administration', 'events', 'events', '', 'f', '/admin/events/'); --- create a sub-group in Events for managing activities select administration_subgroup_add ('Activities Administration', 'activities', 'events', 'activities', 'f', '/admin/events/', 'events'); -- create a group type of "events" insert into user_group_types (group_type, pretty_name, pretty_plural, approval_policy, group_module_administration) values ('event', 'Event', 'Events', 'closed', 'full'); create table event_info ( group_id integer primary key references user_groups ); -- can't ever delete an event/activity because it might have been -- ordered and therefore the row in events_registrations would be hosed -- so we flag it create sequence events_activity_id_sequence; -- the activities create table events_activities ( activity_id integer primary key, -- activities are owned by user groups group_id integer references user_groups, user_id integer references users, creator_id integer not null references users, short_name varchar(100) not null, default_price numeric default 0 not null, currency char(3) default 'USD', description varchar(4000), -- Is this activity occurring? If not, we can't assign -- any new events to it. available_p char(1) default 't' check (available_p in ('t', 'f')), deleted_p char(1) default 'f' check (deleted_p in ('t', 'f')), detail_url varchar(256) -- URL for more details ); create sequence events_venues_id_sequence; -- where the events occur create table events_venues ( venue_id integer primary key, venue_name varchar(200) not null, address1 varchar(100), address2 varchar(100), city varchar(100) not null, usps_abbrev char(2), postal_code varchar(20), iso char(2) default 'us' references country_codes, time_zone varchar(50), needs_reserve_p char(1) default 'f' check (needs_reserve_p in ('t', 'f')), max_people integer, description varchar(4000) ); create sequence events_event_id_sequence; -- the events (instances of activities) create table events_events ( event_id integer not null primary key, activity_id integer not null references events_activities, venue_id integer not null references events_venues, -- the user group that is created for this event's registrants group_id integer not null references user_groups, creator_id integer not null references users, -- HTML to be displayed after a successful order. display_after varchar(4000), -- Date and time. start_time datetime not null, end_time datetime not null, reg_deadline datetime not null, -- An event may have been cancelled. available_p char(1) default 't' check (available_p in ('t', 'f')), deleted_p char(1) default 'f' check (deleted_p in ('t', 'f')), max_people numeric, -- can someone cancel his registration? reg_cancellable_p char(1) default 't' check (reg_cancellable_p in ('t', 'f')), -- does a registration need approval to become finalized? reg_needs_approval_p char(1) default 'f' check (reg_needs_approval_p in ('t', 'f')), -- notes for doing av setup av_note varchar(4000), -- notes for catering refreshments_note varchar(4000), -- extra info about this event additional_note varchar(4000), -- besides the web, is there another way to register? alternative_reg varchar(4000), check (start_time < end_time), check (reg_deadline <= start_time) ); -- Each activity can have default custom fields registrants should enter. create table events_activity_fields ( activity_id integer not null references events_activities, column_name varchar(30) not null, pretty_name varchar(50) not null, -- something generic and suitable for handing to AOLserver, -- e.g., boolean or text column_type varchar(50) not null, -- something nitty gritty and Oracle-specific, e.g., -- char(1) instead of boolean -- things like "not null" column_actual_type varchar(100) not null, column_extra varchar(100), -- Sort key for display of columns. sort_key integer not null ); -- Each event can have custom fields registrants should enter. The -- event's custom fields are actually stored in the table, -- event_{$event_id}_info. For example, the event with event_id == 5 -- would have a corresponding table of event_5_info. Furthermore, this -- table will contain a "user_id not null references users" column -- This table describes the columns that go into event_{$event_id}_info create table events_event_fields ( event_id integer not null references events_events, column_name varchar(30) not null, pretty_name varchar(50) not null, -- something generic and suitable for handing to AOLserver, -- e.g., boolean or text column_type varchar(50) not null, -- something nitty gritty and Oracle-specific, e.g., -- char(1) instead of boolean -- things like "not null" column_actual_type varchar(100) not null, column_extra varchar(100), -- Sort key for display of columns. sort_key integer not null ); -- the organizers for events create table events_organizers_map ( event_id integer not null references events_events, user_id integer not null references users, role varchar(200) default 'organizer' not null, responsibilities varchar(4000) ); create sequence events_price_id_sequence; create table events_prices ( price_id integer primary key, event_id integer not null references events_events, -- e.g., "Developer", "Student" description varchar(100) not null, -- we also store the price here too in case someone doesnt want -- to use the ecommerce module but still wants to have prices price numeric not null, -- This is for hooking up to ecommerce. -- Each product is a different price for this event. For example, -- student price and normal price products for an event. -- product_id integer references ec_products, -- prices may be different for early, normal, late, on-site -- admission, -- depending on the date expire_date datetime not null, available_date datetime not null ); create sequence events_orders_id_sequence; create table events_orders ( order_id integer not null primary key, -- ec_order_id integer references ec_orders, -- the person who made the order user_id integer not null references users, paid_p char(1) default null check (paid_p in ('t', 'f', null)), payment_method varchar(50), confirmed_date datetime, price_charged numeric, -- the date this registration was refunded, if it was refunded refunded_date datetime, price_refunded numeric, ip_address varchar(50) not null ); create sequence events_reg_id_sequence; create table events_registrations( -- Goes into table at confirmation time: reg_id integer not null primary key, order_id integer not null references events_orders, price_id integer not null references events_prices, -- the person registered for this reg_id (may not be the person -- who made the order) user_id integer not null references users, -- reg_states: pending, shipped, canceled, refunded --pending: waiting for approval --shipped: registration all set --canceled: registration canceled --waiting: registration is wait-listed reg_state varchar(50) not null check (reg_state in ('pending', 'shipped', 'canceled', 'waiting')), -- when the registration was made reg_date datetime, -- when the registration was shipped shipped_date datetime, org varchar(4000), title_at_org varchar(4000), attending_reason varchar(4000), where_heard varchar(4000), -- does this person need a hotel? need_hotel_p char(1) default 'f' check (need_hotel_p in ('t', 'f')), -- does this person need a rental car? need_car_p char(1) default 'f' check (need_car_p in ('t', 'f')), -- does this person need airfare? need_plane_p char(1) default 'f' check (need_plane_p in ('t', 'f')), comments varchar(4000) ); -- trigger for recording when a registration ships create function trig_event_ship_date_trigger() returns opaque as ' DECLARE BEGIN IF TG_OP=''INSERT'' then if NEW.reg_state = ''shipped'' then NEW.shipped_date:=sysdate(); end if; else IF OLD.reg_state != ''shipped'' and NEW.reg_state=''shipped'' THEN NEW.shipped_date:= sysdate(); END IF; end if; return NEW; END; ' language 'plpgsql'; create trigger event_ship_date_trigger before insert or update on events_registrations for each row execute procedure trig_event_ship_date_trigger(); create view events_pending_orders as select * from events_registrations where reg_state='pending'; create view events_waiting_orders as select * from events_registrations where reg_state='waiting'; -- create a view that shows order states based upon each order's -- registrations. The order states are: -- void: All registrations canceled -- incomplete: This order is not completely fulfilled--some registrations -- are either canceled, waiting, or pending -- fulfilled: This order is completely fulfilled create view events_orders_states_helper as select order_id, case when (floor (avg (case when reg_state = 'canceled' then 0 when reg_state = 'waiting' then 1 when reg_state = 'pending' then 2 when reg_state = 'shipped' then 3 else 0 end)))=0 then 'canceled' when (floor (avg (case when reg_state = 'canceled' then 0 when reg_state = 'waiting' then 1 when reg_state = 'pending' then 2 when reg_state = 'shipped' then 3 else 0 end)))=1 then 'incomplete' when (floor (avg (case when reg_state = 'canceled' then 0 when reg_state = 'waiting' then 1 when reg_state = 'pending' then 2 when reg_state = 'shipped' then 3 else 0 end)))=2 then 'incomplete' when (floor (avg (case when reg_state = 'canceled' then 0 when reg_state = 'waiting' then 1 when reg_state = 'pending' then 2 when reg_state = 'shipped' then 3 else 0 end)))=3 then 'fulfilled' else 'void' end as order_state from events_registrations group by order_id; create view events_orders_states as select o.*, o_states.order_state from events_orders o, events_orders_states_helper o_states where o_states.order_id = o.order_id; create view events_reg_not_canceled as select * from events_registrations where reg_state <> 'canceled'; create view events_reg_canceled as select * from events_registrations where reg_state = 'canceled'; create view events_reg_shipped as select * from events_registrations where reg_state = 'shipped'; create sequence events_fs_file_id_seq start 1; create table events_file_storage ( file_id integer primary key, file_title varchar(300), -- file_content blob not null, client_file_name varchar(500), file_type varchar(100), file_extension varchar(50), on_which_table varchar(100) not null, on_what_id integer not null, -- the size (kB) of the fileument file_size integer, created_by integer references users, creation_ip_address varchar(100), creation_date datetime default current_timestamp ); create index events_file_storage_id_idx on events_file_storage(on_which_table, on_what_id); -- -- Outer join stuff -- -- BMA create function events_count_reg_shipped_by_price_id(integer) returns integer as ' DECLARE v_price_id alias for $1; BEGIN return count(*) from events_reg_shipped where price_id= v_price_id; END; ' language 'plpgsql'; create function events_count_pending_orders_by_price_id(integer) returns integer as ' DECLARE v_price_id alias for $1; BEGIN return count(*) from events_pending_orders where price_id= v_price_id; END; ' language 'plpgsql'; create function events_count_waiting_orders_by_price_id(integer) returns integer as ' DECLARE v_price_id alias for $1; BEGIN return count(*) from events_waiting_orders where price_id= v_price_id; END; ' language 'plpgsql';