-- Add fee payment model options to organizations table -- This determines whether customers pay the platform fee on top of the ticket price -- or if the fee is absorbed into the ticket price ALTER TABLE organizations ADD COLUMN platform_fee_model VARCHAR(20) DEFAULT 'customer_pays', ADD COLUMN absorb_fee_in_price BOOLEAN DEFAULT false; -- Update fee_structures table to include the fee model ALTER TABLE fee_structures ADD COLUMN fee_model VARCHAR(20) DEFAULT 'customer_pays', ADD COLUMN absorb_fee_in_price BOOLEAN DEFAULT false; -- Add comments for clarity COMMENT ON COLUMN organizations.platform_fee_model IS 'Fee payment model: customer_pays, absorbed_in_price'; COMMENT ON COLUMN organizations.absorb_fee_in_price IS 'Whether to hide fee by including it in the displayed ticket price'; COMMENT ON COLUMN fee_structures.fee_model IS 'Fee payment model: customer_pays, absorbed_in_price'; COMMENT ON COLUMN fee_structures.absorb_fee_in_price IS 'Whether to hide fee by including it in the displayed ticket price'; -- Update existing organizations with default fee model and actual BCT rates UPDATE organizations SET platform_fee_model = 'customer_pays', absorb_fee_in_price = false, platform_fee_percentage = 0.025, -- 2.5% BCT platform fee platform_fee_fixed = 150 -- $1.50 BCT platform fee WHERE platform_fee_model IS NULL; -- Update existing fee structure templates with actual rates UPDATE fee_structures SET fee_model = 'customer_pays', absorb_fee_in_price = false WHERE fee_model IS NULL; -- Update the default template to reflect actual BCT rates UPDATE fee_structures SET fee_percentage = 0.025, fee_fixed = 150, description = 'BCT platform fee: 2.5% + $1.50 per transaction' WHERE name = 'Standard Platform Fee' AND is_template = true; -- Add new fee structure templates with absorbed fee model and correct BCT rates INSERT INTO fee_structures (name, description, fee_type, fee_percentage, fee_fixed, fee_model, absorb_fee_in_price, is_template) VALUES ('All-Inclusive BCT Standard', 'BCT platform fee 2.5% + $1.50 included in ticket price', 'percentage_plus_fixed', 0.025, 150, 'absorbed_in_price', true, true), ('All-Inclusive Percentage Only', '2.5% fee included in ticket price', 'percentage', 0.025, 0, 'absorbed_in_price', true, true), ('All-Inclusive Fixed Only', '$1.50 fee included in ticket price', 'fixed', 0.0000, 150, 'absorbed_in_price', true, true), ('Premium All-Inclusive', 'Premium 3% + $2.00 fee included in ticket price', 'percentage_plus_fixed', 0.030, 200, 'absorbed_in_price', true, true); -- Add template for Stripe fee structure (for reference/calculation) INSERT INTO fee_structures (name, description, fee_type, fee_percentage, fee_fixed, fee_model, absorb_fee_in_price, is_template) VALUES ('Stripe Processing Fee', 'Stripe credit card processing: 2.99% + $0.30', 'percentage_plus_fixed', 0.0299, 30, 'customer_pays', false, true); -- Add function to calculate the display price based on fee model CREATE OR REPLACE FUNCTION calculate_display_price( base_price DECIMAL, fee_percentage DECIMAL DEFAULT 0.03, fee_fixed INTEGER DEFAULT 30, fee_type VARCHAR DEFAULT 'percentage_plus_fixed', fee_model VARCHAR DEFAULT 'customer_pays' ) RETURNS DECIMAL AS $$ DECLARE platform_fee DECIMAL; display_price DECIMAL; BEGIN -- Calculate platform fee based on fee type CASE fee_type WHEN 'percentage' THEN platform_fee := base_price * fee_percentage; WHEN 'fixed' THEN platform_fee := fee_fixed / 100.0; -- Convert cents to dollars WHEN 'percentage_plus_fixed' THEN platform_fee := (base_price * fee_percentage) + (fee_fixed / 100.0); ELSE platform_fee := (base_price * fee_percentage) + (fee_fixed / 100.0); END CASE; -- Calculate display price based on fee model CASE fee_model WHEN 'customer_pays' THEN -- Customer pays base price + platform fee display_price := base_price; WHEN 'absorbed_in_price' THEN -- Platform fee is absorbed into the display price -- To maintain the same net revenue for organizer, -- we need to increase the display price to cover the fee display_price := base_price + platform_fee; ELSE display_price := base_price; END CASE; RETURN ROUND(display_price, 2); END; $$ LANGUAGE plpgsql; -- Add function to calculate the total amount customer pays CREATE OR REPLACE FUNCTION calculate_customer_total( base_price DECIMAL, fee_percentage DECIMAL DEFAULT 0.03, fee_fixed INTEGER DEFAULT 30, fee_type VARCHAR DEFAULT 'percentage_plus_fixed', fee_model VARCHAR DEFAULT 'customer_pays' ) RETURNS DECIMAL AS $$ DECLARE platform_fee DECIMAL; customer_total DECIMAL; BEGIN -- Calculate platform fee based on fee type CASE fee_type WHEN 'percentage' THEN platform_fee := base_price * fee_percentage; WHEN 'fixed' THEN platform_fee := fee_fixed / 100.0; -- Convert cents to dollars WHEN 'percentage_plus_fixed' THEN platform_fee := (base_price * fee_percentage) + (fee_fixed / 100.0); ELSE platform_fee := (base_price * fee_percentage) + (fee_fixed / 100.0); END CASE; -- Calculate total amount customer pays CASE fee_model WHEN 'customer_pays' THEN -- Customer pays base price + platform fee separately customer_total := base_price + platform_fee; WHEN 'absorbed_in_price' THEN -- Customer pays only the display price (fee is included) customer_total := base_price; ELSE customer_total := base_price + platform_fee; END CASE; RETURN ROUND(customer_total, 2); END; $$ LANGUAGE plpgsql; -- Add function to calculate organizer net with fee model CREATE OR REPLACE FUNCTION calculate_organizer_net( base_price DECIMAL, fee_percentage DECIMAL DEFAULT 0.03, fee_fixed INTEGER DEFAULT 30, fee_type VARCHAR DEFAULT 'percentage_plus_fixed', fee_model VARCHAR DEFAULT 'customer_pays' ) RETURNS DECIMAL AS $$ DECLARE platform_fee DECIMAL; organizer_net DECIMAL; BEGIN -- Calculate platform fee based on fee type CASE fee_type WHEN 'percentage' THEN platform_fee := base_price * fee_percentage; WHEN 'fixed' THEN platform_fee := fee_fixed / 100.0; -- Convert cents to dollars WHEN 'percentage_plus_fixed' THEN platform_fee := (base_price * fee_percentage) + (fee_fixed / 100.0); ELSE platform_fee := (base_price * fee_percentage) + (fee_fixed / 100.0); END CASE; -- Calculate organizer net (what they receive) organizer_net := base_price - platform_fee; -- Ensure organizer net is never negative IF organizer_net < 0 THEN organizer_net := 0; END IF; RETURN ROUND(organizer_net, 2); END; $$ LANGUAGE plpgsql; -- Add indexes for performance CREATE INDEX idx_organizations_platform_fee_model ON organizations(platform_fee_model); CREATE INDEX idx_fee_structures_fee_model ON fee_structures(fee_model); -- Add check constraints to ensure valid fee models ALTER TABLE organizations ADD CONSTRAINT check_platform_fee_model CHECK (platform_fee_model IN ('customer_pays', 'absorbed_in_price')); ALTER TABLE fee_structures ADD CONSTRAINT check_fee_model CHECK (fee_model IN ('customer_pays', 'absorbed_in_price'));