Index: openacs-4/packages/dotlrn-ecommerce/www/ecommerce/checkout-2-oracle.xql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/dotlrn-ecommerce/www/ecommerce/checkout-2-oracle.xql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/dotlrn-ecommerce/www/ecommerce/checkout-2-oracle.xql 23 Jun 2005 12:28:22 -0000 1.1 @@ -0,0 +1,23 @@ + + + + + oracle + 8.1.6 + + + + + select p.no_shipping_avail_p, p.product_name, p.one_line_description, p.product_id, count(*) as quantity, u.offer_code, i.color_choice, i.size_choice, i.style_choice + from ec_orders o, ec_items i, ec_products p, (select offer_code, product_id + from ec_user_session_offer_codes usoc + where usoc.user_session_id=:user_session_id) u + where i.product_id=p.product_id + and o.order_id=i.order_id + and p.product_id= u.product_id(+) + and o.user_session_id=:user_session_id and o.order_state='in_basket' + group by p.no_shipping_avail_p, p.product_name, p.one_line_description, p.product_id, u.offer_code, i.color_choice, i.size_choice, i.style_choice + + + + Index: openacs-4/packages/dotlrn-ecommerce/www/ecommerce/checkout-2.adp =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/dotlrn-ecommerce/www/ecommerce/checkout-2.adp,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/dotlrn-ecommerce/www/ecommerce/checkout-2.adp 23 Jun 2005 12:28:22 -0000 1.1 @@ -0,0 +1,28 @@ + + Completing Your Order: Verify shopping cart contents + @context_bar;noquote@ + @ec_system_owner;noquote@ + + + +
+ +

Please verify that the items and quantities shown below are correct. Put a 0 (zero) in the + Quantity field to remove a particular item from your order.

+ +
+ + + + + + + @rows_of_items;noquote@ +
QuantityItem
+ +

@tax_exempt_options;noquote@

+ +
+ +
+
Index: openacs-4/packages/dotlrn-ecommerce/www/ecommerce/checkout-2.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/dotlrn-ecommerce/www/ecommerce/checkout-2.tcl,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/dotlrn-ecommerce/www/ecommerce/checkout-2.tcl 23 Jun 2005 12:28:22 -0000 1.1 @@ -0,0 +1,192 @@ +ad_page_contract { + @param address_id a stored address + @param usca_p User session started or not + + @author + @creation-date + @author ported by Jerry Asher (jerry@theashergroup.com) + @author Bart Teeuwisse (bart.teeuwisse@thecodemill.biz) + @revision-date April 20002 + +} { + address_id:optional,naturalnum + usca_p:optional +} + +# ec_redirect_to_https_if_possible_and_necessary + +# We need them to be logged in + +set user_id [ad_verify_and_get_user_id] +if {$user_id == 0} { + set return_url "[ad_conn url]" + ad_returnredirect "/register?[export_url_vars return_url]" + ad_script_abort +} + +# User sessions: +# 1. get user_session_id from cookie +# 2. if user has no session (i.e. user_session_id=0), attempt to set it if it hasn't been +# attempted before +# 3. if it has been attempted before, give them message that we can't do shopping carts +# without cookies + +set user_session_id [ec_get_user_session_id] +ec_create_new_session_if_necessary [export_url_vars address_id] + +# Make sure they have an in_basket order, otherwise they've probably +# gotten here by pushing Back, so return them to index.tcl + +set success_p [db_0or1row get_order_id_and_order_owner " + select order_id, user_id as order_owner + from ec_orders + where user_session_id = :user_session_id + and order_state='in_basket' "] +if { ! $success_p } { + + # No rows came back, so they probably got here by pushing "Back", + # so just redirect them to index.tcl + + rp_internal_redirect index + ad_script_abort +} + +if { $order_owner != $user_id } { + + # make sure the order belongs to this user_id (why? because + # before this point there was no personal information associated + # with the order (so it was fine to go by user_session_id), but + # now there is, and we don't want someone messing with their + # user_session_id cookie and getting someone else's order) + + # If they get here, either they managed to skip past checkout.tcl, + # or they messed w/their user_session_id cookie; + ad_returnredirect [ec_securelink [ec_url]checkout.tcl] + ad_script_abort +} + +# Make sure there's something in their shopping cart, otherwise +# redirect them to their shopping cart which will tell them that it's +# empty. + +if { [db_string get_ec_item_count " + select count(*) + from ec_items + where order_id=:order_id"] == 0 } { + rp_internal_redirect shopping-cart + ad_script_abort +} + +# Either address_id should be a form variable, or it should already be +# in the database for this order + +# Make sure address_id, if it exists, belongs to them, otherwise +# they've probably gotten here by form surgery, in which case send +# them back to checkout.tcl if it is theirs, put it into the database +# for this order + +# If address_id doesn't exist, make sure there is an address for this +# order, otherwise they've probably gotten here via url surgery, so +# redirect them to checkout.tcl + +if { [info exists address_id] && ![empty_string_p $address_id] } { + set n_this_address_id_for_this_user [db_string get_an_address_id " + select count(*) + from ec_addresses + where address_id = :address_id + and user_id=:user_id"] + if {$n_this_address_id_for_this_user == 0} { + ad_returnredirect [ec_securelink [ec_url]checkout] + ad_script_abort + } + + # It checks out ok + + db_dml update_ec_order_address " + update ec_orders + set shipping_address = :address_id + where order_id = :order_id" +} else { + + set address_id [db_string get_address_id " + select shipping_address + from ec_orders + where order_id=:order_id" -default ""] + if { [empty_string_p $address_id] } { + + # No shipping address is needed if the order only consists of + # soft goods not requiring shipping. + + if {[db_0or1row shipping_avail " + select p.no_shipping_avail_p, count (*) + from ec_items i, ec_products p + where i.product_id = p.product_id + and p.no_shipping_avail_p = 'f' + and i.order_id = :order_id + group by no_shipping_avail_p"]} { + ad_returnredirect [ec_securelink [ec_url]checkout] + ad_script_abort + } + } +} + +# Everything is ok now; the user has a non-empty in_basket order and +# an address associated with it, so now get the other necessary +# information + +set form_action [ec_securelink [ec_url]select-shipping] +set rows_of_items "" +set shipping_avail_p 1 + +db_foreach get_shipping_data " + select p.no_shipping_avail_p, p.product_name, p.one_line_description, p.product_id, count(*) as quantity, u.offer_code, i.color_choice, i.size_choice, i.style_choice + from ec_orders o, ec_items i, ec_products p, (select offer_code, product_id + from ec_user_session_offer_codes usoc + where usoc.user_session_id=:user_session_id) u + where i.product_id=p.product_id + and o.order_id=i.order_id + and p.product_id= u.product_id(+) + and o.user_session_id=:user_session_id and o.order_state='in_basket' + group by p.no_shipping_avail_p, p.product_name, p.one_line_description, p.product_id, u.offer_code, i.color_choice, i.size_choice, i.style_choice" { + + if { [string compare $no_shipping_avail_p "t"] == 0 } { + set shipping_avail_p 0 + } + + set option_list [list] + if { ![empty_string_p $color_choice] } { + lappend option_list "Color: $color_choice" + } + if { ![empty_string_p $size_choice] } { + lappend option_list "Size: $size_choice" + } + if { ![empty_string_p $style_choice] } { + lappend option_list "Style: $style_choice" + } + set options [join $option_list ", "] + + # Trying out the fancy new . arrays. It would be much better to + # rework this for a 2D array,multiple setup, but I don't have time + # to think about it now... + + append rows_of_items " + + + $product_name[ec_decode $options "" "" ", $options"]
+ [ec_price_line $product_id $user_id $offer_code] + " +} + +set tax_exempt_options "" +if { [ad_parameter -package_id [ec_id] OfferTaxExemptStatusP ecommerce 0] } { + append tax_exempt_options " +

  • Is your organization tax exempt? (If so, we will ask you to + provide us with an exemption certificate.)

    + Yes
    + No" +} + +set context_bar [template::adp_parse [acs_root_dir]/packages/[ad_conn package_key]/www/contextbar [list context_addition [list "Completing Your Order"]]] +set ec_system_owner [ec_system_owner] +db_release_unused_handles +ad_return_template Index: openacs-4/packages/dotlrn-ecommerce/www/ecommerce/checkout-2.xql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/dotlrn-ecommerce/www/ecommerce/checkout-2.xql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/dotlrn-ecommerce/www/ecommerce/checkout-2.xql 23 Jun 2005 12:28:22 -0000 1.1 @@ -0,0 +1,63 @@ + + + + + + + select order_id, + user_id as order_owner + from ec_orders + where user_session_id=:user_session_id + and order_state='in_basket' + + + + + + select count(*) + from ec_items + where order_id=:order_id + + + + + + select count(*) + from ec_addresses + where address_id=:address_id + and user_id=:user_id + + + + + + update ec_orders set shipping_address=:address_id where order_id=:order_id + + + + + + select shipping_address + from ec_orders + where order_id=:order_id + + + + + + select p.no_shipping_avail_p, p.product_name, p.one_line_description, p.product_id, + count(*) as quantity, + u.offer_code, + i.color_choice, i.size_choice, i.style_choice + from ec_orders o + join ec_items i on (o.order_id=i.order_id) + join ec_products p on (i.product_id=p.product_id) + left join (select offer_code, product_id + from ec_user_session_offer_codes usoc + where usoc.user_session_id=:user_session_id) u on (p.product_id = u.product_id) + where o.user_session_id=:user_session_id and o.order_state='in_basket' + group by p.no_shipping_avail_p, p.product_name, p.one_line_description, p.product_id, u.offer_code, i.color_choice, i.size_choice, i.style_choice + + + + Index: openacs-4/packages/dotlrn-ecommerce/www/ecommerce/checkout-3-oracle.xql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/dotlrn-ecommerce/www/ecommerce/checkout-3-oracle.xql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/dotlrn-ecommerce/www/ecommerce/checkout-3-oracle.xql 23 Jun 2005 12:28:22 -0000 1.1 @@ -0,0 +1,23 @@ + + + + + oracle + 8.1.6 + + + + + select ec_order_cost(:order_id) + from dual + + + + + + select ec_gift_certificate_balance(:user_id) + from dual + + + + Index: openacs-4/packages/dotlrn-ecommerce/www/ecommerce/checkout-3-postgresql.xql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/dotlrn-ecommerce/www/ecommerce/checkout-3-postgresql.xql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/dotlrn-ecommerce/www/ecommerce/checkout-3-postgresql.xql 23 Jun 2005 12:28:22 -0000 1.1 @@ -0,0 +1,21 @@ + + + + + postgresql + 7.1 + + + + + select ec_order_cost(:order_id) + + + + + + select ec_gift_certificate_balance(:user_id) + + + + Index: openacs-4/packages/dotlrn-ecommerce/www/ecommerce/checkout-3.adp =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/dotlrn-ecommerce/www/ecommerce/checkout-3.adp,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/dotlrn-ecommerce/www/ecommerce/checkout-3.adp 23 Jun 2005 12:28:22 -0000 1.1 @@ -0,0 +1,24 @@ + + Completing Your Order: Verify and submit order + @context_bar;noquote@ + @ec_system_owner;noquote@ + + + + + +
    + +
    + + +

    Push to send us your order! +

    + + @order_summary;noquote@ + +

    Push to send us your order! +

    +
    + +
    Index: openacs-4/packages/dotlrn-ecommerce/www/ecommerce/checkout-3.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/dotlrn-ecommerce/www/ecommerce/checkout-3.tcl,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/dotlrn-ecommerce/www/ecommerce/checkout-3.tcl 23 Jun 2005 12:28:22 -0000 1.1 @@ -0,0 +1,165 @@ +ad_page_contract { + + Users should get here from + process-order-quantity-payment-shipping.tcl; this page just + summarizes their order before they submit it. + + @param usca_p User session begun or not + @param referer Referring page + + @author + @creation-date + @author ported by Jerry Asher (jerry@theashergroup.com) + @author revised by Bart Teeuwisse (bart.teeuwisse@thecodemill.biz) + @revision-date April 2002 + +} { + usca_p:optional + referer:optional + + user_id:integer,notnull + participant_id:integer,optional +} + +ec_redirect_to_https_if_possible_and_necessary + +# Make sure we have all their necessary info, otherwise they probably got +# here via url surgery or by pushing Back + +# 1. There should be an in_basket order for their user_session_id. +# 2. The order should have the correct user_id associated with it. +# 3. The order should contain items. +# 4. The order should have an address associated with it. +# 5. The order should have credit card and shipping method associated with it. + +# We need them to be logged in + +#set user_id [ad_verify_and_get_user_id] +if {$user_id == 0} { + set return_url "[ad_conn url]" + ad_returnredirect "/register?[export_url_vars return_url]" + ad_script_abort +} + +# Make sure they have an in_basket order, otherwise they've probably +# gotten here by pushing Back, so return them to index.tcl + +set user_session_id [ec_get_user_session_id] +ec_create_new_session_if_necessary +set order_id [db_string get_order_id " + select order_id + from ec_orders + where user_session_id=:user_session_id + and order_state='in_basket'" -default ""] +if { [empty_string_p $order_id] } { + + # Then they probably got here by pushing "Back", so just redirect + # them to index.tcl + ns_log Notice "checkout-3.tcl ref(55): user_id:$user_id, user_session_id:$user_session_id, order_id is empty, redirecting to index" + rp_internal_redirect index + ad_script_abort +} + +# Make sure there's something in their shopping cart, otherwise +# redirect them to their shopping cart which will tell them that it's +# empty. + +if { [db_string get_ec_item_count " + select count(*) + from ec_items + where order_id=:order_id"] == 0 } { + ns_log Notice "checkout-3.tcl ref(68): order_id:$order_id, no items in basket, redirecting to shopping-cart" + rp_internal_redirect shopping-cart + ad_script_abort +} + +# Make sure the order belongs to this user_id, otherwise they managed +# to skip past checkout*.tcl, or they messed w/their user_session_id +# cookie + +set order_owner [db_string get_order_owner " + select user_id + from ec_orders + where order_id=:order_id"] +if { $order_owner != $user_id } { + ns_log Notice "checkout-3.tcl ref(82): order_owner:$order_owner not matching order_id:$order_id, redirecting to checkout" + rp_internal_redirect checkout + ad_script_abort +} + +# Make sure there is an address for this order, otherwise they've +# probably gotten here via url surgery, so redirect them to +# checkout.tcl + +# set address_id [db_string get_address_id " +# select shipping_address +# from ec_orders +# where order_id=$order_id" -default ""] +# if { [empty_string_p $address_id] } { + +# # No shipping address is needed if the order only consists of soft +# # goods not requiring shipping. + +# if {[db_0or1row shipping_avail " +# select p.no_shipping_avail_p, count (*) +# from ec_items i, ec_products p +# where i.product_id = p.product_id +# and p.no_shipping_avail_p = 'f' +# and i.order_id = :order_id +# group by no_shipping_avail_p"]} { +# ns_log Notice "checkout-3.tcl ref(110): no shipping address needed for order_id:$order_id, redirecting to checkout" +# ad_returnredirect [ec_securelink [ec_url]checkout] +# ad_script_abort +# } +# } + +# Make sure there is a credit card (or that the +# gift_certificate_balance covers the cost) and a shipping method for +# this order, otherwise they've probably gotten here via url surgery, +# so redirect them to checkout-2.tcl + +set creditcard_id [db_string get_creditcard_id " + select creditcard_id + from ec_orders + where order_id=:order_id" -default ""] +if { [empty_string_p $creditcard_id] } { + + # Ec_order_cost returns price + shipping + tax - gift_certificate + # BUT no gift certificates have been applied to in_basket orders, + # so this just returns price + shipping + tax + + set order_total_price_pre_gift_certificate [db_string get_pre_gc_price " + select ec_order_cost(:order_id) + from dual"] + set gift_certificate_balance [db_string get_gc_balance " + select ec_gift_certificate_balance(:user_id) + from dual"] + if { $gift_certificate_balance < $order_total_price_pre_gift_certificate } { + set gift_certificate_covers_cost_p "f" + } else { + set gift_certificate_covers_cost_p "t" + } +} + +# set shipping_method [db_string get_shipping_method " +# select shipping_method +# from ec_orders +# where order_id=:order_id" -default ""] +# if { [empty_string_p $shipping_method] || ([empty_string_p $creditcard_id] && [exists_and_equal gift_certificate_covers_cost_p "f"]) } { +# ns_log Notice "checkout-3.tcl ref(146): no shipping method for order_id:$order_id. Redirecting to checkout-2" +# rp_internal_redirect checkout-2 +# ad_script_abort +# } + +# Done with all the checks. Their order is ready to go! Now show +# them a summary before they submit their order +#if {[exists_and_equal referer "checkout-one-form-2"]} { + set display_progress "f" +#} else { +# set display_progress "t" +#} + +set order_summary [ec_order_summary_for_customer $order_id $user_id] +set context_bar [template::adp_parse [acs_root_dir]/packages/[ad_conn package_key]/www/contextbar [list context_addition [list "Completing Your Order"]]] +set ec_system_owner [ec_system_owner] +db_release_unused_handles Index: openacs-4/packages/dotlrn-ecommerce/www/ecommerce/checkout-3.xql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/dotlrn-ecommerce/www/ecommerce/checkout-3.xql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/dotlrn-ecommerce/www/ecommerce/checkout-3.xql 23 Jun 2005 12:28:22 -0000 1.1 @@ -0,0 +1,54 @@ + + + + + + + select order_id + from ec_orders + where user_session_id=:user_session_id + and order_state='in_basket' + + + + + + select count(*) + from ec_items + where order_id=:order_id + + + + + + select user_id + from ec_orders + where order_id=:order_id + + + + + + select shipping_address + from ec_orders + where order_id=$order_id + + + + + + select creditcard_id + from ec_orders + where order_id=:order_id + + + + + + select shipping_method + from ec_orders + where order_id=:order_id + + + + Index: openacs-4/packages/dotlrn-ecommerce/www/ecommerce/checkout-one-form-2-oracle.xql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/dotlrn-ecommerce/www/ecommerce/checkout-one-form-2-oracle.xql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/dotlrn-ecommerce/www/ecommerce/checkout-one-form-2-oracle.xql 23 Jun 2005 12:28:22 -0000 1.1 @@ -0,0 +1,52 @@ + + + + + + insert into ec_problems_log + (problem_id, problem_date, gift_certificate_id, problem_details) + values + (ec_problem_id_sequence.nextval, sysdate, :gift_certificate_id, :prob_details) + + + + + + select i.item_id, i.product_id, u.offer_code + from ec_items i, (select * + from ec_user_session_offer_codes usoc + where usoc.user_session_id = :user_session_id) u + where i.product_id=u.product_id(+) + and i.order_id=:order_id + + + + + + select nvl(base_shipping_cost,0) + from ec_admin_settings + + + + + + select nvl(add_exp_base_shipping_cost,0) + from ec_admin_settings + + + + + + select ec_tax(0,:order_shipping_cost,:order_id) + from dual + + + + + + select ec_gift_certificate_balance(:user_id) + from dual + + + + Index: openacs-4/packages/dotlrn-ecommerce/www/ecommerce/checkout-one-form-2-postgresql.xql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/dotlrn-ecommerce/www/ecommerce/checkout-one-form-2-postgresql.xql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/dotlrn-ecommerce/www/ecommerce/checkout-one-form-2-postgresql.xql 23 Jun 2005 12:28:22 -0000 1.1 @@ -0,0 +1,70 @@ + + + + + postgresql + 7.1 + + + + + insert into ec_problems_log + (problem_id, problem_date, problem_details) + values + (ec_problem_id_sequence.nextval, current_timestamp,:prob_details ) + + + + + + update ec_gift_certificates set user_id=:user_id, claimed_date=current_timestamp where gift_certificate_id=:gift_certificate_id + + + + + + insert into ec_problems_log + (problem_id, problem_date, gift_certificate_id, problem_details) + values + (ec_problem_id_sequence.nextval, current_timestamp, :gift_certificate_id, :prob_details) + + + + + + select i.item_id, i.product_id, u.offer_code + from ec_items i + left join (select * + from ec_user_session_offer_codes usoc + where usoc.user_session_id=:user_session_id) u on (i.product_id=u.product_id) + where i.order_id=:order_id + + + + + + select coalesce(base_shipping_cost,0) + from ec_admin_settings + + + + + + select coalesce(add_exp_base_shipping_cost,0) + from ec_admin_settings + + + + + + select ec_tax(0,:order_shipping_cost,:order_id) + + + + + + select ec_gift_certificate_balance(:user_id) + + + + Index: openacs-4/packages/dotlrn-ecommerce/www/ecommerce/checkout-one-form-2.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/dotlrn-ecommerce/www/ecommerce/checkout-one-form-2.tcl,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/dotlrn-ecommerce/www/ecommerce/checkout-one-form-2.tcl 23 Jun 2005 12:28:22 -0000 1.1 @@ -0,0 +1,879 @@ +ad_page_contract { + + @param billing_address_id + @param bill_to_first_names + @param bill_to_last_name + @param bill_to_phone + @param bill_to_phone_time:optional + @param bill_to_line1:notnull + @param bill_to_line2 + @param bill_to_city + @param bill_to_usps_abbrev:optional + @param bill_to_full_state_name:optional + @param bill_to_zip_code:optional + @param bill_to_country_code + + @param claim_check for gift certificate + @param creditcard_expire_1:optional + @param creditcard_expire_2:optional + @param creditcard_number:optional + @param creditcard_type:optional + @param creditcard_id:optional + @param customer_can_use_old_credit_cards:optional + @param old_cards_to_choose_from:optional + + @param certificate_amount:optional + @param order_total_price_pre_gift_certificate:optional + + @param shipping_address_id:optional,naturalnum + @param ship_to_first_names:optional + @param ship_to_last_name:optional + @param ship_to_phone:optional + @param ship_to_phone_time:optional + @param ship_to_line1:optional + @param ship_to_line2:optional + @param ship_to_city:optional + @param ship_to_usps_abbrev:optional + @param ship_to_full_state_name:optional + @param ship_to_zip_code:optional + @param ship_to_country_code:optional + + @param shipping_method:optional + @param shipping_options:optional + + @param tax_exempt_p:optional + @param usca_p:optional + @param value_currency_code:optional + + @author + @creation-date April 2002 + @author ported by Jerry Asher (jerry@theashergroup.com) + @author revised by Bart Teeuwisse + @author combined by Torben Brosten + @creation-date March 2004 + +} { + + billing_address_id:optional,naturalnum + bill_to_first_names + bill_to_last_name + bill_to_phone + bill_to_phone_time:optional + bill_to_line1:notnull + bill_to_line2:optional + bill_to_city + bill_to_usps_abbrev:optional + bill_to_full_state_name:optional + bill_to_zip_code:optional + bill_to_country_code + + claim_check:optional + creditcard_expire_1:optional + creditcard_expire_2:optional + creditcard_number:optional + creditcard_type:optional + creditcard_id:optional + customer_can_use_old_credit_cards:optional + old_cards_to_choose_from:optional + + certificate_amount:optional + order_total_price_pre_gift_certificate:optional + + shipping_address_id:optional,naturalnum + ship_to_first_names:optional + ship_to_last_name:optional + ship_to_phone:optional + ship_to_phone_time:optional + ship_to_line1:optional + ship_to_line2:optional + ship_to_city:optional + ship_to_usps_abbrev:optional + ship_to_full_state_name:optional + ship_to_zip_code:optional + ship_to_country_code:optional + + shipping_method:optional + shipping_options:optional + + tax_exempt_p:optional + usca_p:optional + value_currency_code:optional + + user_id:integer,notnull + participant_id:integer,optional + + {method cc} + internal_account:optional +} + +# We need them to be logged in + +#set user_id [ad_conn user_id] +if {$user_id == 0} { + ns_log Notice "checkout-one-form-2.tcl,ref(137): user_id is 0 which should never happen, redirecting user." + rp_form_put return_url "[ad_conn url]?[export_entire_form_as_url_vars]" + rp_internal_redirect "/register" + ad_script_abort +} + +# eventually evolve this so checks come first, then ad_return_complaints +# ie show complaints after all input has been checked, to provide thorough feedback to user + + +if {![info exists bill_to_country_code]} { + ad_return_complaint 1 [list [list bill_to_country_code "billing country"]] + ad_script_abort +} elseif { [string equal $bill_to_country_code "US"] } { + set possible_exception_list [list [list bill_to_first_names "billing first name"] [list bill_to_last_name "billing last name"] [list bill_to_line1 "billing street address"] [list bill_to_city "billing city"] [list bill_to_usps_abbrev "billing state"] [list bill_to_zip_code "billing zip code"] [list bill_to_phone "billing telephone number"]] +} else { + set possible_exception_list [list [list bill_to_first_names "billing first name"] [list bill_to_last_name "billing last name"] [list bill_to_line1 "billing street address"] [list bill_to_city "billing city"] [list bill_to_country_code "billing country"] [list bill_to_phone "billing telephone number"]] +} +set exception_count 0 +set exception_text "" + +foreach possible_exception $possible_exception_list { + if { ![info exists [lindex $possible_exception 0]] || [empty_string_p [set [lindex $possible_exception 0]]] } { + incr exception_count + append exception_text "
  • A [lindex $possible_exception 1] is required.
  • " + } +} + +if { $exception_count > 0 } { + ns_log Notice "checkout-one-form-2.tcl,ref(127): $exception_count form input exception(s) for user $user_id" + ad_return_complaint $exception_count $exception_text + ad_script_abort +} + + +# Make sure they have an in_basket order unless they are ordering a +# gift certificate, otherwise they've probably gotten here by pushing +# Back, so return them to index.tcl + +set user_session_id [ec_get_user_session_id] +set order_id [db_string get_order_id " + select order_id + from ec_orders + where user_session_id = :user_session_id + and order_state = 'in_basket'" -default ""] + +if { [empty_string_p $order_id] } { + + # They probably got here by pushing "Back", so just redirect + # them to index.tcl + ns_log Notice "checkout-one-form-2.tcl,ref(157): order_id is empty, redirecting user $user_id." + rp_internal_redirect index + ad_script_abort +} +ns_log Notice "checkout-one-form-2.tcl,ref(161): processing user_id: $user_id, order_id: $order_id" + +# start processing the info from checkout-one-form + + +# check addresses against existing addresses, if any (bill_to_address_id_exists_p, ship_to_address_id_exists_p +# if there's any difference, then assume it's a new address, otherwise, use existing address_id + +# for billing address + +regsub -all { +} $bill_to_first_names " " bill_to_first_names +regsub -all { +} $bill_to_last_name " " bill_to_last_name +set bill_to_attn "[string trim $bill_to_first_names] [string trim $bill_to_last_name]" + +if { [value_if_exists billing_address_id] > 0} { + + # This is an existing address that might have been edited + + set address_id $billing_address_id + + # retrieve a saved address + set billing_address_exists [db_0or1row select_address " + select attn, line1, line2, city, usps_abbrev, zip_code, phone, country_code, full_state_name, phone_time + from ec_addresses + where address_id=:address_id + and user_id=:user_id"] + + if { $billing_address_exists == 0 } { + # They probably got here by playing with the billing_address_id number + # have them login again, to make sure they should even have access to current session + + ec_user_session_logout + ns_log Notice "checkout-one-form-2.tcl,ref(193): billing_address_id mismatch. logging out user $user_id." + } + + # compare billing address with address from db + + set combined_billing_address "${bill_to_attn}${bill_to_line1}${bill_to_line2}${bill_to_city}${bill_to_usps_abbrev}${bill_to_zip_code}${bill_to_phone}${bill_to_country_code}${bill_to_full_state_name}${bill_to_phone_time}" + set combined_address "${attn}${line1}${line2}${city}${usps_abbrev}${zip_code}${phone}${country_code}${full_state_name}${phone_time}" + regsub -all { } $combined_billing_address "" combined_billing_address + regsub -all { } $combined_address "" combined_address + if { [string equal $combined_billing_address $combined_address] != 1 } { + set new_address "t" + } else { + # billing addresses same + set new_address "f" + } +} else { + # no billing address id exists + set new_address "t" +} + +if { [string equal $new_address "t"] } { + # This is a new address which requires a new address_id. + set address_type "billing" + set attn $bill_to_attn + set line1 $bill_to_line1 + set line2 $bill_to_line2 + set city $bill_to_city + if {[info exists bill_to_usps_abbrev]} { + set usps_abbrev $bill_to_usps_abbrev + } else { + # billing address, bill_to_usps_abbrev does not exist + set usps_abbrev "" + } + if {[info exists bill_to_zip_code]} { + set zip_code [string range $bill_to_zip_code 0 9] + } else { + set zip_code "" + } + set phone $bill_to_phone + set country_code $bill_to_country_code + set full_state_name $bill_to_full_state_name + set phone_time $bill_to_phone_time + set address_id [db_nextval ec_address_id_sequence] + db_transaction { + db_dml insert_new_address " + insert into ec_addresses + (address_id, user_id, address_type, attn, line1, line2, city, usps_abbrev, full_state_name, zip_code, country_code, phone, phone_time) + values + (:address_id, :user_id, :address_type, :attn,:line1,:line2,:city,:usps_abbrev,:full_state_name,:zip_code,:country_code,:phone,:phone_time)" + } + # ec_orders does not track billing address directly, so won't insert an address_id to it. +} + +set billing_address_id $address_id + +# Check if the order requires shipping + +if {[db_0or1row shipping_avail " + select p.no_shipping_avail_p + from ec_items i, ec_products p + where i.product_id = p.product_id + and p.no_shipping_avail_p = 'f' + and i.order_id = :order_id + group by no_shipping_avail_p"]} { + + set shipping_required "t" + +} else { + set shipping_required "f" +} + +set combined_shipping_address "" + +if { [string equal $shipping_required "t"] } { +# when ship_to_address info is empty, fill it with the bill_to address info and set ship_to_address_id_exists_p false + + # get the shipping_address_id used by checkout-one-form.tcl + set shipping_address_ids [db_list get_shipping_address_ids " + select address_id + from ec_addresses + where user_id=:user_id + and address_type = 'shipping'" ] + set shipping_address_id [ec_max_of_list $shipping_address_ids] + + + # Update the shipping address of the order + regsub -all { +} $ship_to_first_names " " ship_to_first_names + regsub -all { +} $ship_to_last_name " " ship_to_last_name + set ship_to_attn "[string trim $ship_to_first_names] [string trim $ship_to_last_name]" + + # lets combine the shipping address, for comparison to any existing default, and to see if there is anything to work with + set combined_shipping_address "${ship_to_attn}${ship_to_line1}${ship_to_line2}${ship_to_city}${ship_to_usps_abbrev}${ship_to_zip_code}${ship_to_phone}${ship_to_country_code}${ship_to_full_state_name}${ship_to_phone_time}" + regsub -all { } $combined_shipping_address "" combined_shipping_address + + # check addresses against existing addresses, if any (bill_to_address_id_exists_p, ship_to_address_id_exists_p + # if there's any difference, then assume it's a new address, otherwise, use existing address_id + + if { $shipping_address_id > 0 } { + + # Shipping address was presented to user, the existing address info might have been edited + set address_id $shipping_address_id + + # retrieve a saved address + set shipping_address_exists [db_0or1row select_address " + select attn, line1, line2, city, usps_abbrev, zip_code, phone, country_code, full_state_name, phone_time + from ec_addresses + where address_id=:address_id + and user_id=:user_id"] + + if { $shipping_address_exists == 0 } { + # They probably got here by playing with the shipping_address_id number + # have them login again, to make sure they should even have access to current session + ns_log Notice "checkout-one-form-2.tcl,ref(305). shipping_address_id is 0 which should never happen. logging out user $user_id" + ec_user_session_logout + } + + # compare shipping address with address from db + + set combined_address "${attn}${line1}${line2}${city}${usps_abbrev}${zip_code}${phone}${country_code}${full_state_name}${phone_time}" + regsub -all { } $combined_address "" combined_address + + if { [string equal $combined_shipping_address $combined_address] != 1 } { + set new_address "t" + } else { + # addresses are the same + set new_address "f" + } + + } else { + # no previous shipping address, so address must be new + set new_address "t" + + } + + if { [string equal $new_address "t"] } { + + if { [string length $combined_shipping_address] < 15 } { + # shipping address must be blank, replace with billing address + + set ship_to_attn $bill_to_attn + set ship_to_line1 $bill_to_line1 + set ship_to_line2 $bill_to_line2 + set ship_to_city $bill_to_city + if {[info exists bill_to_usps_abbrev]} { + set ship_to_usps_abbrev $bill_to_usps_abbrev + } else { + set ship_to_usps_abbrev "" + } + if {[info exists bill_to_zip_code]} { + set ship_to_zip_code $bill_to_zip_code + } else { + set ship_to_zip_code "" + } + set ship_to_phone $bill_to_phone + set ship_to_country_code $bill_to_country_code + set ship_to_full_state_name $bill_to_full_state_name + set ship_to_phone_time $bill_to_phone_time + } + + # This is a new address which requires an address_id. + set address_type "shipping" + set attn $ship_to_attn + set line1 $ship_to_line1 + set line2 $ship_to_line2 + set city $ship_to_city + set usps_abbrev $ship_to_usps_abbrev + set zip_code [string range $ship_to_zip_code 0 9] + set phone $ship_to_phone + set country_code $ship_to_country_code + set full_state_name $ship_to_full_state_name + set phone_time $ship_to_phone_time + set address_id [db_nextval ec_address_id_sequence] + db_transaction { + db_dml insert_new_address " + insert into ec_addresses + (address_id, user_id, address_type, attn, line1, line2, city, usps_abbrev, full_state_name, zip_code, country_code, phone, phone_time) + values + (:address_id, :user_id, :address_type, :attn,:line1,:line2,:city,:usps_abbrev,:full_state_name,:zip_code,:country_code,:phone,:phone_time)" + } + } + + # Update the shipping address of the order + + db_dml set_shipping_on_order " + update ec_orders + set shipping_address = :address_id + where order_id = :order_id" +} + +# See if there's a gift certificate with a claim check + +if {[info exists claim_check] && ![empty_string_p $claim_check]} { + set gift_certificate_id [db_string get_gc_id " + select gift_certificate_id + from ec_gift_certificates + where claim_check=:claim_check" -default ""] + if { [empty_string_p $gift_certificate_id] } { + ad_return_complaint 1 " +

    The claim check you have entered is invalid. Please re-check it.

    +

    The claim check is case sensitive; enter it exactly as shown on your gift certificate.

    " + set prob_details " + Incorrect gift certificate claim check entered at [ad_conn url]. + Claim check entered: $claim_check by user ID: $user_id. + They may have just made a typo but if this happens repeatedly from the same IP address ([ns_conn peeraddr]) you may wish to look into this." + db_dml insert_error_failed_gc_claim " + insert into ec_problems_log + (problem_id, problem_date, problem_details) + values + (ec_problem_id_sequence.nextval, sysdate,:prob_details )" + ad_script_abort + } + + # There is a gift certificate with that claim check; + # now check whether it's already been claimed + # and, if so, whether it was claimed by this user + + db_1row get_gc_user_id " + select user_id as gift_certificate_user_id, amount + from ec_gift_certificates + where gift_certificate_id = :gift_certificate_id" + + if { [empty_string_p $gift_certificate_user_id ] } { + + # Then no one has claimed it, so go ahead and assign it to them + + db_dml update_ec_cert_set_user " + update ec_gift_certificates + set user_id=:user_id, claimed_date = sysdate + where gift_certificate_id = :gift_certificate_id" + set title "Gift Certificate Claimed" + set certificate_added_p "true" + } else { + + # It's already been claimed. See if it was claimed by a different + # user and, if so, record the problem + + if { $user_id != $gift_certificate_user_id } { + + set prob_details " + User ID $user_id tried to claim gift certificate $gift_certificate_id at [ad_conn url], but it had already been claimed by User ID $gift_certificate_id." + + db_dml insert_other_claim_prob " + insert into ec_problems_log + (problem_id, problem_date, gift_certificate_id, problem_details) + values + (ec_problem_id_sequence.nextval, sysdate, :gift_certificate_id, :prob_details)" + } + + set title "Gift Certificate Already Claimed" + set certificate_added_p "false" + } +} + + +# following mainly from process-order-quanity-shipping.tcl + +# update shipping method + +# 1. Update the shipping method and tax status + +if {[info exists shipping_gateway] && [string equal $shipping_gateway "true"]} { + + # A shipping gateway has been used. The shipping method contains + # both the shipping service level and the associated total + # charges. + + array set shipping_service_and_rate $shipping_method + set shipping_method $shipping_service_and_rate(service_description) + set order_shipping_cost $shipping_service_and_rate(total_charges) +} + +if {![info exists tax_exempt_p]} { + set tax_exempt_p "f" +} +if {[empty_string_p $tax_exempt_p]} { + set tax_exempt_p "f" +} + +if {![info exists shipping_method]} { + # shipping method does not exist + set shipping_method "" +} + +db_dml update_shipping_method " + update ec_orders + set shipping_method = :shipping_method, tax_exempt_p = :tax_exempt_p + where order_id = :order_id" + +# 2. Put the prices into ec_items + +# Set some things to use as arguments when setting prices + +if { [ad_parameter -package_id [ec_id] UserClassApproveP ecommerce] } { + set additional_user_class_restriction "and user_class_approved_p = 't'" +} else { + set additional_user_class_restriction "and (user_class_approved_p is null or user_class_approved_p='t')" +} + +set user_class_id_list [db_list get_list_user_classes " + select user_class_id + from ec_user_class_user_map + where user_id = :user_id $additional_user_class_restriction"] + +if {[info exists shipping_gateway] && [string equal $shipping_gateway "true"]} { + + # A shipping gateway has been used to calculate the total shipping + # charges so there is no to calculate the charges per item. + + set default_shipping_per_item 0 + set weight_shipping_cost 0 + set add_exp_amount_per_item 0 + set add_exp_amount_by_weight 0 +} else { + if {![info exists shipping_method]} { + # shipping method does not exist + set shipping_method "" + } + + if { $shipping_method != "pickup" && $shipping_method != "no shipping" } { + db_1row get_shipping_per_item " + select default_shipping_per_item, weight_shipping_cost + from ec_admin_settings" + db_1row get_exp_amt_peritem " + select add_exp_amount_per_item, add_exp_amount_by_weight + from ec_admin_settings" + } else { + set default_shipping_per_item 0 + set weight_shipping_cost 0 + set add_exp_amount_per_item 0 + set add_exp_amount_by_weight 0 + } +} +set usps_abbrev [db_string get_usps_abbrev " + select usps_abbrev + from ec_addresses + where address_id = :address_id" -default ""] +if { ![empty_string_p $usps_abbrev] && [string equal $tax_exempt_p "f"] } { + if { [db_0or1row get_tax_rate " + select tax_rate, shipping_p + from ec_sales_tax_by_state + where usps_abbrev = :usps_abbrev"] == 0 } { + set tax_rate 0 + set shipping_p f + } +} else { + set tax_rate 0 + set shipping_p f +} + +# These will be updated as we loop through the items + +set total_item_shipping_tax 0 +set total_item_price_tax 0 + +db_foreach get_items_in_cart " + select i.item_id, i.product_id, u.offer_code + from ec_items i, (select * + from ec_user_session_offer_codes usoc + where usoc.user_session_id = :user_session_id) u + where i.product_id=u.product_id(+) + and i.order_id=:order_id" { + + set everything [ec_price_price_name_shipping_price_tax_shipping_tax_for_one_item $product_id $offer_code $item_id $order_id $user_class_id_list \ + $shipping_method $default_shipping_per_item $weight_shipping_cost $add_exp_amount_per_item $add_exp_amount_by_weight $tax_rate $shipping_p] + set total_item_shipping_tax [expr $total_item_shipping_tax + [lindex $everything 4]] + set total_item_price_tax [expr $total_item_price_tax + [lindex $everything 3]] + set price_charged [lindex $everything 0] + set price_name [lindex $everything 1] + set shipping_charged [lindex $everything 2] + set tax_charged [lindex $everything 3] + set shipping_tax [lindex $everything 4] + + db_dml update_ec_items " + update ec_items + set price_charged = round(:price_charged,2), price_name = :price_name, shipping_charged = round(:shipping_charged,2), + price_tax_charged = round(:tax_charged,2), shipping_tax_charged = round(:shipping_tax,2) + where item_id = :item_id" + + # Get associated application assessments + set assessment_ids [list] + if { [db_0or1row get_assessment { + select c.assessment_id + + from dotlrn_ecommerce_section s, + dotlrn_catalogi c, + cr_items i + + where s.course_id = c.item_id + and c.item_id = i.item_id + and i.live_revision = c.course_id + and s.product_id = :product_id + + limit 1 + }] } { + if { [lsearch $assessment_ids $assessment_id] == -1 && ! [empty_string_p $assessment_id] && $assessment_id != -1 } { + lappend assessment_ids $assessment_id + } + } +} + +# 3. Determine base shipping cost & put it into ec_orders + +if {![info exists shipping_gateway]} { + + if {![info exists shipping_method]} { + # shipping_method does not exist + set shipping_method "" + } + + if { $shipping_method != "pickup" && $shipping_method != "no shipping" } { + set order_shipping_cost [db_string get_base_ship_cost " + select nvl(base_shipping_cost,0) + from ec_admin_settings"] + } else { + set order_shipping_cost 0 + } + + # Add on the extra base cost for express shipping, if appropriate + + if { [string equal $shipping_method "express"] } { + set add_exp_base_shipping_cost [db_string get_exp_base_cost " + select nvl(add_exp_base_shipping_cost,0) + from ec_admin_settings"] + set order_shipping_cost [expr $order_shipping_cost + $add_exp_base_shipping_cost] + } +} + +set tax_on_order_shipping_cost [db_string get_shipping_tax " + select ec_tax(0,:order_shipping_cost,:order_id) + from dual"] + +db_dml set_shipping_charges " + update ec_orders + set shipping_charged = round(:order_shipping_cost,2), shipping_tax_charged = round(:tax_on_order_shipping_cost,2) + where order_id=:order_id" + +# following mainly from process-payment.tcl + +# Now do error checking; It is required that either +# (a) their gift_certificate_balance covers the total order price, or +# (b) they've selected a previous credit card (and creditcard_number is null, +# otherwise we assume they want to use a new credit card), or +# (c) *all* of the credit card information for a new card has been filled in + +# we only want price and shipping from this (to determine whether +# gift_certificate_balance covers cost) + +set price_shipping_gift_certificate_and_tax [ec_price_shipping_gift_certificate_and_tax_in_an_order $order_id] +set order_total_price_pre_gift_certificate [expr [lindex $price_shipping_gift_certificate_and_tax 0] + [lindex $price_shipping_gift_certificate_and_tax 1]] +set gift_certificate_balance [db_string get_gc_balance " + select ec_gift_certificate_balance(:user_id) + from dual"] +if { $gift_certificate_balance >= $order_total_price_pre_gift_certificate } { + set gift_certificate_covers_cost_p "t" +} else { + set gift_certificate_covers_cost_p "f" +} + +if { [info exists creditcard_number] } { + + # get rid of spaces and dashes + + regsub -all -- "-" $creditcard_number "" creditcard_number + regsub -all " " $creditcard_number "" creditcard_number +} + +if { [string equal $gift_certificate_covers_cost_p "f"] } { + + if { $method == "cc" } { + if { ![info exists creditcard_id] || ([info exists creditcard_number] && ![empty_string_p $creditcard_number]) } { + if { ![info exists creditcard_number] || [empty_string_p $creditcard_number] } { + + # Then they haven't selected a previous credit card nor + # have they entered new credit card info + + ad_return_complaint 1 "
  • A credit card is required to complete this order." + ad_script_abort + } else { + + # Then they are using a new credit card and we just have + # to check that they got it all right + + set exception_count 0 + set exception_text "" + + if { [regexp {[^0-9]} $creditcard_number] } { + + # I've already removed spaces and dashes, so only + # numbers should remain + + incr exception_count + append exception_text "
  • The credit card number contains invalid characters." + } + + if { ![info exists creditcard_type] || [empty_string_p $creditcard_type] } { + incr exception_count + append exception_text "
  • The credit card type is unknown." + } + + # make sure the credit card type is right & that it has + # the right number of digits + + set additional_count_and_text [ec_creditcard_precheck $creditcard_number $creditcard_type] + set exception_count [expr $exception_count + [lindex $additional_count_and_text 0]] + append exception_text [lindex $additional_count_and_text 1] + + if { ![info exists creditcard_expire_1] || [empty_string_p $creditcard_expire_1] || ![info exists creditcard_expire_2] || [empty_string_p $creditcard_expire_2] } { + incr exception_count + append exception_text "
  • A full credit card expiration date (month and year) is required." + } + + if { $exception_count > 0 } { + ns_log Notice "checkout-one-form-2.tcl,ref(683): $exception_count form input exception(s) for user $user_id" + ad_return_complaint $exception_count $exception_text + ad_script_abort + } + + # A valid credit card number has been provided and thus a + # billing address must exist. + + if {![info exists billing_address_id] || ([info exists billing_address_id] && [empty_string_p $billing_address_id])} { + ad_return_complaint 1 "
  • A billing address is required.
  • " + ad_script_abort + } + } + } else { + + # they're using an old credit card, although we should make + # sure they didn't submit to us someone else's creditcard_id + # or a blank creditcard_id + + if { [empty_string_p $creditcard_id] } { + + # Probably form surgery + + ad_returnredirect [export_vars -base checkout-2 { user_id participant_id }] + ad_script_abort + } + + set creditcard_owner [db_string get_cc_owner " + select user_id + from ec_creditcards + where creditcard_id=:creditcard_id" -default ""] + if { $user_id != $creditcard_owner } { + + # Probably form surgery + + ad_returnredirect [export_vars -base checkout-2 { user_id participant_id }] + ad_script_abort + } + + # A valid credit card number has been provided and thus a + # billing address must exist. + + if {![info exists billing_address_id] || ([info exists billing_address_id] && [empty_string_p $billing_address_id])} { + ad_return_complaint 1 "
  • A billing address is required.
  • " + ad_script_abort + } + + } + } else { + # Other payment methods + # Just store it + if { $method == "internal_account" } { + # Check if internal account was entered + if { [empty_string_p $internal_account] } { + ad_return_complaint 1 "
  • Please enter an internal account number.
  • " + ad_script_abort + } + + if { [db_0or1row check_transaction { + select 1 + from dotlrn_ecommerce_transactions + where order_id = :order_id + }] } { + db_dml update_transaction_internal_account { + update dotlrn_ecommerce_transactions + set method = 'internal_account', + internal_account = :internal_account + where order_id = :order_id + } + } else { + db_dml save_transaction_internal_account { + insert into dotlrn_ecommerce_transactions + (order_id, method, internal_account) + values + (:order_id, 'internal_account', :internal_account) + } + } + } elseif { $method == "check" } { + if { [db_0or1row check_transaction { + select 1 + from dotlrn_ecommerce_transactions + where order_id = :order_id + }] } { + db_dml update_transaction_check { + update dotlrn_ecommerce_transactions + set method = 'check', + internal_account = null + where order_id = :order_id + } + } else { + db_dml save_transaction_check { + insert into dotlrn_ecommerce_transactions + (order_id, method) + values + (:order_id, 'check') + } + } + } + } +} + +# Everything is ok now; the user has a non-empty in_basket order and +# an address associated with it, so now insert credit card info if +# needed + +if { $method == "cc" } { + db_transaction { + # If gift_certificate doesn't cover cost, either insert or update + # credit card + if { [string equal $gift_certificate_covers_cost_p "f"] } { + if { ![info exists creditcard_number] || [empty_string_p $creditcard_number] } { + + # Using pre-existing credit card + + db_dml use_existing_cc_for_order " + update ec_orders + set creditcard_id=:creditcard_id + where order_id=:order_id" + db_dml update_cc_address " + update ec_creditcards + set billing_address = :billing_address_id + where creditcard_id = :creditcard_id" + } else { + + # Using new credit card + + set creditcard_id [db_nextval ec_creditcard_id_sequence] + set cc_no [string range $creditcard_number [expr [string length $creditcard_number] -4] [expr [string length $creditcard_number] -1]] + set expiry "$creditcard_expire_1/$creditcard_expire_2" + db_dml insert_new_cc " + insert into ec_creditcards + (creditcard_id, user_id, creditcard_number, creditcard_last_four, creditcard_type, creditcard_expire, billing_address) + values + (:creditcard_id, :user_id, :creditcard_number, :cc_no , :creditcard_type, :expiry, :billing_address_id)" + db_dml update_order_set_cc " + update ec_orders + set creditcard_id=:creditcard_id + where order_id=:order_id" + } + } else { + + # Make creditcard_id be null (which it might not be if this isn't + # their first time along this path) + + db_dml set_null_cc_in_order " + update ec_orders + set creditcard_id=null + where order_id=:order_id" + } + } +} + +set checkout_url [export_vars -base [apm_package_url_from_key dotlrn-ecommerce]ecommerce/checkout-3.tcl { {url checkout-one-form-2} user_id participant_id }] + +# Determine if there's an application assessment +if { [llength $assessment_ids] > 0 } { + # Since we can have multiple sections under the shopping cart, we + # can have multiple associated assessments, we keep track of all + # these assessments but for now just use the first one + + ad_returnredirect [export_vars -base [apm_package_url_from_key assessment]assessment { {assessment_id "[lindex $assessment_ids 0]"} {return_url $checkout_url} }] + ad_script_abort +} + +db_release_unused_handles +#rp_form_put url checkout-one-form-2 +#rp_internal_redirect checkout-3.tcl +ad_returnredirect $checkout_url +ad_script_abort Index: openacs-4/packages/dotlrn-ecommerce/www/ecommerce/checkout-one-form-2.xql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/dotlrn-ecommerce/www/ecommerce/checkout-one-form-2.xql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/dotlrn-ecommerce/www/ecommerce/checkout-one-form-2.xql 23 Jun 2005 12:28:22 -0000 1.1 @@ -0,0 +1,219 @@ + + + + + + + select order_id + from ec_orders + where user_session_id=:user_session_id + and order_state='in_basket' + + + + + + select gift_certificate_id + from ec_gift_certificates + where claim_check=:claim_check + + + + + + select user_id as gift_certificate_user_id, amount + from ec_gift_certificates + where gift_certificate_id=:gift_certificate_id + + + + + + select user_id + from ec_creditcards + where creditcard_id=:creditcard_id + + + + + + select address_id + from ec_addresses + where user_id=:user_id + and address_type = 'shipping' + + + + + + update ec_orders + set creditcard_id=:creditcard_id + where order_id=:order_id + + + + + + insert into ec_creditcards + (creditcard_id, user_id, creditcard_number, creditcard_last_four, creditcard_type, creditcard_expire, billing_address) + values + (:creditcard_id, :user_id, :creditcard_number, :cc_no , :creditcard_type, :expiry, :billing_address_id) + + + + + + update ec_creditcards + set billing_address = :billing_address_id + where creditcard_id = :creditcard_id + + + + + + update ec_orders + set creditcard_id=:creditcard_id + where order_id=:order_id + + + + + + update ec_orders + set creditcard_id=null + where order_id=:order_id + + + + + + update ec_addresses + set attn=:attn, line1=:line1, line2=:line2, city=:city, usps_abbrev=:usps_abbrev, zip_code=:zip_code, phone=:phone, phone_time=:phone_time + where address_id=:address_id + + + + + + update ec_items + set price_charged=round(:price_charged,2), price_name=:price_name, shipping_charged=round(:shipping_charged,2), price_tax_charged=round(:tax_charged,2), shipping_tax_charged=round(:shipping_tax,2) + where item_id=:item_id + + + + + + update ec_orders + set shipping_address=:address_id + where order_id=:order_id + + + + + + update ec_orders + set shipping_method=:shipping_method, + tax_exempt_p=:tax_exempt_p + where order_id=:order_id + + + + + + select user_class_id + from ec_user_class_user_map + where user_id=:user_id $additional_user_class_restriction + + + + + + select order_id + from ec_orders + where user_session_id=:user_session_id + and order_state='in_basket' + + + + + + select attn, line1, line2, city, usps_abbrev, zip_code, phone, country_code, full_state_name, phone_time + from ec_addresses + where address_id=:address_id + and user_id=:user_id + + + + + + update ec_addresses + set attn = :attn, line1 = :line1, line2 = :line2, usps_abbrev = :usps_abbrev, + city = :city, full_state_name = :full_state_name, zip_code = :zip_code, country_code = :country_code, phone = :phone, phone_time = :phone_time + where address_id = :address_id + + + + + + select usps_abbrev + from ec_addresses + where address_id=:address_id + + + + + + select tax_rate, shipping_p + from ec_sales_tax_by_state + where usps_abbrev=:usps_abbrev + + + + + + update ec_orders + set shipping_address=:address_id + where order_id=:order_id + + + + + + insert into ec_addresses + (address_id, user_id, address_type, attn, line1, line2, city, usps_abbrev, full_state_name, zip_code, country_code, phone, phone_time) + values + (:address_id, :user_id, :address_type, :attn,:line1,:line2,:city,:usps_abbrev,:full_state_name,:zip_code,:country_code,:phone,:phone_time) + + + + + + update ec_orders + set shipping_address=:address_id + where order_id=:order_id + + + + + + select default_shipping_per_item, weight_shipping_cost + from ec_admin_settings + + + + + + select add_exp_amount_per_item, add_exp_amount_by_weight + from ec_admin_settings + + + + + + update ec_orders + set shipping_charged=round(:order_shipping_cost,2), shipping_tax_charged=round(:tax_on_order_shipping_cost,2) + where order_id=:order_id + + + + Index: openacs-4/packages/dotlrn-ecommerce/www/ecommerce/checkout-one-form-oracle.xql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/dotlrn-ecommerce/www/ecommerce/checkout-one-form-oracle.xql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/dotlrn-ecommerce/www/ecommerce/checkout-one-form-oracle.xql 23 Jun 2005 12:28:22 -0000 1.1 @@ -0,0 +1,55 @@ + + + + + oracle + 8.1.6 + + + + + select i.product_id, i.color_choice, i.size_choice, i.style_choice, count(*) as item_count, u.offer_code + from ec_products p, ec_items i, ec_user_session_offer_codes u + where u.product_id(+)=i.product_id and (u.user_session_id is null or u.user_session_id=:user_session_id) + and i.product_id = p.product_id + and p.no_shipping_avail_p = 'f' + and i.order_id = :order_id + group by i.product_id, i.color_choice, i.size_choice, i.style_choice, u.offer_code + + + + + + select nvl(base_shipping_cost,0) as base_shipping_cost, + nvl(default_shipping_per_item,0) as default_shipping_per_item, + nvl(weight_shipping_cost,0) as weight_shipping_cost, + nvl(add_exp_base_shipping_cost,0) as add_exp_base_shipping_cost, + nvl(add_exp_amount_per_item,0) as add_exp_amount_per_item, + nvl(add_exp_amount_by_weight,0) as add_exp_amount_by_weight + from ec_admin_settings + + + + + + select i.item_id, i.product_id, u.offer_code + from ec_items i, (select * + from ec_user_session_offer_codes usoc + where usoc.user_session_id = :user_session_id) u + where i.product_id=u.product_id(+) + and i.order_id=:order_id + order by i.product_id + + + + + + select ec_order_cost(:order_id) as otppgc, + ec_gift_certificate_balance(:user_id) as user_gift_certificate_balance + from dual + + + + + + Index: openacs-4/packages/dotlrn-ecommerce/www/ecommerce/checkout-one-form-postgresql.xql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/dotlrn-ecommerce/www/ecommerce/checkout-one-form-postgresql.xql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/dotlrn-ecommerce/www/ecommerce/checkout-one-form-postgresql.xql 23 Jun 2005 12:28:22 -0000 1.1 @@ -0,0 +1,57 @@ + + + + + postgresql + 7.1 + + + + + select ec_tax(0,:order_shipping_cost,:order_id) + + + + + + select coalesce(base_shipping_cost,0) as base_shipping_cost, + coalesce(default_shipping_per_item,0) as default_shipping_per_item, + coalesce(weight_shipping_cost,0) as weight_shipping_cost, + coalesce(add_exp_base_shipping_cost,0) as add_exp_base_shipping_cost, + coalesce(add_exp_amount_per_item,0) as add_exp_amount_per_item, + coalesce(add_exp_amount_by_weight,0) as add_exp_amount_by_weight + from ec_admin_settings + + + + + + select i.item_id, i.product_id, u.offer_code + from ec_items i + left join (select * + from ec_user_session_offer_codes usoc + where usoc.user_session_id=:user_session_id) u on (i.product_id=u.product_id) + where i.order_id=:order_id + order by i.product_id + + + + + + select i.product_id, i.color_choice, i.size_choice, i.style_choice, count(*) as item_count, u.offer_code + from ec_products p, ec_items i + left join ec_user_session_offer_codes u on (u.product_id = i.product_id and u.user_session_id = :user_session_id) + where i.product_id = p.product_id + and p.no_shipping_avail_p = 'f' + and i.order_id = :order_id + group by i.product_id, i.color_choice, i.size_choice, i.style_choice, u.offer_code + + + + + + select ec_order_cost(:order_id) as otppgc, ec_gift_certificate_balance(:user_id) as user_gift_certificate_balance + + + + Index: openacs-4/packages/dotlrn-ecommerce/www/ecommerce/checkout-one-form.adp =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/dotlrn-ecommerce/www/ecommerce/checkout-one-form.adp,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/dotlrn-ecommerce/www/ecommerce/checkout-one-form.adp 23 Jun 2005 12:28:22 -0000 1.1 @@ -0,0 +1,148 @@ + + + + + Completing Your Order + +

    To complete your order, submit this form, and confirm the information + on the following page.

    + + +

    Alternately, you can use a multi-page order process, + if you prefer using some of your other addresses on file with us. +

    +
    + + + +

    1. Please review your order list for accuracy.

    +

    Order list

    + @items_ul;noquote@ +
    +

    2. Complete this information.

    + + +@hidden_vars;noquote@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

    Bill to:

     

    Ship to (if different):

    First name(s): First name(s):
    Last name: Last name:
    Telephone: Telephone:
    Best time to call: checked>day    checked>evening Best time to call: checked>day    checked>evening
    Address: Address:
    Address line 2
    (optional):
     Address line 2
    (optional):
    City: City:
    State/Province:@bill_to_state_widget;noquote@ State/Province:@ship_to_state_widget;noquote@
    Other province or region: Other province or region:
    ZIP/Postal code: ZIP/Postal code:
    Country:
    @bill_to_country_code;noquote@
     Country:
    @ship_to_country_code;noquote@
    + @tax_exempt_options;noquote@ +   
    + + +
    + +

    Shipping information

    + + @shipping_options;noquote@ +
    +
    + + + + +

    Payment information

    +
    + + @tax_exempt_options;noquote@ + + +

    Your gift certificate balance covers the total cost of your + order. No need to enter any payment information!

    +
    + + +

    Your gift certificate balance takes care of + @certificate_amount@ of your order! Please enter credit card + information to pay for the rest.

    +
    +
    + +
    + + + + +

    Since we already have a credit card on file for you, you + can just click on the button next to it to use it for this + order.

    +

    @old_cards_to_choose_from;noquote@

    +

    Or enter a new credit card:

    +

    If you're using a new card, please enter the full credit card number below.

    +
    + Internal account number: +

    + User sends in a check

    + Pay via credit card + + + + + + + + + + + + + + + + +

    Credit card information

    Credit card number:
    Type:
    Expires:@ec_expires_widget;noquote@
    + + +

    + + + Index: openacs-4/packages/dotlrn-ecommerce/www/ecommerce/checkout-one-form.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/dotlrn-ecommerce/www/ecommerce/checkout-one-form.tcl,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/dotlrn-ecommerce/www/ecommerce/checkout-one-form.tcl 23 Jun 2005 12:28:22 -0000 1.1 @@ -0,0 +1,665 @@ +ad_page_contract { + + This generates a custom single order fulfillment page + with options to interface with the sophisticated multi address fulfillment + processing, when enough address history exists to make it worthwhile + Essentially combines /ecommerce/www/checkout* address* select-shipping* billing* payment* + + @author ported by Jerry Asher (jerry@theashergroup.com) + @author revised by Bart Teeuwisse + @author combined by Torben Brosten + @creation-date March 2004 + + @param usca_p:optional User session if started + +} { + usca_p:optional + + user_id:integer,notnull + participant_id:integer,optional +} + +# security checks +# following from checkout.tcl + +ec_redirect_to_https_if_possible_and_necessary + +# Make sure they have an in_basket order, otherwise they've probably +# gotten here by pushing Back, so return them to index.tcl + +#set user_id [ad_conn user_id] +set user_session_id [ec_get_user_session_id] +ec_create_new_session_if_necessary + +ec_log_user_as_user_id_for_this_session + +set order_id [db_string get_order_id " + select order_id + from ec_orders + where user_session_id = :user_session_id + and order_state='in_basket'" -default "" ] + +if { [empty_string_p $order_id] } { + + # Then they probably got here by pushing "Back", so just redirect + # them to index.tcl + + rp_internal_redirect index + ad_script_abort +} else { + db_dml update_ec_order_set_uid " + update ec_orders + set user_id = :user_id + where order_id = :order_id" +} + + # end security check + + # useful references declared: order_id, user_id, user_session_id + + # Retrieve the user name, use as default + + db_0or1row get_names " + select first_names, last_name + from cc_users + where user_id=:user_id" + + # is there an existing shipping address? + + if { ![info exists address_id] } { + set address_id [db_string get_address_id " + select shipping_address + from ec_orders + where order_id=:order_id" -default ""] + set shipping_address_id $address_id + } + +# set initial conditions needed to build and process this form + + set form_action [ec_securelink checkout-one-form-2] + set hidden_vars "" + set show_item_detail_p "f" + + set gateway_shipping_default_price 0 + + set gift_certificate_covers_whole_order 0 + set gift_certificate_covers_part_of_order 0 + + set address_type "billing" + set billing_address_exists 0 + set more_addresses_available "f" + + set currency [ad_parameter -package_id [ec_id] Currency ecommerce] + set tax_exempt_status [ad_parameter -package_id [ec_id] OfferTaxExemptStatusP ecommerce 0] + set tax_exempt_options "" + if { $tax_exempt_status == "t" } { + append tax_exempt_options " +

  • Is your organization tax exempt? (If so, we will ask you to + provide us with an exemption certificate.) + Yes
    + No

    " + } + + # prepare the cart contents for display + # following mainly from ec_order_summary_for_customer + + set items_ul "" + set order_total 0 + set last_product_id 0 + + db_foreach order_details_select " + select i.price_name, i.price_charged, i.color_choice, i.size_choice, i.style_choice, + p.product_name, p.one_line_description, p.product_id, count(*) as quantity + from ec_items i, ec_products p + where i.order_id = :order_id + and i.product_id = p.product_id + group by p.product_name, p.one_line_description, p.product_id, i.price_name, i.price_charged, i.color_choice, i.size_choice, i.style_choice" { + if {$product_id != $last_product_id} { + set lowest_price [lindex [ec_lowest_price_and_price_name_for_an_item $product_id $user_id] 0] + } + set option_list [list] + if { ![empty_string_p $color_choice] } { + lappend option_list "Color: $color_choice" + } + if { ![empty_string_p $size_choice] } { + lappend option_list "Size: $size_choice" + } + if { ![empty_string_p $style_choice] } { + lappend option_list "Style: $style_choice" + } + set options [join $option_list ", "] + if { ![empty_string_p $options] } { + set options "$options; " + } + + append items_ul "
  • Quantity $quantity: $product_name; $options$price_name [ec_pretty_price $lowest_price $currency]" + if { $show_item_detail_p == "t" } { + append items_ul "
    + [ec_shipment_summary_sub $product_id $color_choice $size_choice $style_choice $price_charged $price_name $order_id]" + } + append items_ul "
  • " + + set order_total [expr $order_total + $quantity * $lowest_price] + + } + set order_total_price_pre_gift_certificate $order_total + + + # Check if the order requires shipping + + if {[db_0or1row shipping_avail " + select p.no_shipping_avail_p + from ec_items i, ec_products p + where i.product_id = p.product_id + and p.no_shipping_avail_p = 'f' + and i.order_id = :order_id + group by no_shipping_avail_p"]} { + + set shipping_required "t" + + } else { + set shipping_required "f" + } + + + # calculate shipping options + +# prepare shipping method choices (shipping rates determined previously) +# some of this from ec_price_price_name_shipping_price_tax_shipping_tax_for_one_item +# and from ec_shipping_price_for_one_item +# and select-shipping.tcl + + + # Check if a shipping gateway has been selected. + set shipping_gateway [ad_parameter ShippingGateway ecommerce] + set shipping_gateway_in_use [acs_sc_binding_exists_p ShippingGateway $shipping_gateway] + +# below was: if info exists no_shipping_avail_p && string equal $no_shipping_avail_p "f" +if { [exists_and_equal shipping_required "t"] } { + + if { $shipping_gateway_in_use} { + + if { $address_id != 0 } { + + # Replace the default ecommerce shipping calculations with the + # charges from the shipping gateway, which contains + # both the shipping service level and the associated total + # charges. Requries zipcode and country. + + db_1row select_shipping_address " + select country_code, zip_code + from ec_addresses + where address_id = :address_id" + + # Calculate the total value of the shipment. + set shipment_value 0 + + db_foreach select_hard_goods " + select i.product_id, i.color_choice, i.size_choice, i.style_choice, count(*) as item_count, u.offer_code + from ec_products p, ec_items i + left join ec_user_session_offer_codes u on (u.product_id = i.product_id and u.user_session_id = :user_session_id) + where i.product_id = p.product_id + and p.no_shipping_avail_p = 'f' + and i.order_id = :order_id + group by i.product_id, i.color_choice, i.size_choice, i.style_choice, u.offer_code" { + + # If the quantity was altered in the previous step then + # use the new quantity instead of the number of items in + # the database. + + if {[info exists quantity]} { + set item_price [lindex [ec_lowest_price_and_price_name_for_an_item $product_id $user_id $offer_code] 0] + foreach {item_name item_quantity} [array get quantity [list $product_id*]] { + set shipment_value [expr $shipment_value + ((($item_quantity != $item_count) ? $item_quantity : $item_count) * $item_price)] + } + } else { + set shipment_value [expr $shipment_value + [lindex [ec_lowest_price_and_price_name_for_an_item $product_id $user_id $offer_code] 0]] + } + } + + set value_currency_code [ad_parameter Currency ecommerce] + set weight_unit_of_measure [ad_parameter WeightUnits ecommerce] + + append shipping_options " +

    Shipping method:

    + " + + # Get the list of services and their charges sorted on + # charges. + + set rates_and_services [lsort -index 1 -real \ + [acs_sc_call "ShippingGateway" "RatesAndServicesSelection" \ + [list "" "" "$country_code" "$zip_code" "$shipment_value" "$value_currency_code" "" "$weight_unit_of_measure"] \ + "$shipping_gateway"]] + + # Present the available shipping services to the user with the + # cheapest service selected. + + set cheapest_service true + foreach service $rates_and_services { + array set rate_and_service $service + set total_charges $rate_and_service(total_charges) + set service_code $rate_and_service(service_code) + set service_description [acs_sc_call "ShippingGateway" "ServiceDescription" "$service_code" "$shipping_gateway"] + append shipping_options " + + + + + + " + } + append shipping_options "
    + + $service_description + + + [string map {USD $} $value_currency_code] + + $total_charges +
    " + + # Add a flag to the export parameters to indicate that a + # shipping gateway is in use. + + set shipping_gateway true + append shipping_options "[export_form_vars shipping_gateway]" + } else { set shipping_options "

    We need your shipping address before we can quote a shipping price. You will be able to review your order and shipping charge before confirming the order.

    " + } + } else { + # calculate shipping charge options when not using shipping-gateway, + # and then include the value with each option (for an informed choice) + + # mainly from process-order-quantity-shipping.tcl + set total_reg_shipping_price 0 + set total_exp_shipping_price 0 + set last_product_id 0 + + db_1row get_ec_admin_settings " + select nvl(base_shipping_cost,0) as base_shipping_cost, + nvl(default_shipping_per_item,0) as default_shipping_per_item, + nvl(weight_shipping_cost,0) as weight_shipping_cost, + nvl(add_exp_base_shipping_cost,0) as add_exp_base_shipping_cost, + nvl(add_exp_amount_per_item,0) as add_exp_amount_per_item, + nvl(add_exp_amount_by_weight,0) as add_exp_amount_by_weight + from ec_admin_settings" + + db_foreach get_items_in_cart " + select i.item_id, i.product_id, u.offer_code + from ec_items i, (select * + from ec_user_session_offer_codes usoc + where usoc.user_session_id = :user_session_id) u + where i.product_id=u.product_id(+) + and i.order_id=:order_id + order by i.product_id" { + # ordering by i.product_id so loop can identify first instance of a quantity + + if { $product_id != $last_product_id } { + set first_instance 1 + db_1row get_shipping_info " + select shipping, shipping_additional, weight, no_shipping_avail_p + from ec_products + where product_id=:product_id" + } else { + set first_instance 0 + } + # if no_shipping_avail_p, skip calculating shipping for this item + if { [string equal $no_shipping_avail_p "f"] } { + + set shipping_prices_for_one_item [ec_shipping_prices_for_one_item_by_rate $product_id $shipping $shipping_additional $default_shipping_per_item $weight $weight_shipping_cost $first_instance $add_exp_amount_per_item $add_exp_amount_by_weight] + + set total_reg_shipping_price [expr $total_reg_shipping_price + [lindex $shipping_prices_for_one_item 0]] + set total_exp_shipping_price [expr $total_exp_shipping_price + [lindex $shipping_prices_for_one_item 1]] + set last_product_id $product_id + } + } + + +# 3. Determine base shipping costs that are separate from items + + # set base shipping charge + + set order_shipping_cost $base_shipping_cost + + set shipping_method_standard $order_shipping_cost + + # Add on the extra base cost for express shipping + + set shipping_method_express [expr $order_shipping_cost + $add_exp_base_shipping_cost] + +# 4. set total costs for each shipping option + set total_shipping_price_default $total_reg_shipping_price + set total_reg_shipping_price [ec_pretty_price [expr $total_reg_shipping_price + $shipping_method_standard] $currency "t"] + set total_exp_shipping_price [ec_pretty_price [expr $total_exp_shipping_price + $shipping_method_express] $currency "t"] + set shipping_method_pickup [ec_pretty_price 0 $currency "t"] + set shipping_method_no_shipping 0 + +# 5 prepare shipping options to present to user + + set shipping_options " +

    Shipping method:

    +

    Standard Shipping ($total_reg_shipping_price)
    " + + if { [ad_parameter -package_id [ec_id] ExpressShippingP ecommerce] } { + append shipping_options " + Express ($total_exp_shipping_price)
    " + } + if { [ad_parameter -package_id [ec_id] PickupP ecommerce] } { + append shipping_options " + Pickup ($shipping_method_pickup)" + } + append shipping_options "

    " + } + # bracket above ends if gateway not used + } else { + # shipping not available or required + set total_shipping_price_default 0 + } + + +# we want to present the most recent billing address, if there is one + + set billing_address_ids [db_list get_billing_address_ids " + select address_id + from ec_addresses + where user_id=:user_id + and address_type = 'billing'" ] + + # $more_billing_addresses_available can be used in the adp to notify the user + # to choose one of their other billing addresses, if any + if { [llength $billing_address_ids] > 1 } { + # the max valued id is most likely the newest id (no date_last_modified field available) + set billing_address_id [ec_max_of_list $billing_address_ids] + set more_billing_addresses_available "t" + } else { + set more_billing_addresses_available "f" + if { $billing_address_ids > 0 } { + set billing_address_id $billing_address_ids + } else { + # we assume that no valid address_id is ever 0 + set billing_address_id 0 + } + } + + # retrieve a saved address + set address_id $billing_address_id + if { [info exists address_id] } { + set billing_address_exists [db_0or1row select_address " + select attn, line1, line2, city, usps_abbrev, zip_code, phone, country_code, full_state_name, phone_time + from ec_addresses + where address_id=:address_id"] + } + if {$billing_address_exists == 1} { + set bill_to_attn $attn + # split attn for separate first_names, last_name processing, delimiter is triple space + # separate first_names, last_name is required for some payment gateway validation systems (such as EZIC) + set name_delim [string first " " $attn] + if {$name_delim < 0 } { + set name_delim 0 + } + set bill_to_first_names [string trim [string range $attn 0 $name_delim]] + set bill_to_last_name [string range $attn [expr $name_delim + 3 ] end] + + set bill_to_line1 $line1 + set bill_to_line2 $line2 + set bill_to_city $city + set bill_to_usps_abbrev $usps_abbrev + set bill_to_zip_code $zip_code + set bill_to_phone $phone + set bill_to_country_code [ec_country_widget $country_code "bill_to_country_code"] + set bill_to_full_state_name $full_state_name + set bill_to_phone_time $phone_time + set bill_to_state_widget [ec_state_widget $usps_abbrev "bill_to_usps_abbrev"] + } else { + set billing_address_id 0 + # no previous billing address, set defaults + set bill_to_first_names [value_if_exists first_names] + set bill_to_last_name [value_if_exists last_name] + + set bill_to_line1 "" + set bill_to_line2 "" + set bill_to_city "" + set bill_to_usps_abbrev "" + set bill_to_zip_code "" + set bill_to_phone "" + set bill_to_country_code [ec_country_widget "US" "bill_to_country_code"] + set bill_to_full_state_name "" + set bill_to_phone_time "" + set bill_to_state_widget [ec_state_widget "" "bill_to_usps_abbrev"] + } + +if { [exists_and_equal shipping_required "t"] } { +# prepare shipping address + + set address_type "shipping" + + set shipping_address_exists 0 + + # we want to present the most recent shipping address, if there is one + # alternately, we can always start with a blank shipping address for all cases, + # if we want to bias users to use their billing addresses. + set shipping_address_ids [db_list get_shipping_address_ids " + select address_id + from ec_addresses + where user_id=:user_id + and address_type = 'shipping'" ] + + # $more_shipping_addresses_available can be used to notify the user + # to choose one of their other shipping addresses, if any + # ("previous addresses shipped to" link?) + if { [llength $shipping_address_ids] > 1 } { + set more_shipping_addresses_available "t" + # the max valued id is most likely the newest id (no last used date field available) + set shipping_address_id [ec_max_of_list $shipping_address_ids] + } else { + set more_shipping_addresses_available "f" + if { $shipping_address_ids > 0 } { + set shipping_address_id $shipping_address_ids + } else { + set shipping_address_id 0 + } + } + if {$more_billing_addresses_available == "t" || $more_shipping_addresses_available == "t" } { + set more_addresses_available "t" + } else { + set more_addresses_available "f" + } + # retrieve a saved address + set address_id $shipping_address_id + if { [info exists address_id] } { + set shipping_address_exists [db_0or1row select_address " + select attn, line1, line2, city, usps_abbrev, zip_code, phone, country_code, full_state_name, phone_time + from ec_addresses + where address_id=:address_id"] + } + if {$shipping_address_exists == 1} { + set ship_to_attn $attn + # split attn for separate first_names, last_name processing, delimiter is triple space + # separate first_names, last_name is required for some payment gateway validation systems (such as EZIC) + # in some cases, shipping address can be used as the default for billing address + set name_delim [string first " " $attn] + if {$name_delim < 0 } { + set name_delim 0 + } + set ship_to_first_names [string trim [string range $attn 0 $name_delim]] + set ship_to_last_name [string range $attn [expr $name_delim + 3 ] end] + + set ship_to_line1 $line1 + set ship_to_line2 $line2 + set ship_to_city $city + set ship_to_usps_abbrev $usps_abbrev + set ship_to_zip_code $zip_code + set ship_to_phone $phone + set ship_to_country_code [ec_country_widget $country_code "ship_to_country_code"] + set ship_to_full_state_name $full_state_name + set ship_to_phone_time $phone_time + set ship_to_state_widget [ec_state_widget $usps_abbrev "ship_to_usps_abbrev"] + } else { + set shipping_address_id 0 + # no previous shipping address, set defaults + set ship_to_first_names "" + set ship_to_last_name "" + + set ship_to_line1 "" + set ship_to_line2 "" + set ship_to_city "" + set ship_to_usps_abbrev "" + set ship_to_zip_code "" + set ship_to_phone "" + set ship_to_country_code [ec_country_widget "US" "ship_to_country_code"] + set ship_to_full_state_name "" + set ship_to_phone_time "" + set ship_to_state_widget [ec_state_widget "" "ship_to_usps_abbrev"] + } + # next bracket ends prepare shipping +} + +# prepare payment information + + # ec_order_cost returns price + shipping + tax - gift_certificate BUT + # no gift certificates have been applied to in_basket orders, so this + # just returns price + shipping + tax + + db_1row get_order_cost " + select ec_order_cost(:order_id) as otppgc, + ec_gift_certificate_balance(:user_id) as user_gift_certificate_balance + from dual" + + # Had to do this because the variable name below is too long for + # Oracle. It should be changed, but not in this upgrade + # hbrock@arsdigita.com + + set order_total_price_pre_gift_certificate $otppgc + unset otppgc + +# ec_order_cost does not work here, except maybe in special circumstances, +# where it might actually be more accurate than the alternate calculation. + + if { $order_total_price_pre_gift_certificate == 0 } { + # building order_total_price_pre_gift_certificate from an above query + # shipping value uses default from previous calcs on this page + if { $shipping_gateway_in_use == 1 } { + # there might not be an address available yet, so regional taxes are in flux still + set order_total_price_pre_gift_certificate [expr $order_total + $gateway_shipping_default_price] + } else { + # note: this does not include taxes for total value of order + set order_total_price_pre_gift_certificate [expr $order_total + $total_shipping_price_default] + } + } + + # these variable names help clarify usage for non-programmers editing the ADP + # templates: + + set customer_can_use_old_credit_cards 0 + + set show_creditcard_form_p "t" + + if { $user_gift_certificate_balance >= $order_total_price_pre_gift_certificate } { + set gift_certificate_covers_whole_order 1 + set show_creditcard_form_p "f" + } elseif { $user_gift_certificate_balance > 0 } { + set gift_certificate_covers_part_of_order 1 + set certificate_amount [ec_pretty_price $user_gift_certificate_balance] + } + + if { $show_creditcard_form_p == "t" } { + set customer_can_use_old_credit_cards [ad_parameter -package_id [ec_id] SaveCreditCardDataP ecommerce] + + # See if the administrator lets customers reuse their credit cards + + if { $customer_can_use_old_credit_cards } { + + # Then see if we have any credit cards on file for this user + # for this shipping address only (for security purposes) + + set to_print_before_creditcards " + + + + + + + " + set card_counter 0 + set old_cards_to_choose_from "" + + db_foreach get_creditcards_onfile " + select c.creditcard_id, c.creditcard_type, c.creditcard_last_four, c.creditcard_expire + from ec_creditcards c + where c.user_id=:user_id + and c.creditcard_number is not null + and c.failed_p='f' + and 0 < (select count(*) from ec_orders o where o.creditcard_id = c.creditcard_id) + order by c.creditcard_id desc" { + + if { $card_counter == 0 } { + append old_cards_to_choose_from $to_print_before_creditcards + } + append old_cards_to_choose_from " + + + + + + " + incr card_counter + } if_no_rows { + set customer_can_use_old_credit_cards 0 + } + } + + set ec_creditcard_widget [ec_creditcard_widget] + set ec_expires_widget "[ec_creditcard_expire_1_widget] [ec_creditcard_expire_2_widget]" + + # If customer_can_use_old_credit_cards is 0, we don't have to + # worry about what's in old_cards_to_choose_from because it won't + # get printed in the template anyway. + + append old_cards_to_choose_from "
    Card TypeLast 4 DigitsExpires
    + [ec_pretty_creditcard_type $creditcard_type]$creditcard_last_four$creditcard_expire
    " + } + + set gift_certificate_p [ad_parameter -package_id [ec_id] SellGiftCertificatesP ecommerce] + +# quoting is default behavior for openacs 5.x + +# set bill_to_first_names [ad_quotehtml $bill_to_first_names] +# set bill_to_last_name [ad_quotehtml $bill_to_last_name] + +# set bill_to_line1 [ad_quotehtml $bill_to_line1] +# set bill_to_line2 [ad_quotehtml $bill_to_line2] +# set bill_to_city [ad_quotehtml $bill_to_city] +# set bill_to_usps_abbrev [ad_quotehtml $bill_to_usps_abbrev] +# set bill_to_zip_code [ad_quotehtml $bill_to_zip_code] +# set bill_to_phone [ad_quotehtml $bill_to_phone] +# cannot quote bill_to_country_code [ad_quotehtml $country_code] +# set bill_to_full_state_name [ad_quotehtml $bill_to_full_state_name] +# set bill_to_phone_time [ad_quotehtml $bill_to_phone_time] +# cannot quote bill_to_state_widget [ad_quotehtml $state_widget] + +if { [exists_and_equal shipping_required "t"] } { +# set ship_to_first_names [ad_quotehtml $ship_to_first_names] +# set ship_to_last_name [ad_quotehtml $ship_to_last_name] + +# set ship_to_line1 [ad_quotehtml $ship_to_line1] +# set ship_to_line2 [ad_quotehtml $ship_to_line2] +# set ship_to_city [ad_quotehtml $ship_to_city] +# set ship_to_usps_abbrev [ad_quotehtml $ship_to_usps_abbrev] +# set ship_to_zip_code [ad_quotehtml $ship_to_zip_code] +# set ship_to_phone [ad_quotehtml $ship_to_phone] +# cannot quote ship_to_country_code [ad_quotehtml $ship_to_country_code] +# set ship_to_full_state_name [ad_quotehtml $ship_to_full_state_name] +# set ship_to_phone_time [ad_quotehtml $ship_to_phone_time] +# cannot quote ship_to_state_widget [ad_quotehtml $ship_to_state_widget] +} +append hidden_vars [export_form_vars billing_address_id shipping_address_id user_id participant_id] +db_release_unused_handles Index: openacs-4/packages/dotlrn-ecommerce/www/ecommerce/checkout-one-form.xql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/dotlrn-ecommerce/www/ecommerce/checkout-one-form.xql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/dotlrn-ecommerce/www/ecommerce/checkout-one-form.xql 23 Jun 2005 12:28:21 -0000 1.1 @@ -0,0 +1,155 @@ + + + + + + + select order_id + from ec_orders + where user_session_id=:user_session_id + and order_state='in_basket' + + + + + + select order_id, user_id as order_owner + from ec_orders + where user_session_id=:user_session_id + and order_state='in_basket' + + + + + + select i.price_name, i.price_charged, i.color_choice, i.size_choice, i.style_choice, p.product_name, p.one_line_description, p.product_id, count(*) as quantity + from ec_items i, ec_products p + where i.order_id = :order_id + and i.product_id = p.product_id + group by p.product_name, p.one_line_description, p.product_id, i.price_name, i.price_charged, i.color_choice, i.size_choice, i.style_choice + + + + + + update ec_orders + set user_id=:user_id + where order_id=:order_id + + + + + + select count(*) + from ec_items + where order_id=:order_id + + + + + + select count(*) + from ec_addresses + where address_id = :address_id + and user_id = :user_id + + + + + + select shipping_address + from ec_orders + where order_id=:order_id + + + + + + select first_names, last_name + from cc_users + where user_id=:user_id + + + + + + select p.no_shipping_avail_p + from ec_items i, ec_products p + where i.product_id = p.product_id + and p.no_shipping_avail_p = 'f' + and i.order_id = :order_id + group by no_shipping_avail_p + + + + + + select attn, line1, line2, city, usps_abbrev, zip_code, phone, country_code, full_state_name, phone_time + from ec_addresses + where address_id=:address_id + + + + + + update ec_addresses + set attn=:attn, line1=:line1, line2=:line2, city=:city, usps_abbrev=:usps_abbrev, zip_code=:zip_code, phone=:phone, phone_time=:phone_time + where address_id=:address_id + + + + + + insert into ec_addresses + (address_id, user_id, address_type, attn, line1, line2, city, usps_abbrev, zip_code, country_code, phone, phone_time) + values + (:address_id, :user_id, :address_type, :attn, :line1,:line2,:city,:usps_abbrev,:zip_code,:country_code,:phone,:phone_time) + + + + + + select country_code, zip_code + from ec_addresses + where address_id = :address_id + + + + + + update ec_orders + set shipping_address=:address_id + where order_id=:order_id + + + + + + select address_id + from ec_addresses + where user_id=:user_id + and address_type = 'shipping' + + + + + + select shipping, shipping_additional, weight, no_shipping_avail_p + from ec_products + where product_id=:product_id + + + + + + select c.creditcard_id, c.creditcard_type, c.creditcard_last_four, c.creditcard_expire + from ec_creditcards c + where c.user_id=:user_id + and c.creditcard_number is not null + and c.failed_p='f' + and 0 < (select count(*) from ec_orders o where o.creditcard_id = c.creditcard_id) + order by c.creditcard_id desc + + + + Index: openacs-4/packages/dotlrn-ecommerce/www/ecommerce/checkout-oracle.xql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/dotlrn-ecommerce/www/ecommerce/checkout-oracle.xql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/dotlrn-ecommerce/www/ecommerce/checkout-oracle.xql 23 Jun 2005 12:28:21 -0000 1.1 @@ -0,0 +1,21 @@ + + + + + oracle + 8.1.6 + + + + + select count(*) + from dual + where exists (select 1 + from ec_products p, ec_items i + where i.product_id = p.product_id + and i.order_id = :order_id + and no_shipping_avail_p = 't') + + + + Index: openacs-4/packages/dotlrn-ecommerce/www/ecommerce/checkout-postgresql.xql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/dotlrn-ecommerce/www/ecommerce/checkout-postgresql.xql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/dotlrn-ecommerce/www/ecommerce/checkout-postgresql.xql 23 Jun 2005 12:28:21 -0000 1.1 @@ -0,0 +1,20 @@ + + + + + postgresql + 7.1 + + + + + select count(*) + where exists (select 1 + from ec_products p, ec_items i + where i.product_id = p.product_id + and i.order_id = :order_id + and no_shipping_avail_p = 't') + + + + Index: openacs-4/packages/dotlrn-ecommerce/www/ecommerce/checkout-progress.adp =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/dotlrn-ecommerce/www/ecommerce/checkout-progress.adp,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/dotlrn-ecommerce/www/ecommerce/checkout-progress.adp 23 Jun 2005 12:28:21 -0000 1.1 @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + +
    class="altback">Shipping addressclass="altback">--->class="altback">Verify orderclass="altback">--->class="altback">Shipping methodclass="altback">--->class="altback">Billing addressclass="altback">--->class="altback">Payment infoclass="altback">--->class="altback">Confirm order
    Index: openacs-4/packages/dotlrn-ecommerce/www/ecommerce/checkout-progress.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/dotlrn-ecommerce/www/ecommerce/checkout-progress.tcl,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/dotlrn-ecommerce/www/ecommerce/checkout-progress.tcl 23 Jun 2005 12:28:21 -0000 1.1 @@ -0,0 +1 @@ +set express_shipping_avail_p [ad_parameter -package_id [ec_id] ExpressShippingP ecommerce] Index: openacs-4/packages/dotlrn-ecommerce/www/ecommerce/checkout.adp =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/dotlrn-ecommerce/www/ecommerce/checkout.adp,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/dotlrn-ecommerce/www/ecommerce/checkout.adp 23 Jun 2005 12:28:21 -0000 1.1 @@ -0,0 +1,80 @@ + + Completing Your Order: Shipping Address + @context_bar;noquote@ + @ec_system_owner;noquote@ + + + +
    + + +
    + + +

    Select an address listed below or enter a new address.

    +
    + + + + + + + + + + + + + + +
    + @addresses.formatted;noquote@ + + + + + + + +
    +
    + @addresses.use;noquote@ + +
    +
    +
    + @addresses.edit;noquote@ + +
    +
    +
    + @addresses.delete;noquote@ + +
    +
    +
    +   +
    +
    + + + + + + + +
    +
    + @hidden_form_vars;noquote@ + +
    +
    + or + +
    + @hidden_form_vars;noquote@ + +
    +
    + +
    Index: openacs-4/packages/dotlrn-ecommerce/www/ecommerce/checkout.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/dotlrn-ecommerce/www/ecommerce/checkout.tcl,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/dotlrn-ecommerce/www/ecommerce/checkout.tcl 23 Jun 2005 12:28:21 -0000 1.1 @@ -0,0 +1,103 @@ +ad_page_contract { + @param usca_p:optional + + @author + @creation-date + @author ported by Jerry Asher (jerry@theashergroup.com) + @author revised by Bart Teeuwisse (bart.teeuwisse@thecodemill.biz) + @revision-date April 2002 +} { + usca_p:optional +} + + ec_redirect_to_https_if_possible_and_necessary + +# Make sure they have an in_basket order, otherwise they've probably +# gotten here by pushing Back, so return them to index.tcl + +# We need them to be logged in +set user_id [ad_conn user_id] + +if {$user_id == 0} { + set return_url "[ad_conn url]?[export_entire_form_as_url_vars]" + ad_returnredirect "/register?[export_url_vars return_url]" + ad_script_abort +} + + +set user_session_id [ec_get_user_session_id] +ec_create_new_session_if_necessary + +ec_log_user_as_user_id_for_this_session + +set order_id [db_string get_order_id " + select order_id + from ec_orders + where user_session_id = :user_session_id + and order_state='in_basket'" -default "" ] + +if { [empty_string_p $order_id] } { + + # Then they probably got here by pushing "Back", so just redirect + # them to index.tcl + + rp_internal_redirect index + ad_script_abort +} else { + db_dml update_ec_order_set_uid " + update ec_orders + set user_id = :user_id + where order_id = :order_id" +} + +# See if there are any saved shipping addresses for this user + +set address_type "shipping" + +# Check if the order requires shipping + +if {[db_0or1row shipping_avail " + select p.no_shipping_avail_p + from ec_items i, ec_products p + where i.product_id = p.product_id + and p.no_shipping_avail_p = 'f' + and i.order_id = :order_id + group by no_shipping_avail_p"]} { + + set shipping_required true + + # Set the referer to the name of this page so that the user + # returns to this page when the changes to the address have been + # checked. + + set referer checkout + # Present all saved addresses + + template::query get_user_addresses addresses multirow " + select address_id, attn, line1, line2, city, usps_abbrev, zip_code, phone, country_code, full_state_name, phone_time, address_type + from ec_addresses + where user_id=:user_id + and address_type = 'shipping'" -eval { + + set row(formatted) [ec_display_as_html [ec_pretty_mailing_address_from_args $row(line1) $row(line2) $row(city) $row(usps_abbrev) $row(zip_code) $row(country_code) \ + $row(full_state_name) $row(attn) $row(phone) $row(phone_time)]] + set address_id $row(address_id) + set row(delete) "[export_form_vars address_id referer]" + set row(edit) "[export_form_vars address_id address_type referer]" + set row(use) "[export_form_vars address_id]" + } + set hidden_form_vars [export_form_vars address_type referer] + +} else { + set shipping_required false +} + +if { $shipping_required == "false" } { + set address_id "" + ad_returnredirect "checkout-2?[export_url_vars address_id address_type]" + ad_script_abort +} + +set context_bar [template::adp_parse [acs_root_dir]/packages/[ad_conn package_key]/www/contextbar [list context_addition [list "Completing Your Order"]]] +set ec_system_owner [ec_system_owner] +db_release_unused_handles Index: openacs-4/packages/dotlrn-ecommerce/www/ecommerce/checkout.xql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/dotlrn-ecommerce/www/ecommerce/checkout.xql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/dotlrn-ecommerce/www/ecommerce/checkout.xql 23 Jun 2005 12:28:21 -0000 1.1 @@ -0,0 +1,42 @@ + + + + + + + select p.no_shipping_avail_p + from ec_items i, ec_products p + where i.product_id = p.product_id + and p.no_shipping_avail_p = 'f' + and i.order_id = :order_id + group by no_shipping_avail_p + + + + + + select order_id + from ec_orders + where user_session_id=:user_session_id + and order_state='in_basket' + + + + + + update ec_orders + set user_id=:user_id + where order_id=:order_id + + + + + + select address_id, attn, line1, line2, city, usps_abbrev, zip_code, phone, country_code, full_state_name, phone_time + from ec_addresses + where user_id=:user_id + and address_type='shipping' + + + + Index: openacs-4/packages/dotlrn-ecommerce/www/ecommerce/finalize-order-oracle.xql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/dotlrn-ecommerce/www/ecommerce/finalize-order-oracle.xql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/dotlrn-ecommerce/www/ecommerce/finalize-order-oracle.xql 23 Jun 2005 12:28:21 -0000 1.1 @@ -0,0 +1,109 @@ + + + + + oracle + 8.1.6 + + + + + select ec_gift_certificate_balance(:user_id) from dual + + + + + + select ec_order_gift_cert_amount(:order_id) from dual + + + + + + select nvl(sum(i.price_charged),0) - nvl(sum(i.price_refunded),0) as soft_goods_cost, + nvl(sum(i.price_tax_charged),0) - nvl(sum(i.price_tax_refunded),0) as soft_goods_tax + from ec_items i, ec_products p + where i.order_id = :order_id + and i.item_state <> 'void' + and i.product_id = p.product_id + and p.no_shipping_avail_p = 't' + + + + + + select nvl(sum(i.price_charged),0) - nvl(sum(i.price_refunded),0) as hard_goods_cost, + nvl(sum(i.price_tax_charged),0) - nvl(sum(i.shipping_refunded),0) as hard_goods_tax, + nvl(sum(i.shipping_charged),0) - nvl(sum(i.shipping_refunded),0) as hard_goods_shipping, + nvl(sum(i.shipping_tax_charged),0) - nvl(sum(i.shipping_tax_refunded),0) as hard_goods_shipping_tax + from ec_items i, ec_products p + where i.order_id = :order_id + and i.item_state <> 'void' + and i.product_id = p.product_id + and p.no_shipping_avail_p = 'f' + + + + + + insert into ec_financial_transactions + (transaction_id, order_id, transaction_amount, transaction_type, inserted_date) + values + (:transaction_id, :order_id, :transaction_amount, 'charge', sysdate) + + + + + + update ec_financial_transactions + set authorized_date = sysdate + where transaction_id = :transaction_id + + + + + + update ec_financial_transactions + set authorized_date = sysdate, to_be_captured_p = 't', to_be_captured_date = sysdate + where transaction_id = :transaction_id + + + + + + update ec_financial_transactions + set to_be_captured_p = 't', to_be_captured_date = sysdate + where transaction_id = :transaction_id + + + + + + insert into ec_problems_log + (problem_id, problem_date, problem_details, order_id) + values + (ec_problem_id_sequence.nextval, sysdate, :problem_details, :order_id) + + + + + + update ec_financial_transactions + set marked_date = sysdate + where transaction_id = :pgw_transaction_id + + + + + + select nvl(shipping_charged, 0) from ec_orders where order_id = :order_id + + + + + + select ec_tax(0, :order_shipping, :order_id) from dual + + + + Index: openacs-4/packages/dotlrn-ecommerce/www/ecommerce/finalize-order-postgresql.xql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/dotlrn-ecommerce/www/ecommerce/finalize-order-postgresql.xql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/dotlrn-ecommerce/www/ecommerce/finalize-order-postgresql.xql 23 Jun 2005 12:28:21 -0000 1.1 @@ -0,0 +1,109 @@ + + + + + postgresql + 7.1 + + + + + select ec_gift_certificate_balance(:user_id) + + + + + + select ec_order_gift_cert_amount(:order_id) + + + + + + select coalesce(sum(i.price_charged),0) - coalesce(sum(i.price_refunded),0) as soft_goods_cost, + coalesce(sum(i.price_tax_charged),0) - coalesce(sum(i.price_tax_refunded),0) as soft_goods_tax + from ec_items i, ec_products p + where i.order_id = :order_id + and i.item_state <> 'void' + and i.product_id = p.product_id + and p.no_shipping_avail_p = 't' + + + + + + select coalesce(sum(i.price_charged),0) - coalesce(sum(i.price_refunded),0) as hard_goods_cost, + coalesce(sum(i.price_tax_charged),0) - coalesce(sum(i.shipping_refunded),0) as hard_goods_tax, + coalesce(sum(i.shipping_charged),0) - coalesce(sum(i.shipping_refunded),0) as hard_goods_shipping, + coalesce(sum(i.shipping_tax_charged),0) - coalesce(sum(i.shipping_tax_refunded),0) as hard_goods_shipping_tax + from ec_items i, ec_products p + where i.order_id = :order_id + and i.item_state <> 'void' + and i.product_id = p.product_id + and p.no_shipping_avail_p = 'f' + + + + + + insert into ec_financial_transactions + (transaction_id, order_id, transaction_amount, transaction_type, inserted_date) + values + (:transaction_id, :order_id, :transaction_amount, 'charge', current_timestamp) + + + + + + update ec_financial_transactions + set authorized_date = current_timestamp + where transaction_id = :transaction_id + + + + + + update ec_financial_transactions + set authorized_date = current_timestamp, to_be_captured_p = 't', to_be_captured_date = current_timestamp + where transaction_id = :transaction_id + + + + + + update ec_financial_transactions + set to_be_captured_p = 't', to_be_captured_date = current_timestamp + where transaction_id = :transaction_id + + + + + + insert into ec_problems_log + (problem_id, problem_date, problem_details, order_id) + values + (ec_problem_id_sequence.nextval, current_timestamp, :problem_details, :order_id) + + + + + + update ec_financial_transactions + set marked_date = current_timestamp + where transaction_id = :pgw_transaction_id + + + + + + select coalesce(shipping_charged, 0) from ec_orders where order_id = :order_id + + + + + + select ec_tax(0, :order_shipping, :order_id) + + + + Index: openacs-4/packages/dotlrn-ecommerce/www/ecommerce/finalize-order.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/dotlrn-ecommerce/www/ecommerce/finalize-order.tcl,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/dotlrn-ecommerce/www/ecommerce/finalize-order.tcl 23 Jun 2005 12:28:21 -0000 1.1 @@ -0,0 +1,855 @@ +ad_page_contract { + + This script will: + + (1) put this order into the 'confirmed' state + (2) try to authorize the user's credit card info and either + (a) redirect them to a thank you page, or + (b) redirect them to a "please fix your credit card info" + page + + @author + @creation-date + @author ported by Jerry Asher (jerry@theashergroup.com) + @author and Walter McGinnis (wtem@olywa.net) + @author revised by Bart Teeuwisse (bart.teeuwisse@thecodemill.biz) + @revision-date April 2002 + +} { + user_id:integer,notnull + participant_id:integer,optional +} + +# If they reload, we don't have to worry about the credit card +# authorization code being executed twice because the order has +# already been moved to the 'confirmed' state, which means that they +# will be redirected out of this page. We will redirect them to the +# thank you page which displays the order with the most recent +# confirmation date. The only potential problem is that maybe the +# first time the order got to this page it was confirmed but then +# execution of the page stopped before authorization of the order +# could occur. This problem is solved by the scheduled procedure, +# ec_query_for_payment_zombies, which will try to authorize any +# 'confirmed' orders over half an hour old. + +ec_redirect_to_https_if_possible_and_necessary + +set return_url [export_vars -base thank-you { user_id }] + +# first do all the normal checks to make sure nobody is doing url +# or cookie surgery to get here + +# we need them to be logged in +#set user_id [ad_verify_and_get_user_id] + +if {$user_id == 0} { + + set return_url "[ad_conn url]" + + ad_returnredirect "/register?[export_url_vars return_url]" + ad_script_abort +} + +# make sure they have an in_basket order +# unlike previous pages, if they don't have an in_basket order +# it may be because they tried to execute this code twice and +# the order is already in the confirmed state +# In this case, they should be redirected to the thank you +# page for the most recently confirmed order, if one exists, +# otherwise redirect them to index.tcl + +# user session tracking +set user_session_id [ec_get_user_session_id] + +ec_log_user_as_user_id_for_this_session + +set order_id [db_string get_order_id " + select order_id + from ec_orders + where user_session_id = :user_session_id + and order_state = 'in_basket'" -default ""] + +if { [empty_string_p $order_id] } { + + # Find their most recently confirmed order + + set most_recently_confirmed_order [db_string get_mrc_order " + select order_id + from ec_orders + where user_id=:user_id + and confirmed_date is not null + and order_id = (select max(o2.order_id) + from ec_orders o2 + where o2.user_id=:user_id + and o2.confirmed_date is not null)" -default ""] + + if { [empty_string_p $most_recently_confirmed_order] } { + rp_internal_redirect "index" + ns_log Notice "finalize-order.tcl ref(84): no confirmed order for user $user_id. Redirecting user." + } else { + ad_returnredirect .. + } + ad_script_abort +} + +# Make sure there's something in their shopping cart, otherwise +# redirect them to their shopping cart which will tell them that it's +# empty. + +# We may want to make this a redirect to insecure location + +if { [db_string get_in_basket_count " + select count(*) + from ec_items + where order_id = :order_id"] == 0 } { + rp_form_put user_id $user_id + rp_internal_redirect shopping-cart + ad_script_abort +} + +# Make sure the order belongs to this user_id, otherwise they managed +# to skip past checkout.tcl, or they messed w/their user_session_id +# cookie + +set order_owner [db_string get_order_owner " + select user_id + from ec_orders + where order_id = :order_id"] +if { $order_owner != $user_id } { + rp_form_put user_id $user_id + rp_internal_redirect checkout + ad_script_abort +} + +# Make sure there is an address for this order, otherwise they've +# probably gotten here via url surgery, so redirect them to +# checkout.tcl + +set address_id [db_string get_a_shipping_address " + select shipping_address + from ec_orders + where order_id=:order_id" -default ""] +if { [empty_string_p $address_id] } { + + # No shipping address is needed if the order only consists of soft + # goods not requiring shipping. + + if {[db_0or1row shipping_avail " + select p.no_shipping_avail_p, count (*) + from ec_items i, ec_products p + where i.product_id = p.product_id + and p.no_shipping_avail_p = 'f' + and i.order_id = :order_id + group by no_shipping_avail_p"]} { + ad_returnredirect [ec_securelink checkout] + ad_script_abort + } +} + +# Make sure there is a credit card (or that the +# gift_certificate_balance covers the cost) and a shipping method for +# this order, otherwise they've probably gotten here via url surgery, +# so redirect them to checkout-2.tcl + +set creditcard_id [db_string get_creditcard_id " + select creditcard_id + from ec_orders + where order_id=:order_id" -default ""] + +if { [empty_string_p $creditcard_id] } { + + # We only want price and shipping from this (to determine whether + # gift_certificate covers cost) + + set price_shipping_gift_certificate_and_tax [ec_price_shipping_gift_certificate_and_tax_in_an_order $order_id] + set order_total_price_pre_gift_certificate [expr [lindex $price_shipping_gift_certificate_and_tax 0] + [lindex $price_shipping_gift_certificate_and_tax 1]] + set gift_certificate_balance [db_string get_gc_balance " + select ec_gift_certificate_balance(:user_id) + from dual"] + if { $gift_certificate_balance < $order_total_price_pre_gift_certificate } { + set gift_certificate_covers_cost_p "f" + } else { + set gift_certificate_covers_cost_p "t" + } +} + +# set shipping_method [db_string get_shipping_method " +# select shipping_method +# from ec_orders +# where order_id=:order_id" -default ""] +# if { [empty_string_p $shipping_method] || ([empty_string_p $creditcard_id] && (![info exists gift_certificate_covers_cost_p] || $gift_certificate_covers_cost_p == "f")) } { +# rp_internal_redirect checkout-2 +# ad_script_abort +# } + +# Done with all the checks! + +# (1) put this order into the 'confirmed' state + +db_transaction { + ec_update_state_to_confirmed $order_id + + # Call after-checkout callback + callback -- ecommerce::after-checkout -patron_id $user_id -order_id $order_id +} + +set method [db_string payment_method { + select method + from dotlrn_ecommerce_transactions + where order_id = :order_id +} -default "cc"] + +if { ! [empty_string_p $method] && $method != "cc" } { + # Authorize this transaction without credit card + ec_update_state_to_authorized $order_id + ad_returnredirect $return_url + ad_script_abort +} + +# (2) Try to authorize the user's credit card info and either +# (a) send them email & redirect them to a thank you page, or +# (b) redirect them to a "please fix your credit card info" page + +set applied_certificate_amount [db_string get_applied_certificate_amount " + select ec_order_gift_cert_amount(:order_id)"] +db_1row get_soft_goods_costs " + select coalesce(sum(i.price_charged),0) - coalesce(sum(i.price_refunded),0) as soft_goods_cost, + coalesce(sum(i.price_tax_charged),0) - coalesce(sum(i.price_tax_refunded),0) as soft_goods_tax + from ec_items i, ec_products p + where i.order_id = :order_id + and i.item_state <> 'void' + and i.product_id = p.product_id + and p.no_shipping_avail_p = 't'" +db_1row get_hard_goods_costs " + select coalesce(sum(i.price_charged),0) - coalesce(sum(i.price_refunded),0) as hard_goods_cost, + coalesce(sum(i.price_tax_charged),0) - coalesce(sum(i.shipping_refunded),0) as hard_goods_tax, + coalesce(sum(i.shipping_charged),0) - coalesce(sum(i.shipping_refunded),0) as hard_goods_shipping, + coalesce(sum(i.shipping_tax_charged),0) - coalesce(sum(i.shipping_tax_refunded),0) as hard_goods_shipping_tax + from ec_items i, ec_products p + where i.order_id = :order_id + and i.item_state <> 'void' + and i.product_id = p.product_id + and p.no_shipping_avail_p = 'f'" +set order_shipping [db_string get_order_shipping " + select coalesce(shipping_charged, 0) + from ec_orders + where order_id = :order_id"] +set order_shipping_tax [db_string get_order_shipping_tax " + select ec_tax(0, :order_shipping, :order_id)"] + +# Charge soft goods seperately from hard goods as the hard goods +# transaction will not settled until the goods are shipped while soft +# goods can be settled right away. + +if {$hard_goods_cost > 0} { + + # The order contains hard goods that come at a cost. + + if {$soft_goods_cost > 0} { + + # The order contains both hard and soft goods that come at a + # cost. + + if {$applied_certificate_amount >= [expr $soft_goods_cost + $soft_goods_tax]} { + + # The applied certificates cover the cost of the soft + # goods. + + if {[expr $applied_certificate_amount - $soft_goods_cost - $soft_goods_tax] >= [expr $hard_goods_cost + $hard_goods_tax + $hard_goods_shipping + $hard_goods_shipping_tax + \ + $order_shipping + $order_shipping_tax]} { + + # The applied certificates cover the cost of the soft + # goods as well as the hard goods. No financial + # transactions required. Mail the confirmation e-mail + # to the user. + + ec_email_new_order $order_id + + # Change the order state from 'confirmed' to + # 'authorized'. + + ec_update_state_to_authorized $order_id + ad_returnredirect $return_url + + } else { + + # The applied certificates cover the cost of the soft + # goods but not of the hard goods. Create a new + # financial transaction + + set transaction_id [db_nextval ec_transaction_id_sequence] + set transaction_amount [expr $hard_goods_cost + $hard_goods_tax + $hard_goods_shipping + $hard_goods_shipping_tax + $order_shipping + $order_shipping_tax - \ + [expr $applied_certificate_amount - $soft_goods_cost - $soft_goods_tax]] + db_dml insert_financial_transaction " + insert into ec_financial_transactions + (transaction_id, order_id, transaction_amount, transaction_type, inserted_date) + values + (:transaction_id, :order_id, :transaction_amount, 'charge', sysdate)" + + array set response [ec_creditcard_authorization $order_id $transaction_id] + set result $response(response_code) + set transaction_id $response(transaction_id) + if { [string equal $result "authorized"] } { + ec_email_new_order $order_id + + # Change the order state from 'confirmed' to + # 'authorized'. + + ec_update_state_to_authorized $order_id + + # Record the date & time of the authorization. + + db_dml update_authorized_date " + update ec_financial_transactions + set authorized_date = sysdate + where transaction_id = :transaction_id" + } + + if { [string equal $result "authorized"] || [string equal $result "no_recommendation"] } { + ad_returnredirect $return_url + ad_script_abort + } elseif { [string equal $result "failed_authorization"] } { + + # Updates everything that needs to be updated if a + # confirmed order fails + + ec_update_state_to_in_basket $order_id + + # authorization error is not necessarily the fault of the user's card, so log it for identifying pattern for diagnostics + ns_log Notice "finalize-order.tcl ref(295): failed_authorization for order_id: $order_id. Redirecting user to credit-card-correction." + + rp_form_put user_id $user_id + rp_internal_redirect credit-card-correction + ad_script_abort + } else { + + # Then result is probably "invalid_input". This should never + # occur + + ns_log Notice "Order $order_id received a result of $result" + ad_return_error "Sorry" " +

    There has been an error in the processing of your credit card information. + Please contact [ec_system_owner] to report the error.

    " + ad_script_abort + } + } + } else { + + # The applied certificates do no cover the cost of the + # soft goods. + + if {$applied_certificate_amount >= [expr $hard_goods_cost + $hard_goods_tax + $hard_goods_shipping + $hard_goods_shipping_tax + \ + $order_shipping + $order_shipping_tax]} { + + # The applied certificates cover the cost of the hard + # goods but not the soft goods. Create a new financial + # transaction. + + set transaction_id [db_nextval ec_transaction_id_sequence] + set transaction_amount [expr $soft_goods_cost + $soft_goods_tax - \ + [expr $applied_certificate_amount - [expr $hard_goods_cost + $hard_goods_tax + $hard_goods_shipping + $hard_goods_shipping_tax + \ + $order_shipping + $order_shipping_tax]]] + db_dml insert_financial_transaction " + insert into ec_financial_transactions + (transaction_id, order_id, transaction_amount, transaction_type, inserted_date) + values + (:transaction_id, :order_id, :transaction_amount, 'charge', sysdate)" + + array set response [ec_creditcard_authorization $order_id $transaction_id] + set result $response(response_code) + set transaction_id $response(transaction_id) + if { [string equal $result "authorized"] } { + ec_email_new_order $order_id + + # Change the order state from 'confirmed' to + # 'authorized'. + + ec_update_state_to_authorized $order_id + + # Record the date & time of the authorization and + # schedule the transaction for settlement. + + db_dml schedule_settlement " + update ec_financial_transactions + set authorized_date = sysdate, to_be_captured_p = 't', to_be_captured_date = sysdate + where transaction_id = :transaction_id" + + # Mark the transaction now, rather than waiting + # for the scheduled procedures to mark the + # transaction. + + array set response [ec_creditcard_marking $transaction_id] + set mark_result $response(response_code) + set pgw_transaction_id $response(transaction_id) + if { [string equal $mark_result "invalid_input"]} { + set problem_details " + When trying to mark the transaction for the items that don't require shipment (transaction $transaction_id) at [ad_conn url], the following result occurred: $mark_result" + db_dml record_marking_problem " + insert into ec_problems_log + (problem_id, problem_date, problem_details, order_id) + values + (ec_problem_id_sequence.nextval, sysdate, :problem_details, :order_id)" + } elseif {[string equal $mark_result "success"]} { + db_dml update_marked_date " + update ec_financial_transactions + set marked_date = sysdate + where transaction_id = :pgw_transaction_id" + } + + ad_returnredirect $return_url + + } elseif { [string equal $result "failed_authorization"] || [string equal $result "no_recommendation"] } { + + # If the gateway returns no recommendation then + # possibility remains that the card is invalid and + # that soft goods have been 'shipped' because the + # gateway was down and could not verify the soft + # goods transaction. The store owner then depends + # on the honesty of visitor to obtain a new valid + # credit card for the 'shipped' products. + + if {[string equal $result "no_recommendation"] } { + + # Therefor reject the transaction and ask for + # (a new credit card and ask) the visitor to + # retry. Most credit card gateways have + # uptimes close to 99% so this scenario should + # not happen often. Another reason for + # rejecting transactions without + # recommendation is that the scheduled + # procedures can't authorize soft goods + # transactions properly. + + db_dml set_transaction_failed " + update ec_financial_transactions + set failed_p = 't' + where transaction_id = :transaction_id" + + } + + # Updates everything that needs to be updated if a + # confirmed order fails + + ec_update_state_to_in_basket $order_id + ns_log Notice "finalize-order.tcl ref(411): updated creditcard check failed for order_id $order_id. Redirecting to credit-card-correction" + rp_form_put user_id $user_id + rp_internal_redirect credit-card-correction + ad_script_abort + } else { + + # Then result is probably "invalid_input". This should never + # occur + + ns_log Notice "Order $order_id received a result of $result" + ad_return_error "Sorry" " +

    There has been an error in the processing of your credit card information. + Please contact [ec_system_owner] to report the error.

    " + } + } else { + + # The applied certificates cover neither the cost of + # the hard goods nor the soft goods. Create separate + # transactions for the soft goods and the hard goods. + + set transaction_id [db_nextval ec_transaction_id_sequence] + set transaction_amount [expr $soft_goods_cost + $soft_goods_tax - $applied_certificate_amount] + db_dml insert_financial_transaction " + insert into ec_financial_transactions + (transaction_id, order_id, transaction_amount, transaction_type, inserted_date) + values + (:transaction_id, :order_id, :transaction_amount, 'charge', sysdate)" + + array set response [ec_creditcard_authorization $order_id $transaction_id] + set result $response(response_code) + set soft_goods_transaction_id $response(transaction_id) + if { [string equal $result "authorized"] } { + ec_email_new_order $order_id + + # Record the date & time of the soft goods + # authorization. + + set transaction_id $soft_goods_transaction_id + db_dml update_authorized_date " + update ec_financial_transactions + set authorized_date = sysdate + where transaction_id = :transaction_id" + + # Calculate the transaction amount for the hard + # goods. + + set transaction_amount [expr $hard_goods_cost + $hard_goods_tax + $hard_goods_shipping + $hard_goods_shipping_tax + $order_shipping + $order_shipping_tax + \ + $soft_goods_cost + $soft_goods_tax - $transaction_amount] + set transaction_id [db_nextval ec_transaction_id_sequence] + db_dml insert_financial_transaction " + insert into ec_financial_transactions + (transaction_id, order_id, transaction_amount, transaction_type, inserted_date) + values + (:transaction_id, :order_id, :transaction_amount, 'charge', sysdate)" + + array set response [ec_creditcard_authorization $order_id $transaction_id] + set result $response(response_code) + set hard_goods_transaction_id $response(transaction_id) + if { [string equal $result "authorized"] } { + + # Both transactions are approved. Change the + # order state from 'confirmed' to + # 'authorized'. + + ec_update_state_to_authorized $order_id + + # Schedule the soft goods transaction for + # settlement. + + set transaction_id $soft_goods_transaction_id + db_dml schedule_settlement_soft_goods " + update ec_financial_transactions + set to_be_captured_p = 't', to_be_captured_date = sysdate + where transaction_id = :transaction_id" + + # Mark the transaction now, rather than + # waiting for the scheduled procedures to mark + # the transaction. + + array set response [ec_creditcard_marking $transaction_id] + set mark_result $response(response_code) + set pgw_transaction_id $response(transaction_id) + if { [string equal $mark_result "invalid_input"]} { + set problem_details " + When trying to mark the transaction for the items that don't require shipment (transaction $transaction_id) at [ad_conn url], the following result occurred: $mark_result" + db_dml record_marking_problem " + insert into ec_problems_log + (problem_id, problem_date, problem_details, order_id) + values + (ec_problem_id_sequence.nextval, sysdate, :problem_details, :order_id)" + } elseif {[string equal $mark_result "success"]} { + db_dml update_marked_date " + update ec_financial_transactions + set marked_date = sysdate + where transaction_id = :pgw_transaction_id" + } + + # Record the date & time of the hard goods + # authorization. + + set transaction_id $hard_goods_transaction_id + db_dml update_authorized_date " + update ec_financial_transactions + set authorized_date = sysdate + where transaction_id = :transaction_id" + + ad_returnredirect $return_url + + } elseif {[string equal $result "failed_authorization"] || [string equal $result "no_recommendation"] } { + + # Record both transactions as failed and ask + # for a new credit card number. The second + # transaction could have failed because it + # maxed out the card. Both transactions need + # to failed as the user might choose to use a + # different card and this procedure doesn't + # check for prior authorized transactions. + + set transaction_id $soft_goods_transaction_id + db_dml set_transaction_failed " + update ec_financial_transactions + set failed_p = 't' + where transaction_id = :transaction_id" + + set transaction_id $hard_goods_transaction_id + db_dml set_transaction_failed " + update ec_financial_transactions + set failed_p = 't' + where transaction_id = :transaction_id" + + # Updates everything that needs to be updated if a + # confirmed order fails + + ec_update_state_to_in_basket $order_id + ns_log Notice "finalize-order.tcl ref(544): creditcard check failed. Redirecting user to credit-card-correction." + rp_form_put user_id $user_id + rp_internal_redirect credit-card-correction + + } else { + + # Then result is probably + # "invalid_input". This should never occur + + ns_log Notice "Order $order_id received a result of $result" + ad_return_error "Sorry" " +

    There has been an error in the processing of your credit card information. + Please contact [ec_system_owner] to report the error.

    " + } + } elseif { [string equal $result "failed_authorization"] || [string equal $result "no_recommendation"] } { + + set transaction_id $soft_goods_transaction_id + db_dml set_transaction_failed " + update ec_financial_transactions + set failed_p = 't' + where transaction_id = :transaction_id" + + # Updates everything that needs to be updated if a + # confirmed order fails + + ec_update_state_to_in_basket $order_id + + rp_form_put user_id $user_id + rp_internal_redirect credit-card-correction + ad_script_abort + } else { + + # Then result is probably "invalid_input". This should never + # occur + + ns_log Notice "Order $order_id received a result of $result" + ad_return_error "Sorry" " +

    There has been an error in the processing of your credit card information. + Please contact [ec_system_owner] to report the error.

    " + } + } + } + } else { + + # The order contains only hard goods that come at a cost. + + if {$applied_certificate_amount >= [expr $hard_goods_cost + $hard_goods_tax + $hard_goods_shipping + $hard_goods_shipping_tax + $order_shipping + $order_shipping_tax]} { + + # The applied certificates cover the cost of the hard + # goods. No financial transaction required. + + # Mail the confirmation e-mail to the user. + + ec_email_new_order $order_id + + # Change the order state from 'confirmed' to + # 'authorized'. + + ec_update_state_to_authorized $order_id + ad_returnredirect $return_url + + } else { + + # The applied certificates only partially covered the cost + # of the hard goods. Create a new financial transaction. + + set transaction_id [db_nextval ec_transaction_id_sequence] + set transaction_amount [expr $hard_goods_cost + $hard_goods_tax + $hard_goods_shipping + $hard_goods_shipping_tax + $order_shipping + $order_shipping_tax - \ + [expr $applied_certificate_amount - $soft_goods_cost - $soft_goods_tax]] + db_dml insert_financial_transaction " + insert into ec_financial_transactions + (transaction_id, order_id, transaction_amount, transaction_type, inserted_date) + values + (:transaction_id, :order_id, :transaction_amount, 'charge', sysdate)" + + array set response [ec_creditcard_authorization $order_id $transaction_id] + set result $response(response_code) + set transaction_id $response(transaction_id) + if { [string equal $result "authorized"] } { + ec_email_new_order $order_id + + # Change the order state from 'confirmed' to + # 'authorized'. + + ec_update_state_to_authorized $order_id + + # Record the date & time of the authorization. + + db_dml update_authorized_date " + update ec_financial_transactions + set authorized_date = sysdate + where transaction_id = :transaction_id" + } + + if { [string equal $result "authorized"] || [string equal $result "no_recommendation"] } { + ad_returnredirect $return_url + ad_script_abort + } elseif { [string equal $result "failed_authorization"] } { + + # If the gateway returns no recommendation then + # possibility remains that the card is invalid and + # that soft goods have been 'shipped' because the + # gateway was down and could not verify the soft goods + # transaction. The store owner then depends on the + # honesty of visitor to obtain a new valid credit card + # for the 'shipped' products. + + if {[string equal $result "no_recommendation"] } { + + # Therefor reject the transaction and ask for (a + # new credit card and ask) the visitor to + # retry. Most credit card gateways have uptimes + # close to 99% so this scenario should not happen + # often. Another reason for rejecting transactions + # without recommendation is that the scheduled + # procedures can't authorize soft goods + # transactions properly. + + db_dml set_transaction_failed " + update ec_financial_transactions + set failed_p = 't' + where transaction_id = :transaction_id" + + } + + # Updates everything that needs to be updated if a + # confirmed order fails + + ec_update_state_to_in_basket $order_id + + # log this just in case this is a symptom of an extended gateway downtime + ns_log Notice "finalize-order.tcl, ref(671): creditcard check failed for order_id $order_id. Redirecting to credit-card-correction" + + rp_form_put user_id $user_id + rp_internal_redirect credit-card-correction + ad_script_abort + } else { + + # Then result is probably "invalid_input". This should never + # occur + + ns_log Notice "Order $order_id received a result of $result" + ad_return_error "Sorry" " +

    There has been an error in the processing of your credit card information. + Please contact [ec_system_owner] to report the error.

    " + } + } + } +} else { + + # The order does not contain any hard goods that come at a cost. + + if {$soft_goods_cost > 0} { + + # The order contains only soft goods that come at a cost. + + if {$applied_certificate_amount >= [expr $soft_goods_cost + $soft_goods_tax]} { + + # The gift certificates cover the cost of the soft + # goods. No financial transaction required. Mail a + # confirmation e-mail to the user. + + ec_email_new_order $order_id + + # Change the order state from 'confirmed' to + # 'authorized'. + + ec_update_state_to_authorized $order_id + ad_returnredirect $return_url + + } else { + + # The certificates only partially cover the cost of the + # soft goods. Create a new financial transaction + + set transaction_id [db_nextval ec_transaction_id_sequence] + set transaction_amount [expr $soft_goods_cost + $soft_goods_tax - $applied_certificate_amount] + db_dml insert_financial_transaction " + insert into ec_financial_transactions + (transaction_id, order_id, transaction_amount, transaction_type, inserted_date) + values + (:transaction_id, :order_id, :transaction_amount, 'charge', sysdate)" + + array set response [ec_creditcard_authorization $order_id $transaction_id] + set result $response(response_code) + set transaction_id $response(transaction_id) + if { [string equal $result "authorized"] } { + ec_email_new_order $order_id + + # Change the order state from 'confirmed' to + # 'authorized'. + + ec_update_state_to_authorized $order_id + + # Record the date & time of the authorization and + # schedule the transaction for settlement. + + db_dml schedule_settlement " + update ec_financial_transactions + set authorized_date = sysdate, to_be_captured_p = 't', to_be_captured_date = sysdate + where transaction_id = :transaction_id" + + # Mark the transaction now, rather than waiting for + # the scheduled procedures to mark the transaction. + + array set response [ec_creditcard_marking $transaction_id] + set mark_result $response(response_code) + set pgw_transaction_id $response(transaction_id) + if { [string equal $mark_result "invalid_input"]} { + set problem_details " + When trying to mark the transaction for the items that don't require shipment (transaction $transaction_id) at [ad_conn url], the following result occurred: $mark_result" + db_dml record_marking_problem " + insert into ec_problems_log + (problem_id, problem_date, problem_details, order_id) + values + (ec_problem_id_sequence.nextval, sysdate, :problem_details, :order_id)" + } elseif {[string equal $mark_result "success"]} { + db_dml update_marked_date " + update ec_financial_transactions + set marked_date = sysdate + where transaction_id = :pgw_transaction_id" + } + ad_returnredirect $return_url + } + + if {[string equal $result "failed_authorization"] || [string equal $result "no_recommendation"] } { + + # If the gateway returns no recommendation then the + # possibility remains that the card is invalid and + # that soft goods have been 'shipped' because the + # gateway was down and could not verify the soft goods + # transaction. The store owner then depends on the + # honesty of visitor to obtain a new valid credit card + # for the 'shipped' products. + + if {[string equal $result "no_recommendation"] } { + + # Therefor reject the transaction and ask for (a + # new credit card and ask) the visitor to + # retry. Most credit card gateways have uptimes + # close to 99% so this scenario should not happen + # often. Another reason for rejecting transactions + # without recommendation is that the scheduled + # procedures can't authorize soft goods + # transactions properly. + + db_dml set_transaction_failed " + update ec_financial_transactions + set failed_p = 't' + where transaction_id = :transaction_id" + + } + + # Updates everything that needs to be updated if a + # confirmed order fails + + ec_update_state_to_in_basket $order_id + ns_log Notice "finalize-order.tcl ref(789): creditcard check failed. Redirecting to credit-card-correction" + rp_form_put user_id $user_id + rp_internal_redirect credit-card-correction + ad_script_abort + + } else { + + # Then result is probably "invalid_input". This should never + # occur + + ns_log Notice "Order $order_id received a result of $result" + ad_return_error "Sorry" " +

    There has been an error in the processing of your credit card information. + Please contact [ec_system_owner] to report the error.

    " + } + } + } else { + + # The order contains neither hard nor soft goods that come at + # a cost. No financial transactions required. Mail the + # confirmation e-mail to the user. + + ec_email_new_order $order_id + + # Change the order state from 'confirmed' to + # 'authorized'. + + ec_update_state_to_authorized $order_id + ad_returnredirect $return_url + } +} Index: openacs-4/packages/dotlrn-ecommerce/www/ecommerce/finalize-order.xql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/dotlrn-ecommerce/www/ecommerce/finalize-order.xql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/dotlrn-ecommerce/www/ecommerce/finalize-order.xql 23 Jun 2005 12:28:21 -0000 1.1 @@ -0,0 +1,83 @@ + + + + + + + select order_id + from ec_orders + where user_session_id=:user_session_id + and order_state='in_basket' + + + + + + select order_id + from ec_orders + where user_id=:user_id + and confirmed_date is not null + and order_id=(select max(o2.order_id) + from ec_orders o2 + where o2.user_id=:user_id + and o2.confirmed_date is not null) + + + + + + select count(*) + from ec_items + where order_id=:order_id + + + + + + select user_id + from ec_orders + where order_id=:order_id + + + + + + select shipping_address + from ec_orders + where order_id=:order_id + + + + + + select creditcard_id + from ec_orders + where order_id=:order_id + + + + + + select shipping_method + from ec_orders + where order_id=:order_id + + + + + + update ec_financial_transactions + set failed_p = 't' + where transaction_id = :transaction_id" + + + + + + update ec_financial_transactions + set failed_p = 't' + where transaction_id = :transaction_id + + + + Index: openacs-4/packages/dotlrn-ecommerce/www/ecommerce/shopping-cart-add-oracle.xql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/dotlrn-ecommerce/www/ecommerce/shopping-cart-add-oracle.xql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/dotlrn-ecommerce/www/ecommerce/shopping-cart-add-oracle.xql 23 Jun 2005 12:28:21 -0000 1.1 @@ -0,0 +1,47 @@ + + + + + oracle + 8.1.6 + + + + + insert into ec_orders + (order_id, user_session_id, order_state, in_basket_date) + select :order_id, :user_session_id, 'in_basket', sysdate from dual + where not exists (select 1 + from ec_orders + where user_session_id=:user_session_id + and order_state='in_basket') + + + + + + insert into ec_problems_log + (problem_id, problem_date, problem_details) + values + (ec_problem_id_sequence.nextval, sysdate,:errormsg) + + + + + + insert into ec_items + (item_id, product_id, color_choice, size_choice, style_choice, order_id, in_cart_date) + (select ec_item_id_sequence.nextval, :product_id, :color_choice, :size_choice, :style_choice, :order_id, sysdate + from dual + where not exists (select 1 + from ec_items + where order_id=:order_id + and product_id=:product_id + and color_choice [ec_decode $color_choice "" "is null" "= :color_choice"] + and size_choice [ec_decode $size_choice "" "is null" "= :size_choice"] + and style_choice [ec_decode $style_choice "" "is null" "= :style_choice"] + and ((sysdate - in_cart_date) * 86400 < 5))) + + + + Index: openacs-4/packages/dotlrn-ecommerce/www/ecommerce/shopping-cart-add-postgresql.xql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/dotlrn-ecommerce/www/ecommerce/shopping-cart-add-postgresql.xql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/dotlrn-ecommerce/www/ecommerce/shopping-cart-add-postgresql.xql 23 Jun 2005 12:28:21 -0000 1.1 @@ -0,0 +1,36 @@ + + + + + postgresql + 7.1 + + + + + insert into ec_orders + (order_id, user_session_id, order_state, in_basket_date) + select :order_id, :user_session_id, 'in_basket', current_timestamp + where not exists (select 1 from ec_orders where user_session_id=:user_session_id and order_state='in_basket') + + + + + + insert into ec_problems_log + (problem_id, problem_date, problem_details) + values + (ec_problem_id_sequence.nextval, current_timestamp,:errormsg) + + + + + + insert into ec_items + (item_id, product_id, color_choice, size_choice, style_choice, order_id, in_cart_date) + select :item_id, :product_id, :color_choice, + :size_choice, :style_choice, :order_id, current_timestamp from dual + + + + Index: openacs-4/packages/dotlrn-ecommerce/www/ecommerce/shopping-cart-add.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/dotlrn-ecommerce/www/ecommerce/shopping-cart-add.tcl,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/dotlrn-ecommerce/www/ecommerce/shopping-cart-add.tcl 23 Jun 2005 12:28:21 -0000 1.1 @@ -0,0 +1,160 @@ +ad_page_contract { + + This adds an item to an 'in_basket' order, although if there + exists a 'confirmed' order for this user_session_id, the user is + told they have to wait because 'confirmed' orders can potentially + become 'in_basket' orders (if authorization fails), and we can + only have one 'in_basket' order for this user_session_id at a + time. Most orders are only in the 'confirmed' state for a few + seconds, except for those whose credit card authorizations are + inconclusive. Furthermore, it is unlikely for a user to start + adding things to their shopping cart right after they've made an + order. So this case is unlikely to occur often. I will include a + ns_log Notice so that any occurrences will be logged. + + @param product_id:integer + @param size_choice + @param color_choice + @param style_choice + @param usca_p:optional + + @author + @creation-date + @author ported by Jerry Asher (jerry@theashergroup.com) + @author revised by Bart Teeuwisse (bart.teeuwisse@thecodemill.biz) + @revision-date April 2002 + +} { + product_id:integer + {item_count 1} + {size_choice ""} + {color_choice ""} + {style_choice ""} + usca_p:optional + + user_id:integer,notnull + {participant_id:integer 0} +} +# added default values to above params so that this page works +# when a post from a form to shopping-cart-add originates from another domain. + +# 1. get user_session_id +# 1.5 see if there exists a 'confirmed' order for this user_session_id +# 2. get order_id +# 3. get item_id +# 4. put item into ec_items, unless there is already an item with that product_id +# in that order (this is double click protection -- the only way they can increase +# the quantity of a product in their order is to click on "update quantities" on +# the shopping cart page (shopping-cart.tcl) +# 5. ad_returnredirect them to their shopping cart + +set user_session_id [ec_get_user_session_id] +ec_create_new_session_if_necessary [export_url_vars product_id user_id participant_id] +set n_confirmed_orders [db_string get_n_confirmed_orders " + select count(*) + from ec_orders + where user_session_id = :user_session_id + and order_state = 'confirmed'"] +if { $n_confirmed_orders > 0 } { + ad_return_complaint 1 " +

    Sorry, you have an order for which credit card authorization has not yet taken place. + Please wait for the authorization to complete before adding new items to your shopping cart.

    +

    Thank you.

    " + ns_log Warning "shopping-cart-add.tcl,line59: User tried to add an item to the shopping cart after making a purchase, but was rejected!" + ad_script_abort +} + +set order_id [db_string get_order_id " + select order_id + from ec_orders + where user_session_id = :user_session_id + and order_state = 'in_basket'" -default ""] + +# Here's the airtight way to do it: do the check on order_id, then +# insert a new order where there doesn't exist an old one, then set +# order_id again (because the correct order_id might not be the one +# set inside the if statement). It should now be impossible for +# order_id to be the empty string (if it is, log the error and +# redirect them to product.tcl). + +if { [value_if_exists order_id] < 1 || [ad_var_type_check_number_p $order_id] == 0 } { + set order_id [db_nextval ec_order_id_sequence] + + # Create the order (if an in_basket order *still* doesn't exist) + + db_dml insert_new_ec_order " + insert into ec_orders + (order_id, user_session_id, order_state, in_basket_date) + select :order_id, :user_session_id, 'in_basket', sysdate from dual + where not exists (select 1 from ec_orders where user_session_id = :user_session_id and order_state = 'in_basket')" + + # Now either an in_basket order should have been inserted by the + # above statement or it was inserted by a different thread + # milliseconds ago + + set order_id [db_string get_order_id " + select order_id + from ec_orders + where user_session_id = :user_session_id + and order_state = 'in_basket'" -default ""] + if { [empty_string_p $order_id] } { + + # I don't expect this to ever happen, but just in case, I'll + # log the problem and redirect them to product.tcl + + set errormsg "Null order_id on shopping-cart-add.tcl for user_session_id :user_session_id. Please report this problem to [ec_package_maintainer]." + db_dml insert_problem_into_log " + insert into ec_problems_log + (problem_id, problem_date, problem_details) + values + (ec_problem_id_sequence.nextval, sysdate,:errormsg)" + ad_returnredirect "product?[export_url_vars product_id]" + ad_script_abort + } +} + +# Insert an item into that order if an identical item doesn't exist +# (this is double click protection). If they want to update +# quantities, they can do so from the shopping cart page. + +# Bart Teeuwisse: Fine tuned the postgresql version to only reject +# items that were added to the shopping cart in the last 5 seconds. +# That should be enough to protect from double clicks yet provides a +# more intuitive user experience. + +# Roel: Participant also pays +if { $participant_id == 0 } { + set participant_id $user_id +} +for {set i 0} {$i < $item_count} {incr i} { + db_transaction { + set item_id [db_nextval ec_item_id_sequence] + + if { ( [exists_and_not_null participant_id] ) } { + set limit_order_p [expr ! [db_string order_exists { + select count(*) + from ec_items i, dotlrn_ecommerce_orders o, ec_orders eo + where i.item_id = o.item_id + and i.order_id = eo.order_id + and i.product_id = :product_id + and o.participant_id = :participant_id + and eo.order_state = 'in_basket' + and eo.user_session_id = :user_session_id + } -default 0]] + } else { + set limit_order_p 1 + } + + if { $limit_order_p } { + db_dml insert_new_item_in_order {} + + db_dml insert_new_item_order_dotlrn_ecommerce { + insert into dotlrn_ecommerce_orders (item_id, patron_id, participant_id) + values (:item_id, :user_id, :participant_id) + } + } + } +} + +db_release_unused_handles +ad_returnredirect [export_vars -base shopping-cart { user_id product_id }] \ No newline at end of file Index: openacs-4/packages/dotlrn-ecommerce/www/ecommerce/shopping-cart-add.xql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/dotlrn-ecommerce/www/ecommerce/shopping-cart-add.xql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/dotlrn-ecommerce/www/ecommerce/shopping-cart-add.xql 23 Jun 2005 12:28:21 -0000 1.1 @@ -0,0 +1,23 @@ + + + + + + + select count(*) + from ec_orders + where user_session_id=:user_session_id + and order_state='confirmed' + + + + + + select order_id + from ec_orders + where user_session_id=:user_session_id + and order_state='in_basket' + + + + Index: openacs-4/packages/dotlrn-ecommerce/www/ecommerce/shopping-cart-delete-from.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/dotlrn-ecommerce/www/ecommerce/shopping-cart-delete-from.tcl,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/dotlrn-ecommerce/www/ecommerce/shopping-cart-delete-from.tcl 23 Jun 2005 12:28:21 -0000 1.1 @@ -0,0 +1,47 @@ +# www/ecommerce/shopping-cart-delete-from.tcl +ad_page_contract { + @param product_id + @param color_choice + @param size_choice + @param style_choice + @author + @creation-date + @cvs-id $Id: shopping-cart-delete-from.tcl,v 1.1 2005/06/23 12:28:21 roelc Exp $ + @author ported by Jerry Asher (jerry@theashergroup.com) +} { + product_id:integer + + color_choice:optional + size_choice:optional + style_choice:optional + + user_id:integer,notnull,optional + patron_id:integer,notnull,optional + participant_id:integer,notnull,optional +} + + +set user_session_id [ec_get_user_session_id] + + + + +set order_id [db_string get_order_id "select order_id from ec_orders where user_session_id=:user_session_id and order_state='in_basket'" -default ""] + +if { [empty_string_p $order_id] } { + # then they probably got here by pushing "Back", so just redirect them + # into their empty shopping cart + rp_internal_redirect shopping-cart + ad_script_abort +} + +if { [exists_and_not_null patron_id] && [exists_and_not_null participant_id] } { + set process_purchase_clause [db_map delete_item_from_cart_purchase_process] +} else { + set process_purchase_clause "" +} + +db_dml delete_item_from_cart "delete from ec_items where order_id=:order_id and product_id=:product_id and color_choice [ec_decode $color_choice "" "is null" "= :color_choice"] and size_choice [ec_decode $size_choice "" "is null" "= :size_choice"] and style_choice [ec_decode $style_choice "" "is null" "= :style_choice"]" +db_release_unused_handles + +rp_internal_redirect shopping-cart Index: openacs-4/packages/dotlrn-ecommerce/www/ecommerce/shopping-cart-delete-from.xql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/dotlrn-ecommerce/www/ecommerce/shopping-cart-delete-from.xql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/dotlrn-ecommerce/www/ecommerce/shopping-cart-delete-from.xql 23 Jun 2005 12:28:21 -0000 1.1 @@ -0,0 +1,37 @@ + + + + + + + select order_id + from ec_orders + where user_session_id=:user_session_id + and order_state='in_basket' + + + + + + delete from ec_items + where order_id=:order_id + and product_id=:product_id + and color_choice [ec_decode $color_choice "" "is null" "= :color_choice"] + and size_choice [ec_decode $size_choice "" "is null" "= :size_choice"] + and style_choice [ec_decode $style_choice "" "is null" "= :style_choice"] + + $process_purchase_clause + + + + + + and item_id in (select item_id + from dotlrn_ecommerce_orders + where order_id = :order_id + and product_id = :product_id + and patron_id = :patron_id + and participant_id = :participant_id) + + + Index: openacs-4/packages/dotlrn-ecommerce/www/ecommerce/shopping-cart-oracle.xql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/dotlrn-ecommerce/www/ecommerce/shopping-cart-oracle.xql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/dotlrn-ecommerce/www/ecommerce/shopping-cart-oracle.xql 23 Jun 2005 12:28:21 -0000 1.1 @@ -0,0 +1,46 @@ + + + + + oracle + 8.1.6 + + + + + select nvl(base_shipping_cost,0) as base_shipping_cost, + nvl(default_shipping_per_item,0) as default_shipping_per_item, + nvl(weight_shipping_cost,0) as weight_shipping_cost, + nvl(add_exp_base_shipping_cost,0) as add_exp_base_shipping_cost, + nvl(add_exp_amount_per_item,0) as add_exp_amount_per_item, + nvl(add_exp_amount_by_weight,0) as add_exp_amount_by_weight + from ec_admin_settings + + + + + + select p.product_name, p.one_line_description, p.no_shipping_avail_p, p.shipping, p.shipping_additonal, p.weight, p.product_id, count(*) as quantity, u.offer_code, i.color_choice, i.size_choice, i.style_choice, '' as price + from ec_orders o, ec_items i, ec_products p, + (select product_id, offer_code from ec_user_session_offer_codes usoc where usoc.user_session_id=:user_session_id) u + where i.product_id=p.product_id + and o.order_id=i.order_id + and p.product_id=u.product_id(+) + and o.user_session_id=:user_session_id and o.order_state='in_basket' + group by p.product_name, p.one_line_description, p.no_shipping_avail_p, p.shipping, p.shipping_additonal, p.weight, p.product_id, u.offer_code, i.color_choice, i.size_choice, i.style_choice + + + + + + select i.product_id, i.color_choice, i.size_choice, i.style_choice, count(*) as item_count, u.offer_code + from ec_products p, ec_items i, ec_user_session_offer_codes u + where u.product_id(+)=i.product_id and (u.user_session_id is null or u.user_session_id=:user_session_id) + and i.product_id = p.product_id + and p.no_shipping_avail_p = 'f' + and i.order_id = :order_id + group by i.product_id, i.color_choice, i.size_choice, i.style_choice, u.offer_code + + + + Index: openacs-4/packages/dotlrn-ecommerce/www/ecommerce/shopping-cart-postgresql.xql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/dotlrn-ecommerce/www/ecommerce/shopping-cart-postgresql.xql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/dotlrn-ecommerce/www/ecommerce/shopping-cart-postgresql.xql 23 Jun 2005 12:28:21 -0000 1.1 @@ -0,0 +1,49 @@ + + + + + postgresql + 7.1 + + + + + select coalesce(base_shipping_cost,0) as base_shipping_cost, + coalesce(default_shipping_per_item,0) as default_shipping_per_item, + coalesce(weight_shipping_cost,0) as weight_shipping_cost, + coalesce(add_exp_base_shipping_cost,0) as add_exp_base_shipping_cost, + coalesce(add_exp_amount_per_item,0) as add_exp_amount_per_item, + coalesce(add_exp_amount_by_weight,0) as add_exp_amount_by_weight + from ec_admin_settings + + + + + + select p.product_name, p.one_line_description, p.no_shipping_avail_p, p.shipping, p.shipping_additional, p.weight, p.product_id, count(*) as quantity, u.offer_code, i.color_choice, i.size_choice, i.style_choice, '' as price, deo.patron_id, deo.participant_id + from ec_orders o + join ec_items i on (o.order_id=i.order_id) + join ec_products p on (i.product_id=p.product_id) + left join (select product_id, offer_code + from ec_user_session_offer_codes usoc + where usoc.user_session_id=:user_session_id) u on (p.product_id=u.product_id) + left join dotlrn_ecommerce_orders deo on (i.item_id = deo.item_id) + where o.user_session_id=:user_session_id + and o.order_state='in_basket' + group by p.product_name, p.one_line_description, p.no_shipping_avail_p, p.shipping, p.shipping_additional, p.weight, p.product_id, u.offer_code, i.color_choice, i.size_choice, i.style_choice, deo.patron_id, deo.participant_id + + + + + + select i.product_id, i.color_choice, i.size_choice, i.style_choice, count(*) as item_count, u.offer_code + from ec_products p, ec_items i + left join ec_user_session_offer_codes u on (u.product_id = i.product_id and u.user_session_id = :user_session_id) + where i.product_id = p.product_id + and p.no_shipping_avail_p = 'f' + and i.order_id = :order_id + group by i.product_id, i.color_choice, i.size_choice, i.style_choice, u.offer_code + + + + Index: openacs-4/packages/dotlrn-ecommerce/www/ecommerce/shopping-cart-quantities-change-oracle.xql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/dotlrn-ecommerce/www/ecommerce/shopping-cart-quantities-change-oracle.xql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/dotlrn-ecommerce/www/ecommerce/shopping-cart-quantities-change-oracle.xql 23 Jun 2005 12:28:21 -0000 1.1 @@ -0,0 +1,18 @@ + + + + + oracle + 8.1.6 + + + + + insert into ec_items + (item_id, product_id, color_choice, size_choice, style_choice, order_id, in_cart_date) + values + (ec_item_id_sequence.nextval, :product_id, :color_choice, :size_choice, :style_choice, :order_id, sysdate) + + + + Index: openacs-4/packages/dotlrn-ecommerce/www/ecommerce/shopping-cart-quantities-change-postgresql.xql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/dotlrn-ecommerce/www/ecommerce/shopping-cart-quantities-change-postgresql.xql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/dotlrn-ecommerce/www/ecommerce/shopping-cart-quantities-change-postgresql.xql 23 Jun 2005 12:28:21 -0000 1.1 @@ -0,0 +1,18 @@ + + + + + postgresql + 7.1 + + + + + insert into ec_items + (item_id, product_id, color_choice, size_choice, style_choice, order_id, in_cart_date) + values + (ec_item_id_sequence.nextval, :product_id, :color_choice, :size_choice, :style_choice, :order_id, current_timestamp) + + + + Index: openacs-4/packages/dotlrn-ecommerce/www/ecommerce/shopping-cart-quantities-change.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/dotlrn-ecommerce/www/ecommerce/shopping-cart-quantities-change.tcl,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/dotlrn-ecommerce/www/ecommerce/shopping-cart-quantities-change.tcl 23 Jun 2005 12:28:21 -0000 1.1 @@ -0,0 +1,164 @@ +# www/ecommerce/shopping-cart-quantities-change.tcl +ad_page_contract { + + Changes the quantity of an item in an order. An item is a unique + combination of product_id, Color, Size, and Style. In addition, + each item is represented by a row in the database, so changing + quantities involves inserting and deleting rows. + + @quantity -- an array whose keys are tcl lists of product_id, color, size, and style + @param return_url -- optional, probably will take the user back to process_order_quantity_shipping.tcl + @author original author unknown (eveander@arsdigita.com?) + @author heavily modified by jgoler@arsdigita.com + @author hbrock@arsdigita.com + @creation-date + @cvs-id $Id: shopping-cart-quantities-change.tcl,v 1.1 2005/06/23 12:28:21 roelc Exp $ + @author ported by Jerry Asher (jerry@theashergroup.com) +} { + return_url:optional + quantity:array,naturalnum +} + + +set user_session_id [ec_get_user_session_id] + + + +if { $user_session_id == 0 } { + doc_return 200 text/html "[ad_header "No Cart Found"]

    No Shopping Cart Found

    +

    + We could not find any shopping cart for you. This may be because you have cookies + turned off on your browser. Cookies are necessary in order to have a shopping cart + system so that we can tell which items are yours. + +

    + In Netscape 4.0, you can enable cookies from Edit -> Preferences -> Advanced.
    + + In Microsoft Internet Explorer 4.0, you can enable cookies from View -> + Internet Options -> Advanced -> Security.
    + +

    + + [ec_continue_shopping_options] + " + ad_script_abort +} + +set order_id [db_string get_order_id "select order_id from ec_orders where order_state='in_basket' and user_session_id=:user_session_id" -default ""] + +# if order_id is null, this probably means that they got to this page by pushing back +# so just return them to their empty cart + +if { [empty_string_p $order_id] } { + rp_internal_redirect "shopping-cart" + ad_script_abort +} + +db_foreach get_products_w_attribs " + select i.product_id, + i.color_choice, + i.size_choice, + i.style_choice, + count(*) as r_quantity + from ec_orders o, + ec_items i + where o.order_id=i.order_id + and o.user_session_id=:user_session_id + and o.order_state='in_basket' + group by i.product_id, + i.color_choice, + i.size_choice, + i.style_choice + " { + + set pid_bak $product_id + + set array_value [list $product_id $color_choice $size_choice $style_choice] + regsub -all "{" $array_value {} array_value + regsub -all "}" $array_value {} array_value + + set real_quantity($array_value) $r_quantity +} + +# quantity_to_add might be negative +# also there are two special cases that may come about, for instace, +# when a user pushes "Back" to get here after having altered their cart +# (1) if quantity($product_id) exists but real_quantity($product_id) +# doesn't exist, then ignore it (we're going to miss that +# product_id anyway when looping through product_id_list) +# (2) if real_quantity($product_id) exists but quantity($product_id) +# doesn't exist then quantity_to_add will be 0 + +# set product_id [lindex $product_color_size_style 0] +# set color_choice [lindex $product_color_size_style 1] +# set size_choice [lindex $product_color_size_style 2] +# set style_choice [lindex $product_color_size_style 3] + +set max_quantity_to_add [parameter::get -parameter CartMaxToAdd] + +db_transaction { + + foreach product_color_size_style [array names quantity] { + + set product_lookup $product_color_size_style + + regsub -all "{" $product_lookup {} product_lookup + regsub -all "}" $product_lookup {} product_lookup + + if { [info exists real_quantity($product_lookup)] } { + + set quantity_to_add "[expr $quantity($product_color_size_style) - $real_quantity($product_lookup)]" + + set product_id [lindex $product_color_size_style 0] + set color_choice [lindex $product_color_size_style 1] + set size_choice [lindex $product_color_size_style 2] + set style_choice [lindex $product_color_size_style 3] + + if { $quantity_to_add > 0 } { + set remaining_quantity [min $quantity_to_add $max_quantity_to_add] + while { $remaining_quantity > 0 } { + + db_dml insert_new_quantity_to_add "insert into ec_items + (item_id, product_id, color_choice, size_choice, style_choice, order_id, in_cart_date) + values + (ec_item_id_sequence.nextval, :product_id, :color_choice, :size_choice, :style_choice, :order_id, sysdate)" + set remaining_quantity [expr $remaining_quantity - 1] + } + } elseif { $quantity_to_add < 0 } { + set remaining_quantity [expr abs($quantity_to_add)] + + set rows_to_delete [list] + while { $remaining_quantity > 0 } { + # determine the rows to delete in ec_items (the last instance of this product within this order) + if { [llength $rows_to_delete] > 0 } { + set extra_condition "and item_id not in ([join $rows_to_delete ", "])" + } else { + set extra_condition "" + } + lappend rows_to_delete [db_string get_rows_to_delete " + select max(item_id) + from ec_items + where product_id=:product_id + and color_choice [ec_decode $color_choice "" "is null" "= :color_choice"] + and size_choice [ec_decode $size_choice "" "is null" "= :size_choice"] + and style_choice [ec_decode $style_choice "" "is null" "= :style_choice"] + and order_id=:order_id $extra_condition"] + + set remaining_quantity [expr $remaining_quantity - 1] + } + db_dml delete_from_ec_items "delete from ec_items where item_id in ([join $rows_to_delete ", "])" + } + # otherwise, do nothing + } + } +} + +db_release_unused_handles + +if { [info exists return_url] } { + ad_returnredirect $return_url +} else { + rp_internal_redirect shopping-cart +} + + Index: openacs-4/packages/dotlrn-ecommerce/www/ecommerce/shopping-cart-quantities-change.xql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/dotlrn-ecommerce/www/ecommerce/shopping-cart-quantities-change.xql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/dotlrn-ecommerce/www/ecommerce/shopping-cart-quantities-change.xql 23 Jun 2005 12:28:21 -0000 1.1 @@ -0,0 +1,41 @@ + + + + + + + select order_id from ec_orders where order_state='in_basket' and user_session_id=:user_session_id + + + + + + select i.product_id, i.color_choice, i.size_choice, i.style_choice, count(*) as r_quantity + from ec_orders o, ec_items i + where o.order_id=i.order_id + and o.user_session_id=:user_session_id + and o.order_state='in_basket' + group by i.product_id, i.color_choice, i.size_choice, i.style_choice + + + + + + select max(item_id) + from ec_items + where product_id=:product_id + and color_choice [ec_decode $color_choice "" "is null" "= :color_choice"] + and size_choice [ec_decode $size_choice "" "is null" "= :size_choice"] + and style_choice [ec_decode $style_choice "" "is null" "= :style_choice"] + and order_id=:order_id $extra_condition + + + + + + delete from ec_items + where item_id in ([join $rows_to_delete ", "]) + + + + Index: openacs-4/packages/dotlrn-ecommerce/www/ecommerce/shopping-cart.adp =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/dotlrn-ecommerce/www/ecommerce/shopping-cart.adp,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/dotlrn-ecommerce/www/ecommerce/shopping-cart.adp 23 Jun 2005 12:28:21 -0000 1.1 @@ -0,0 +1,146 @@ + + Your Shopping Cart + @context;noquote@ + @ec_system_owner;noquote@ + + t + shopping-cart + + + for @first_names@ @last_name@ (if you're not @first_names@ @last_name@, + click here). + + +

    + + +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Item DescriptionPaid ByParticipantQuantityPrice/ItemSubtotal Action
    + @in_cart.product_name@ + + @in_cart.patron_name@ + + @in_cart.patron_name@ + + + Group: @group.group_name@ + + + @in_cart.participant_name@ + + + @in_cart.quantity@ + @in_cart.price;noquote@@in_cart.line_subtotal@ + delete +
    Total:@product_counter@ @pretty_total_price@
    + + + + + @shipping_options@@total_reg_shipping_price@standard
    + + + + +  @total_exp_shipping_price@express
    + + + + +   + @shipping_method_pickup@pickup
    + Residents of @tax_entries.state@, please add @tax_entries.pretty_tax@ tax. +
    + + + @shipping_options;noquote@ + +
    + +
    +
    + +
    +
    +
    +
    + +
    Your Shopping Cart is empty.
    +
    + + +
    Index: openacs-4/packages/dotlrn-ecommerce/www/ecommerce/shopping-cart.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/dotlrn-ecommerce/www/ecommerce/shopping-cart.tcl,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/dotlrn-ecommerce/www/ecommerce/shopping-cart.tcl 23 Jun 2005 12:28:21 -0000 1.1 @@ -0,0 +1,347 @@ +ad_page_contract { + @param usca_p User session begun or not + + @author + @creation-date + @author ported by Jerry Asher (jerry@theashergroup.com) + @author revised by Bart Teeuwisse (bart.teeuwisse@thecodemill.biz) + @revision-date April 2002 + +} { + usca_p:optional + product_id:optional + + user_id:integer,notnull,optional +} + +# bottom links: +# 1) continue shopping (always) + +# Case 1) Continue shopping +# Create the link now before the product_id gets overwritten when +# looping through the products in the cart. + +set previous_product_id_p 0 +set previous_product_id 0 + +if {[info exists product_id]} { + set previous_product_id_p 1 + set previous_product_id $product_id +} + +# We don't need them to be logged in, but if they are they might get a +# lower price +set first_names "" +set last_name "" +set email "" + +if { ! [info exists user_id] } { + set user_id [ad_verify_and_get_user_id] +} +if { $user_id != 0 } { + db_1row user_info { + select first_names, last_name, email + from dotlrn_users where user_id = :user_id + } +} + +# user sessions: +# 1. get user_session_id from cookie +# 2. if user has no session (i.e. user_session_id=0), attempt to set it if it hasn't been +# attempted before +# 3. if it has been attempted before, give them message that we can't do shopping carts +# without cookies + +set user_session_id [ec_get_user_session_id] +ec_create_new_session_if_necessary [export_url_vars user_id] + +# This is not being used anywhere +#set n_items_in_cart [db_string get_n_items " +# select count(*) +# from ec_orders o, ec_items i +# where o.order_id=i.order_id +# and o.user_session_id=:user_session_id and o.order_state='in_basket'"] + +# calculate shipping charge options when not using shipping-gateway, +# and then include the value with each option (for an informed choice) + +# mainly from process-order-quantity-shipping.tcl + +# set initial values for itemization loop +db_1row get_ec_admin_settings " + select nvl(base_shipping_cost,0) as base_shipping_cost, + nvl(default_shipping_per_item,0) as default_shipping_per_item, + nvl(weight_shipping_cost,0) as weight_shipping_cost, + nvl(add_exp_base_shipping_cost,0) as add_exp_base_shipping_cost, + nvl(add_exp_amount_per_item,0) as add_exp_amount_per_item, + nvl(add_exp_amount_by_weight,0) as add_exp_amount_by_weight + from ec_admin_settings" + +set last_product_id 0 +set product_counter 0 +set total_price 0 +set currency [parameter::get -parameter Currency] +set max_add_quantity_length [string length [parameter::get -parameter CartMaxToAdd]] +set offer_express_shipping_p [parameter::get -parameter ExpressShippingP] +set offer_pickup_option_p [parameter::get -parameter PickupP] +set total_reg_shipping_price 0 +set total_exp_shipping_price 0 +set no_shipping_options "t" +# Check if a shipping gateway has been selected. +set shipping_gateway [parameter::get -parameter ShippingGateway] +set shipping_gateway_in_use [acs_sc_binding_exists_p ShippingGateway $shipping_gateway] +set shipping_address_id 0 + +if { $shipping_gateway_in_use} { + #this section mainly from select-shipping.tcl + + # Replace the default ecommerce shipping calculations with the + # charges from the shipping gateway, which contains + # both the shipping service level and the associated total + # charges. Requries zipcode and country, so + # user needs to be logged in too. + + if { $user_id != 0 } { + set shipping_address_ids [db_list get_shipping_address_ids " + select address_id + from ec_addresses + where user_id=:user_id + and address_type = 'shipping'" ] + + if { [llength $shipping_address_ids] > 1 } { + # the max valued id is most likely the newest id (no last used date field available) + set shipping_address_id [ec_max_of_list $shipping_address_ids] + } elseif { $shipping_address_ids > 0 } { + set shipping_address_id $shipping_address_ids + } else { + set shipping_address_id 0 + set shipping_options "

    We need your shipping address before we can quote a shipping price. You are able to review your order and any shipping charges before confirming an order.

    " + } + if { $shipping_address_id > 0 } { + # we have a zipcode and country + db_1row select_shipping_area " + select country_code, zip_code + from ec_addresses + where address_id = :shipping_address_id" + + # Calculate the total value of the shipment. + set shipment_value 0 + } + } else { + # user_id == 0 + set shipping_options "

    If you were logged in, we could show you any associated shipping charges

    " + } +} + + +# adding some fields to handle calculating shipping prices +# p.no_shipping_avail_p, p.shipping, p.shipping_additional, p.weight +# basically collect shipping information for any items where ec_products.no_shipping_avail_p = 't' + +db_multirow -extend { line_subtotal patron_name participant_name participant_type } in_cart get_products_in_cart " + select p.product_name, p.one_line_description, p.no_shipping_avail_p, p.shipping, p.shipping_additonal, p.weight, p.product_id, count(*) as quantity, u.offer_code, i.color_choice, i.size_choice, i.style_choice, '' as price + from ec_orders o + join ec_items i on (o.order_id=i.order_id) + join ec_products p on (i.product_id=p.product_id) + left join (select product_id, offer_code + from ec_user_session_offer_codes usoc + where usoc.user_session_id=:user_session_id) u on (p.product_id=u.product_id) + where o.user_session_id=:user_session_id + and o.order_state='in_basket' + group by p.product_name, p.one_line_description, p.no_shipping_avail_p, p.shipping, p.shipping_additional, p.weight, p.product_id, u.offer_code, i.color_choice, i.size_choice, i.style_choice" { + set line_subtotal "$quantity" + if { ! [empty_string_p $patron_id] } { + set patron_name [person::name -person_id $patron_id] + } + if { ! [empty_string_p $participant_id] } { + set participant_type [acs_object_type $participant_id] + if { $participant_type == "user" } { + set participant_name [person::name -person_id $participant_id] + } else { + group::get -group_id $participant_id -array group + } + } + } + +for {set i 1} {$i <= [template::multirow size in_cart]} {incr i} { + + set product_name [template::multirow get in_cart $i product_name] + set one_line_description [template::multirow get in_cart $i one_line_description] + set product_id [template::multirow get in_cart $i product_id] + set no_shipping_avail_p [template::multirow get in_cart $i no_shipping_avail_p] + set shipping [template::multirow get in_cart $i shipping] + set shipping_additional [template::multirow get in_cart $i shipping_additional] + set weight [template::multirow get in_cart $i weight] + set quantity [template::multirow get in_cart $i quantity] + set offer_code [template::multirow get in_cart $i offer_code] + set color_choice [template::multirow get in_cart $i color_choice] + set size_choice [template::multirow get in_cart $i size_choice] + set style_choice [template::multirow get in_cart $i style_choice] + + set patron_id [template::multirow get in_cart $i patron_id] + set participant_id [template::multirow get in_cart $i participant_id] + + set max_quantity_length [max $max_add_quantity_length [string length $quantity]] + # Deletions are done by product_id, color_choice, size_choice, + # style_choice, not by item_id because we want to delete the + # entire quantity of that product. Also print the price for a + # product of the selected options and the aforementioned delete + # option. + + set price_line [ec_price_line $product_id $user_id $offer_code] + set delete_export_vars [export_url_vars product_id color_choice size_choice style_choice user_id patron_id participant_id] + + # Too bad I have to do another call to get the price. That is + # because ec_price_line returns canned html instead of the price. + + set lowest_price_and_price_name [ec_lowest_price_and_price_name_for_an_item $product_id $user_id $offer_code] + set lowest_price [lindex $lowest_price_and_price_name 0] + + + # Calculate line subtotal for end users + set line_subtotal [ec_pretty_price [expr $quantity * $lowest_price] $currency] + template::multirow set in_cart $i line_subtotal $line_subtotal + + if { [string equal $no_shipping_avail_p "f"] && !$shipping_gateway_in_use} { + # at least one thing is shippable, begin calculating ship value(s) + set no_shipping_options "f" + + # Calculate shipping for line item + set first_instance 1 + set shipping_prices_for_first_line_item [ec_shipping_prices_for_one_item_by_rate $product_id $shipping $shipping_additional $default_shipping_per_item $weight $weight_shipping_cost $first_instance $add_exp_amount_per_item $add_exp_amount_by_weight] + set total_reg_shipping_price [expr $total_reg_shipping_price + [lindex $shipping_prices_for_first_line_item 0]] + set total_exp_shipping_price [expr $total_exp_shipping_price + [lindex $shipping_prices_for_first_line_item 1]] + + if { $quantity > 1 } { + set first_instance 0 + set shipping_prices_for_more_line_items [ec_shipping_prices_for_one_item_by_rate $product_id $shipping $shipping_additional $default_shipping_per_item $weight $weight_shipping_cost $first_instance $add_exp_amount_per_item $add_exp_amount_by_weight] + set total_reg_shipping_price [expr $total_reg_shipping_price + ( [lindex $shipping_prices_for_more_line_items 0] * ( $quantity - 1 ) ) ] + set total_exp_shipping_price [expr $total_exp_shipping_price + ( [lindex $shipping_prices_for_more_line_items 1] * ( $quantity - 1 ) ) ] + + } + } elseif { $shipping_gateway_in_use && $shipping_address_id > 0 && [string equal $no_shipping_avail_p "f"] } { + set shipment_value [expr $shipment_value + [lindex [ec_lowest_price_and_price_name_for_an_item $product_id $user_id $offer_code] 0]] + } + + # Add the price of the item to the total price + + set total_price [expr $total_price + ($quantity * $lowest_price)] + incr product_counter $quantity + + template::multirow set in_cart $i delete_export_vars $delete_export_vars + template::multirow set in_cart $i price "[lindex $lowest_price_and_price_name 1]:  [ec_pretty_price [lindex $lowest_price_and_price_name 0] $currency]" + +} + +# Add adjust quantities line if there are products in the cart. +set pretty_total_price [ec_pretty_price $total_price $currency] + +if { $shipping_gateway_in_use && $shipping_address_id > 0} { + + set weight_unit_of_measure [parameter::get -parameter WeightUnits] + + set shipping_options "" + + # Get the list of services and their charges + + set rates_and_services [lsort -index 1 -real \ + [acs_sc_call "ShippingGateway" "RatesAndServicesSelection" \ + [list "" "" "$country_code" "$zip_code" "$shipment_value" "$currency" "" "$weight_unit_of_measure"] "$shipping_gateway"]] + + # Present the available shipping services to the user + + foreach service $rates_and_services { + array set rate_and_service $service + set total_charges $rate_and_service(total_charges) + set service_code $rate_and_service(service_code) + set service_description [acs_sc_call "ShippingGateway" "ServiceDescription" "$service_code" "$shipping_gateway"] + set gateway_shipping_default_price $total_charges + append shipping_options " + " + } + append shipping_options "
    Shipping method:

    + $service_description + + [string map {USD $} $currency] + + $total_charges +
    " +} + +if { !$shipping_gateway_in_use } { + # Rate based shipping calculations + # 3. Determine base shipping costs that are separate from items + + # set base shipping charges + set order_shipping_cost $base_shipping_cost + set shipping_method_standard $order_shipping_cost + + # Add on the extra base cost for express shipping + set shipping_method_express [expr $order_shipping_cost + $add_exp_base_shipping_cost] + + # 4. set total costs for each shipping option + set total_shipping_price_default $total_reg_shipping_price + set total_reg_shipping_price [ec_pretty_price [expr $total_reg_shipping_price + $shipping_method_standard] $currency "t"] + set total_exp_shipping_price [ec_pretty_price [expr $total_exp_shipping_price + $shipping_method_express] $currency "t"] + set shipping_method_pickup [ec_pretty_price 0 $currency "t"] + set shipping_method_no_shipping 0 + + # 5 prepare shipping options to present to user + if { [string equal $no_shipping_options "f" ] } { + + # standard shipping is total_reg_shipping_price + set shipping_options "Shipping is addtional:" + if { $offer_express_shipping_p } { + # express shipping is total_exp_shipping_price + set shipping_options "Shipping is additional, choices are:" + } + if { $offer_pickup_option_p } { + # pickup instead of shipping is shipping_method_pickup + set shipping_options "Shipping is additional, choices are:" + } + } else { + set shipping_options "No shipping options available." + } +} + +# List the states that get charged tax. Although not 100% accurate +# as shipping might be taxed too this is better than nothing. + +db_multirow -extend { pretty_tax } tax_entries tax_states " + select tax_rate, initcap(state_name) as state + from ec_sales_tax_by_state tax, us_states state + where state.abbrev = tax.usps_abbrev" { + set pretty_tax "[format %0.2f [expr $tax_rate * 100]]%" +} + +# bottom links: +# 1) continue shopping (always and already created) +# 2) log in (if they're not logged in) +# 3) retrieve a saved cart (if they are logged in and they have a saved cart) +# 4) save their cart (if their cart is not empty) + +if { $user_id == 0 } { + + # Case 2) the user is not logged in. + set return_url [ns_urlencode "[ec_url]"] + +} else { + # Case 3) Retrieve saved carts + set saved_carts_p [db_string check_for_saved_carts " + select 1 + from dual + where exists ( + select 1 + from ec_orders + where user_id=:user_id + and order_state='in_basket' + and saved_p='t')" -default ""] +} + +set context_bar [template::adp_parse [acs_root_dir]/packages/[ad_conn package_key]/www/contextbar [list context_addition [list "Shopping Cart"]]] +set context [list [list [export_vars -base ../admin/process-purchase-course { user_id }] "Process Purchase"] "Shopping Cart"] +set ec_system_owner [ec_system_owner] +db_release_unused_handles + +ad_return_template Index: openacs-4/packages/dotlrn-ecommerce/www/ecommerce/shopping-cart.xql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/dotlrn-ecommerce/www/ecommerce/shopping-cart.xql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/dotlrn-ecommerce/www/ecommerce/shopping-cart.xql 23 Jun 2005 12:28:21 -0000 1.1 @@ -0,0 +1,40 @@ + + + + + + + select count(*) + from ec_orders o, ec_items i + where o.order_id=i.order_id + and o.user_session_id=:user_session_id and o.order_state='in_basket' + + + + + + + select address_id + from ec_addresses + where user_id=:user_id + and address_type = 'shipping' + + + + + + select country_code, zip_code + from ec_addresses + where address_id = :shipping_address_id + + + + + + select tax_rate, initcap(state_name) as state + from ec_sales_tax_by_state tax, us_states state + where state.abbrev = tax.usps_abbrev + + + + Index: openacs-4/packages/dotlrn-ecommerce/www/ecommerce/thank-you.adp =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/dotlrn-ecommerce/www/ecommerce/thank-you.adp,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/dotlrn-ecommerce/www/ecommerce/thank-you.adp 23 Jun 2005 12:28:21 -0000 1.1 @@ -0,0 +1,28 @@ + + Thank You For Your Order + @context;noquote@ + @ec_system_owner;noquote@ + + + +
    +

    The following has beens sent to the purchaser

    + @order_summary;noquote@ +
    + Index: openacs-4/packages/dotlrn-ecommerce/www/ecommerce/thank-you.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/dotlrn-ecommerce/www/ecommerce/thank-you.tcl,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/dotlrn-ecommerce/www/ecommerce/thank-you.tcl 23 Jun 2005 12:28:21 -0000 1.1 @@ -0,0 +1,64 @@ +ad_page_contract { + @param usca_p User session begun or not + + @author + @creation-date + @author ported by Jerry Asher (jerry@theashergroup.com) + @author revised by Bart Teeuwisse (bart.teeuwisse@thecodemill.biz) + @revision-date April 2002 + +} { + user_id:integer,notnull + usca_p:optional +} + +set admin_p [permission::permission_p -object_id [ad_conn package_id] -privilege "admin"] + +# This is a "thank you for your order" page displays order summary for +# the most recently confirmed order for this user + +# We need them to be logged in + +#set user_id [ad_verify_and_get_user_id] +if {$user_id == 0} { + set return_url "[ad_conn url]" + ad_returnredirect "[ad_conn package_url]register?[export_url_vars return_url]" + ad_script_abort +} + +# wtem@olywa.net, 2001-03-21 +# it isn't clear to me why we would log the session here +# or why you would create a new session at this point + +# User session tracking + +set user_session_id [ec_get_user_session_id] +ec_create_new_session_if_necessary +ec_log_user_as_user_id_for_this_session + +# Their most recently confirmed order (or the empty string if there is +# none) + +set order_id [db_string get_order_id_info " + select order_id + from ec_orders + where user_id=:user_id + and confirmed_date is not null + and order_id = ( + select max(o2.order_id) + from ec_orders o2 + where o2.user_id = $user_id + and o2.confirmed_date is not null)" -default ""] + +if { [empty_string_p $order_id] } { + rp_internal_redirect index + ad_stript_abort +} + +set order_summary [ec_order_summary_for_customer $order_id $user_id] +set context { {Order Confirmation} } +set ec_system_owner [ec_system_owner] + +db_release_unused_handles +ad_return_template + Index: openacs-4/packages/dotlrn-ecommerce/www/ecommerce/thank-you.xql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/dotlrn-ecommerce/www/ecommerce/thank-you.xql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/dotlrn-ecommerce/www/ecommerce/thank-you.xql 23 Jun 2005 12:28:21 -0000 1.1 @@ -0,0 +1,17 @@ + + + + + + + select order_id + from ec_orders + where user_id=:user_id and confirmed_date is not null + and order_id=(select max(o2.order_id) + from ec_orders o2 + where o2.user_id=$user_id + and o2.confirmed_date is not null) + + + +