create or replace function sos.register_user(_email text, _password_hash text) returns setof sos.user language plpgsql as $function$ declare _user_uuid uuid; begin insert into sos."user" ( user_email, user_password_hash ) values ( _email, _password_hash ) returning user_uuid into _user_uuid; return query select * from sos."user" where user_uuid = _user_uuid; end; $function$; create or replace function sos.validate_session(_session_uuid uuid) returns setof sos.v_session language plpgsql as $function$ begin return query select * from sos.v_session where session_uuid = _session_uuid and session_time_logged_out is null and session_time_last_active + session_timeout_length > now(); end; $function$; create or replace function sos.update_session(_session_uuid uuid) returns setof sos.v_session language plpgsql as $function$ begin update sos."session" set session_time_last_active = now() where session_uuid = _session_uuid and session_time_logged_out is null and now() < (select session_time_last_active + session_timeout_length); return query select * from sos.validate_session(_session_uuid); end; $function$; create or replace function sos.login_user_session(_user_uuid uuid, _timeout_length interval, _ip_addr varchar(50), _user_agent varchar(500), _referer varchar(500), _link uuid) returns setof sos.v_session language plpgsql as $function$ declare _session_uuid uuid; begin insert into sos."session" ( session_user_uuid, session_timeout_length, session_ip_address, session_user_agent, session_referer, session_originating_link ) values ( _user_uuid, _timeout_length, _ip_addr, _user_agent, _referer, _link ) returning session_uuid into _session_uuid; return query select * from sos.validate_session(_session_uuid); end; $function$; create or replace function sos.end_session(_session_uuid uuid) returns setof sos.v_session language plpgsql as $function$ begin update sos."session" set session_time_logged_out = now() where session_uuid = _session_uuid and session_time_logged_out is null and now() < (select session_time_last_active + session_timeout_length); return query select * from sos.validate_session(_session_uuid); end; $function$; create or replace function sos.create_item(_name text, _urlslug citext, _description text, _price_cents integer, _published boolean) returns setof sos.v_item language plpgsql as $function$ declare _item_uuid uuid; begin insert into sos."item" ( item_name, item_urlslug, item_description, item_price_cents, item_published ) values ( _name, _urlslug, _description, _price_cents, _published ) returning item_uuid into _item_uuid; return query select * from sos.v_item where item_uuid = _item_uuid; end; $function$; create or replace function sos.update_item(_uuid uuid, _name text, _urlslug citext, _description text, _price_cents integer, _published boolean) returns setof sos.v_item language plpgsql as $function$ begin update sos."item" set ( item_name, item_urlslug, item_description, item_price_cents, item_published ) = ( _name, _urlslug, _description, _price_cents, _published ) where item_uuid = _uuid; return query select * from sos.v_item where item_uuid = _uuid; end; $function$; create or replace function sos.add_image_to_item(_item_uuid uuid, _large_file bytea, _thumb_file bytea, _mime_type varchar, _uploader_uuid uuid) returns setof sos.v_item language plpgsql as $function$ declare _image_uuid uuid; begin insert into sos."image" ( image_item_uuid, image_large_file, image_thumb_file, image_mime_type, image_uploader_uuid ) values ( _item_uuid, _large_file, _thumb_file, _mime_type, _uploader_uuid ) returning image_uuid into _image_uuid; return query select * from sos.v_item where item_uuid = _item_uuid; end; $function$; create or replace function sos.set_featured_image(_item_uuid uuid, _image_uuid uuid) returns setof sos.v_item language plpgsql as $function$ begin -- Un-feature all other images update sos."image" set image_featured = false where image_item_uuid = _item_uuid; update sos."image" set image_featured = true where image_uuid = _image_uuid; return query select * from sos.v_item where item_uuid = _item_uuid; end; $function$; create or replace function sos.get_image_large(_image_uuid uuid) returns table (image_uuid uuid, image_mime_type varchar, image_file bytea) language plpgsql as $function$ begin return query select "image".image_uuid, "image".image_mime_type, "image".image_large_file as image_file from sos."image" where "image".image_uuid = _image_uuid; end; $function$; create or replace function sos.get_image_thumb(_image_uuid uuid) returns table (image_uuid uuid, image_mime_type varchar, image_file bytea) language plpgsql as $function$ begin return query select "image".image_uuid, "image".image_mime_type, "image".image_thumb_file as image_file from sos."image" where "image".image_uuid = _image_uuid; end; $function$; create or replace function sos.create_category(_category_name text, _category_urlslug citext, _category_description text) returns setof sos.v_category language plpgsql as $function$ declare _category_uuid uuid; begin insert into sos."category" ( category_name, category_urlslug, category_description ) values ( _category_name, _category_urlslug, _category_description ) returning category_uuid into _category_uuid; return query select * from sos.v_category where category_uuid = _category_uuid; end; $function$; create or replace function sos.add_item_to_category(_category_uuid uuid, _item_uuid uuid) returns setof sos.v_category language plpgsql as $function$ begin insert into sos."category_item" ( category_item_item_uuid, category_item_category_uuid ) values ( _item_uuid, _category_uuid ); return query select * from sos.v_category where category_uuid = _category_uuid; end; $function$; create or replace function sos.add_category_to_category(_parent_uuid uuid, _child_uuid uuid) returns setof sos.v_category language plpgsql as $function$ begin insert into sos."category_category" ( category_category_parent_uuid, category_category_child_uuid ) values ( _parent_uuid, _child_uuid ); return query select * from sos.v_category where category_uuid = _parent_uuid; end; $function$; create or replace function sos.create_cart(_session_uuid uuid) returns setof sos.v_cart language plpgsql as $function$ declare _cart_uuid uuid; begin insert into sos."cart" default values returning cart_uuid into _cart_uuid; update sos."session" set session_cart = _cart_uuid where session_uuid = _session_uuid and session_time_logged_out is null and now() < (select session_time_last_active + session_timeout_length); return query select * from sos.v_cart where cart_uuid = _cart_uuid; end; $function$; create or replace function sos.add_item_to_cart(_cart_uuid uuid, _item_uuid uuid, _amount integer) returns setof sos.v_cart language plpgsql as $function$ declare _row_count integer; begin -- Invalidate transactions that use this cart perform sos.cancel_transactions_for_cart(_cart_uuid); -- Check if we already have a row for this combination select count(*) into _row_count from sos.cart_item where cart_item_cart_uuid = _cart_uuid and cart_item_item_uuid = _item_uuid; -- If we found a row, increment otherwise insert if _row_count > 0 then update sos.cart_item set cart_item_count = cart_item_count + _amount where cart_item_cart_uuid = _cart_uuid and cart_item_item_uuid = _item_uuid; else insert into sos.cart_item ( cart_item_cart_uuid, cart_item_item_uuid, cart_item_count ) values ( _cart_uuid, _item_uuid, _amount ); end if; -- Return cart return query select * from sos.v_cart where cart_uuid = _cart_uuid; end; $function$; create or replace function sos.remove_item_from_cart(_cart_uuid uuid, _item_uuid uuid, _amount integer) returns setof sos.v_cart language plpgsql as $function$ declare _row_count integer; _current_amount integer; begin -- Invalidate transactions that use this cart perform sos.cancel_transactions_for_cart(_cart_uuid); -- Check if we already have a row for this combination select count(*), cart_item_count into _row_count, _current_amount from sos.cart_item where cart_item_cart_uuid = _cart_uuid and cart_item_item_uuid = _item_uuid group by cart_item_uuid, cart_item_count; -- If we do not have a row, just exit if _row_count < 1 then return query select * from sos.v_cart where cart_uuid = _cart_uuid; end if; -- If we do not have enough to decrement, delete row if _current_amount <= _amount then delete from sos.cart_item where cart_item_cart_uuid = _cart_uuid and cart_item_item_uuid = _item_uuid; -- Else, decrement row else update sos.cart_item set cart_item_count = cart_item_count - _amount where cart_item_cart_uuid = _cart_uuid and cart_item_item_uuid = _item_uuid; end if; -- Return cart return query select * from sos.v_cart where cart_uuid = _cart_uuid; end; $function$; create or replace function sos.remove_item_from_cart(_cart_uuid uuid, _item_uuid uuid) returns setof sos.v_cart language plpgsql as $function$ declare _row_count integer; begin -- Invalidate transactions that use this cart perform sos.cancel_transactions_for_cart(_cart_uuid); -- Check if we already have a row for this combination select count(*) into _row_count from sos.cart_item where cart_item_cart_uuid = _cart_uuid and cart_item_item_uuid = _item_uuid group by cart_item_uuid, cart_item_count; -- If we do not have a row, just exit if _row_count < 1 then return query select * from sos.v_cart where cart_uuid = _cart_uuid; end if; -- If we have a row, then delete it delete from sos.cart_item where cart_item_cart_uuid = _cart_uuid and cart_item_item_uuid = _item_uuid; -- Return cart return query select * from sos.v_cart where cart_uuid = _cart_uuid; end; $function$; create or replace function sos.publish_item(_item_uuid uuid) returns setof sos.v_item language plpgsql as $function$ begin update sos."item" set item_published = true where item_uuid = _item_uuid; return query select * from sos.v_item where item_uuid = _item_uuid; end; $function$; create or replace function sos.unpublish_item(_item_uuid uuid) returns setof sos.v_item language plpgsql as $function$ begin update sos."item" set item_published = false where item_uuid = _item_uuid; return query select * from sos.v_item where item_uuid = _item_uuid; end; $function$; create or replace function sos.create_order(_cart_uuid uuid) returns setof sos.v_order language plpgsql as $function$ declare _completed_transactions integer; _order_uuid uuid; _cart_price integer; begin -- Check for completed transactions select count(*) into _completed_transactions from sos."transaction" where transaction_cart_uuid = _cart_uuid and transaction_payment_state = 'completed'; if _completed_transactions > 0 then raise 'Cart has already been purchased'; end if; -- Check for existing transaction for this cart? select transaction_order_uuid into _order_uuid from sos."transaction" where transaction_cart_uuid = _cart_uuid and transaction_payment_state = 'started'; -- If no existing order, create an order and a transaction if _order_uuid is null then -- Create order insert into sos."order" default values returning order_uuid into _order_uuid; -- Get cart cost select cart_price into _cart_price from sos.v_cart_price where cart_uuid = _cart_uuid; -- Create transaction insert into sos."transaction" ( transaction_order_uuid, transaction_cart_uuid, transaction_item_total_price ) values ( _order_uuid, _cart_uuid, _cart_price ); end if; return query select * from sos.v_order where order_uuid = _order_uuid; end; $function$; create or replace function sos.cancel_transactions_for_cart(_cart_uuid uuid) returns void language plpgsql as $function$ declare _completed_transactions integer; begin select count(*) into _completed_transactions from sos."transaction" where transaction_cart_uuid = _cart_uuid and transaction_payment_state = 'completed'; if _completed_transactions > 0 then raise 'Cart has already been purchased'; end if; update sos."transaction" set ( transaction_completion_time, transaction_payment_state )= ( now(), 'cancelled' ) where transaction_cart_uuid = _cart_uuid and transaction_payment_state = 'started'; end; $function$; create or replace function sos.find_order_for_cart(_cart_uuid uuid) returns setof sos.v_order language plpgsql as $function$ declare _order_uuid uuid; begin select transaction_order_uuid into _order_uuid from sos."transaction" where transaction_cart_uuid = _cart_uuid and transaction_payment_state = 'started'; return query select * from sos.v_order where order_uuid = _order_uuid; end; $function$; create or replace function sos.create_address(_order_uuid uuid, _name text, _company text, _street1 text, _street2 text, _city text, _state text, _zip text, _country text, _phone text, _easypost_id text) returns setof sos.v_order language plpgsql as $function$ declare _address_uuid uuid; begin insert into sos."address" ( address_name, address_company, address_street1, address_street2, address_city, address_state, address_zip, address_country, address_phone, address_easypost_id ) values ( _name, _company, _street1, _street2, _city, _state, _zip, _country, _phone, _easypost_id ) returning address_uuid into _address_uuid; if _order_uuid is not null then update sos."order" set order_address_uuid = _address_uuid where order_uuid = _order_uuid; end if; return query select * from sos.v_order where address_uuid = _address_uuid; end; $function$;