Index: openacs-4/packages/dotlrn-ecommerce/dotlrn-ecommerce.info =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/dotlrn-ecommerce/dotlrn-ecommerce.info,v diff -u -r1.52 -r1.53 --- openacs-4/packages/dotlrn-ecommerce/dotlrn-ecommerce.info 2 May 2006 23:53:45 -0000 1.52 +++ openacs-4/packages/dotlrn-ecommerce/dotlrn-ecommerce.info 9 Jun 2006 19:29:22 -0000 1.53 @@ -7,15 +7,15 @@ f t - + Roel Canicula Package to tie the dotLRN, Ecommerce, Assessments and dotLRN Catalog packages together 2005-08-10 Solution Grove Package to tie the dotLRN, Ecommerce, Assessments and dotLRN Catalog packages together. Initially intended for the MOS and MGH projects, the goal is to create a reusable module for similar projects. 0 - + @@ -25,7 +25,7 @@ - + @@ -63,6 +63,7 @@ + Index: openacs-4/packages/dotlrn-ecommerce/catalog/dotlrn-ecommerce.en_US.ISO-8859-1.xml =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/dotlrn-ecommerce/catalog/dotlrn-ecommerce.en_US.ISO-8859-1.xml,v diff -u -r1.67 -r1.68 --- openacs-4/packages/dotlrn-ecommerce/catalog/dotlrn-ecommerce.en_US.ISO-8859-1.xml 12 Apr 2006 19:11:14 -0000 1.67 +++ openacs-4/packages/dotlrn-ecommerce/catalog/dotlrn-ecommerce.en_US.ISO-8859-1.xml 9 Jun 2006 19:29:22 -0000 1.68 @@ -14,6 +14,7 @@ Administrative Setup Approved/Registered Amount to be Paid + Applicant Application Application submitted Approved @@ -35,10 +36,12 @@ available (awaiting approval) Back to + Back to Applications Balance Balance due: Bill to: body + Bulk Payments Cancel Cash change @@ -98,6 +101,7 @@ Instructor Instructors Internal Account + Invalid price Invoice Item Item Description @@ -182,6 +186,7 @@ Please enter a search string Please enter a value greater than 1 Please enter an internal account code + Please enter an internal account number. Please enter the number of attendees Please select a credit card type Please select a section from the list @@ -212,16 +217,18 @@ Sorry, There seems to be a problem with completing this transaction. Test email sent to %user.email%. Please check your inbox. <p>Thank you for applying, the course administrator(s) will contact you soon regarding your registration.</p><p> -If you have any technical issues please contact the <a href="mailto:%administrator_email%">web site administrator</a></p> +If you have any technical issues please contact the <a href="mailto:%administrator_email%">web site administrator</a></p> Thank You For Your Order The applications have been rejected. The course only has $available_slots slots left The following applications need to be handled separately because a section specific approval email needs to be sent: The following applications are already approved: The following applications need to be handled separately because a section specific rejection email needs to be sent: The following has been sent to the purchaser + The following users' payment info could not be entered because they are already regsitered for the course. The offer code was accepted. You save $savings! There is no fee for this course + There was a problem registering this user This section is currently full, but we are taking names for the waiting list. To complete your order, submit this form, and confirm the information on the following page. to send us your order, or click "back" on your browser to make changes. @@ -245,6 +252,7 @@ Instructors: %instructor_names% + We're sorry, but we cannot display this page because SSL isn't available from this site. Please contact <a href=\"mailto:[ad_system_owner]\">[ad_system_owner]</a> for assistance Who is taking the course? Who's participating in this course? (You are number @course_list.waiting_list_number@ on the wait list) @@ -264,15 +272,18 @@ You've already purchased this course. You may purchase for someone else. Make a donation Manage Course List + Mark as Paid Medical Issues Member Request more More Information: My Shopping Cart + New Price No No applications No orders No related users + No SSL available No waiting lists Notes Offer Code: @@ -291,12 +302,15 @@ Payment Information Payment Method Payment method + Pending Applications Pending applications + {Pending Applications} Per User Phone Number Please select one PreReq Approval List Preview Application + Price Charged Price/Item Proceed Process Registration @@ -315,6 +329,7 @@ Registered By Admin Registration Regsitered By Admin + Regular Price Reject waiver of prerequitsites application Index: openacs-4/packages/dotlrn-ecommerce/www/application-bulk-payments.adp =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/dotlrn-ecommerce/www/application-bulk-payments.adp,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/dotlrn-ecommerce/www/application-bulk-payments.adp 9 Jun 2006 19:29:22 -0000 1.1 @@ -0,0 +1,91 @@ + + #dotlrn-ecommerce.Bulk_Payments# + + + + + + + + + + + + + + + + + + + + + + + + + +
#dotlrn-ecommerce.Payment_Information#
+ + #dotlrn-ecommerce.lt_Select_a_payment_meth# + * + + + + + + + + + + +
+ @formgroup.widget;noquote@ + + +
+ + +
+ @formerror.method;noquote@ +
+
+ +
+ + #dotlrn-ecommerce.Internal_Account# + + + + +
+ @formerror.internal_account;noquote@ +
+
+
+ +

+ + + + + + + + + + + + + + + + + +

+

#dotlrn-ecommerce.lt_The_following_users_p#

+

+ + Index: openacs-4/packages/dotlrn-ecommerce/www/application-bulk-payments.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/dotlrn-ecommerce/www/application-bulk-payments.tcl,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/dotlrn-ecommerce/www/application-bulk-payments.tcl 9 Jun 2006 19:29:22 -0000 1.1 @@ -0,0 +1,524 @@ +# packages/dotlrn-ecommerce/www/application-bulk-payments.tcl + +ad_page_contract { + + Bulk payments + + @author Roel Canicula (roel@solutiongrove.com) + @creation-date 2006-03-15 + @arch-tag: 7e28fd03-d828-4adb-b86b-4cf01769a9ee + @cvs-id $Id: application-bulk-payments.tcl,v 1.1 2006/06/09 19:29:22 roelc Exp $ +} { + {rel_id:multiple {}} + return_url + + {method cc} + {internal_account ""} +} -properties { +} -validate { +} -errors { +} + +db_multirow already_registered already_registered [subst { + select person__name(r.user_id) as person_name, t.course_name||': '||s.section_name as section_name + + from dotlrn_member_rels_full r, + dotlrn_ecommerce_section s, + dotlrn_catalogi t, + cr_items i + + where rel_id in ([join $rel_id ,]) + and r.community_id = s.community_id + and s.course_id = t.item_id + and t.course_id = i.live_revision + and r.member_state = 'approved' +}] + +if { [template::multirow size already_registered] > 0 } { + set registered_exists_p 1 + + template::list::create \ + -name already_registered \ + -multirow already_registered \ + -elements { + person_name { + label "[_ dotlrn-ecommerce.Applicant]" + } + section_name { + label "[_ dotlrn-ecommerce.Section]" + } + } +} else { + set registered_exists_p 0 +} + +set user_id [auth::require_login] +set user_session_id [ec_get_user_session_id] + +if {![ad_secure_conn_p]} { + if { ![ec_ssl_available_p] } { + ad_return_error "[_ dotlrn-ecommerce.No_SSL_available]" "[_ dotlrn-ecommerce.lt_Were_sorry_but_we_can]. + " + ad_script_abort + } else { + set secure_url "[ec_secure_location][ns_conn url]" + set vars_to_export [ec_export_entire_form_as_url_vars_maybe] + if { ![empty_string_p $vars_to_export] } { + set secure_url "$secure_url?$vars_to_export" + } + + ad_returnredirect $secure_url + ad_script_abort + } +} + +ec_create_new_session_if_necessary [export_url_vars rel_id:multiple return_url] +ec_log_user_as_user_id_for_this_session + +# Build bulk payment list +ad_form -name applications -export { return_url } -form { + {back:text(button) {label Back} {html {onclick "window.location = 'applications'"}}} + {submit:text(submit) {label Submit}} +} + +# Determine supported payment methods +if { [empty_string_p [set payment_methods [parameter::get -parameter PaymentMethods]]] } { + lappend payment_methods cc +} + +set method_count 0 +set new_payment_methods [list] +set validate [list] +foreach payment_method [split $payment_methods] { + set _payment_method [split $payment_method :] + if { [llength $_payment_method] == 2 } { + lappend new_payment_methods [set payment_method [lindex $_payment_method 0]] + + switch [lindex $_payment_method 1] { + admin { + if { $admin_p } { + set ${payment_method}_p 1 + } else { + continue + } + } + } + } else { + set ${payment_method}_p 1 + lappend new_payment_methods $payment_method + } + + switch $payment_method { + internal_account { + lappend method_options [list "[_ dotlrn-ecommerce.lt_Internal_account_numb]" internal_account] + lappend validate {internal_account + { [exists_and_not_null internal_account] || [template::element::get_value applications method] != "internal_account" } + "[_ dotlrn-ecommerce.lt_Please_enter_an_inter]" + } + } + check { + lappend method_options [list "[_ dotlrn-ecommerce.Check]" check] + } + cc { + lappend method_options [list "[_ dotlrn-ecommerce.Credit_Card]" cc] + lappend validate {creditcard_number + { [template::element::get_value applications method] != "cc" || [exists_and_not_null creditcard_number] } + "[_ dotlrn-ecommerce.lt_Please_enter_a_credit]" + } + lappend validate {creditcard_type + { [template::element::get_value applications method] != "cc" || [exists_and_not_null creditcard_type] } + "[_ dotlrn-ecommerce.lt_Please_select_a_credi]" + } + lappend validate {creditcard_expires + { [template::element::get_value applications method] != "cc" || ([exists_and_not_null creditcard_expire_1] && [exists_and_not_null creditcard_expire_2]) } + "[_ dotlrn-ecommerce.lt_A_full_credit_card_ex]" + } + } + cash { + lappend method_options [list "[_ dotlrn-ecommerce.Cash]" cash] + } + invoice { + lappend method_options [list "[_ dotlrn-ecommerce.Invoice]" invoice] + } + scholarship { + # Purchasing via scholarships should only be available to + # admins by logic, but this can be set in the param + lappend method_options [list "[_ dotlrn-ecommerce.Scholarship]" scholarship] + } + lockbox { + lappend method_options [list "[_ dotlrn-ecommerce.Lock_Box]" lockbox] + } + } + incr method_count +} +set payment_methods $new_payment_methods + +if { $method_count > 1 } { + ad_form -extend -name applications -form { + {-section "[_ dotlrn-ecommerce.Payment_Information]"} + {method:text(radio) {label "[_ dotlrn-ecommerce.Select]"} {options {$method_options}}} + } + + if { [exists_and_equal internal_account_p 1] } { + ad_form -extend -name applications -form { + {internal_account:text,optional {label "[_ dotlrn-ecommerce.Internal_Account]"}} + } + } +} elseif { $method_count == 1 } { + ad_form -extend -name applications -export { {method "[lindex [split $payment_methods] 0]"} } -form {} +} else { + ad_form -extend -name applications -export { {method cc} } -form {} +} + +if { [info exists cc_p] } { + if { $method_count == 1 } { + # The creditcard_expires field is a hack, improve it + ad_form -extend -name applications -form { + {creditcard_number:text {label "[_ dotlrn-ecommerce.Credit_card_number]"}} + {creditcard_type:text(select) {label "[_ dotlrn-ecommerce.Type]"} {options {{"[_ dotlrn-ecommerce.Please_select_one]" ""} {VISA v} {MasterCard m} {"American Express" a}}}} + {creditcard_expires:text(inform) {label "[_ dotlrn-ecommerce.Expires] *"} {value $ec_expires_widget}} + } + } else { + ad_form -extend -name applications -form { + {-section "[_ dotlrn-ecommerce.lt_Credit_card_informati]"} + {creditcard_number:text,optional {label "[_ dotlrn-ecommerce.Credit_card_number]"}} + {creditcard_type:text(select),optional {label Type} {options {{"[_ dotlrn-ecommerce.Please_select_one]" ""} {VISA v} {MasterCard m} {"American Express" a}}}} + {creditcard_expires:text(inform),optional {label "[_ dotlrn-ecommerce.Expires]"} {value $ec_expires_widget}} + } + } +} + +template::list::create \ + -name applications \ + -multirow applications \ + -elements { + person_name { + label "[_ dotlrn-ecommerce.Applicant]" + } + section_name { + label "[_ dotlrn-ecommerce.Section]" + } + regular_price { + label "[_ dotlrn-ecommerce.Regular_Price]" + html { align center } + display_template { + + Free + + + @applications.pretty_price;noquote@ + + } + } + new_price { + label "[_ dotlrn-ecommerce.New_Price]" + display_template { + + } + } + } \ + -filters { + rel_id {} + return_url {} + } + +db_multirow -extend { regular_price free_p pretty_price } applications applications [subst { + select r.rel_id, r.user_id, person__name(r.user_id) as person_name, t.course_name||': '||s.section_name as section_name, s.product_id + + from dotlrn_member_rels_full r, dotlrn_ecommerce_section s + left join ec_products p + on (s.product_id = p.product_id), + dotlrn_catalogi t, + cr_items i + + where rel_id in ([join $rel_id ,]) + and r.community_id = s.community_id + and s.course_id = t.item_id + and t.course_id = i.live_revision + and r.member_state != 'approved' +}] { + set regular_price [format "%.2f" [lindex [ec_lowest_price_and_price_name_for_an_item $product_id $user_id] 0]] + set free_p [expr {$regular_price == 0}] + set pretty_price [ec_pretty_price $regular_price] +} + +ad_form -extend -name applications -validate $validate -form {} -on_submit { + + # Actually register and record payments + set _form [rp_getform] + array set form [util_ns_set_to_list -set $_form] + + template::multirow create applications_registered rel_id price valid_p order_id person_name section_name + + foreach name [array names form] { + if { [regexp {^bulk_payment_(\d+)$} $name match one_rel_id] } { + # Check if price is valid + set new_price $form($match) + if { [string is double $new_price] && $new_price >= 0 } { + # Register the user + if { [db_0or1row get_rel_info { + select r.user_id as participant_id, r.community_id, s.product_id, o.creation_user as patron_id, person__name(r.user_id) as person_name, t.course_name||': '||s.section_name as section_name + from dotlrn_member_rels_full r, dotlrn_ecommerce_section s, acs_objects o, dotlrn_catalogi t, cr_items i + + where r.community_id = s.community_id + and r.rel_id = o.object_id + and s.course_id = t.item_id + and t.course_id = i.live_revision + and r.rel_id = :one_rel_id + }] } { + # Check if this is a free course + if { $new_price > 0 } { + + # Use user_id to the patron to be used in the + # ecommerce SQL calls since the patron is paying + set user_id $patron_id + + # Check for an existing order in this session + if { ! [db_0or1row existing_order { + select order_id + from ec_orders + where user_session_id = :user_session_id + and order_state = 'in_basket' + }] } { + ns_log notice "application-bulk-payments: no existing order in session $user_session_id" + + # Create an order entry + 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', current_timestamp + where not exists (select 1 from ec_orders where user_session_id=:user_session_id and order_state='in_basket') + } + } else { + ns_log notice "application-bulk-payments: existing order_id $order_id in session $user_session_id" + } + + # Check for an existing item in this order, + # there can be more than one + set existing_item_p 0 + db_foreach existin_items { + select product_id as existing_product_id, item_id as existing_item_id + from ec_items + where order_id = :order_id + } { + if { $product_id == $existing_product_id } { + ns_log notice "application-bulk-payments: existing product $product_id with item_id $existing_item_id in order $order_id" + + set existing_item_p 1 + } else { + ns_log notice "application-bulk-payments: unrecognized product $product_id in order $order_id" + + # Delete the item that doesn't match, + # this should not happen and we need to + # delete it or the order will be inaccurate + db_dml delete_unmatched_item { + delete from ec_items + where item_id = :existing_item_id + } + } + } + + if { ! $existing_item_p } { + ns_log notice "application-bulk-payments: product $product_id doesn't exist in order $order_id, creating" + + set item_id [db_nextval ec_item_id_sequence] + + set color_choice [set size_choice [set style_choice ""]] + db_dml insert_new_item_in_order { + insert into ec_items + (item_id, product_id, color_choice, size_choice, style_choice, order_id, in_cart_date, price_charged) + select :item_id, :product_id, :color_choice, + :size_choice, :style_choice, :order_id, current_timestamp, :new_price + from dual + } + + 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) + } + + + if { $method == "cc" } { + 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 = 'cc', + 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, 'cc') + } + } + } 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 "

  • [_ dotlrn-ecommerce.lt_Please_enter_an_inter_1]
  • " + 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" || + $method == "cash" || + $method == "invoice" || + $method == "scholarship" || + $method == "lockbox" + } { + 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 = :method, + 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, :method) + } + } + } + } + } + + set use_member_price_p 0 + if {[parameter::get -parameter MemberPriceP -default 0]} { + set ec_category_id [parameter::get -parameter "MembershipECCategoryId" -default ""] + set group_id [parameter::get -parameter MemberGroupId -default 0] + if {$group_id} { + set use_member_price_p [group::member_p -group_id $group_id -user_id $user_id] + } + + if {$use_member_price_p} { + set offer_code [db_string get_offer_code { + select offer_code + from ec_sale_prices + where product_id = :product_id + and offer_code = 'dotlrn-ecommerce' + } -default ""] + if {![empty_string_p $offer_code]} { + # DEDS: at this point we need to insert or update an offer + set offer_code_exists_p [db_string get_offer_code_p { + select count(*) + from ec_user_session_offer_codes + where user_session_id=:user_session_id + and product_id=:product_id + }] + if {$offer_code_exists_p} { + db_dml update_ec_us_offers { + update ec_user_session_offer_codes + set offer_code = :offer_code + where user_session_id = :user_session_id + and product_id = :product_id + } + } else { + db_dml inert_uc_offer_code { + insert into ec_user_session_offer_codes + (user_session_id, product_id, offer_code) + values + (:user_session_id, :product_id, :offer_code) + } + } + } + } + # DEDS + # at this point if user is purchasing + # a member product then we probably need to adjust + # any other products in basket + if {[parameter::get -parameter MemberPriceP -default 0]} { + if {![empty_string_p $ec_category_id]} { + if {[db_string membership_product_p { + select count(*) + from ec_category_product_map + where category_id = :ec_category_id + and product_id = :product_id + }]} { + dotlrn_ecommerce::ec::toggle_offer_codes -order_id $order_id -insert + } + } + } + } + + # Register the user + + ec_update_state_to_confirmed $order_id + ec_update_state_to_authorized $order_id + callback -- ecommerce::after-checkout -user_id $user_id -patron_id $user_id -order_id $order_id + } else { + dotlrn_ecommerce::registration::new -user_id $participant_id \ + -patron_id $user_id \ + -community_id $community_id + + set order_id "" + } + + template::multirow append applications_registered $one_rel_id [ec_pretty_price $form($match)] 1 $order_id $person_name $section_name + } else { + template::multirow append applications_registered $one_rel_id "[_ dotlrn-ecommerce.lt_There_was_a_problem_r]" 0 "" $person_name $section_name + } + + } else { + template::multirow append applications_registered $one_rel_id "[_ dotlrn-ecommerce.Invalid_price]: $form($match)" 0 "" $person_name $section_name + } + } + } + + template::list::create \ + -name applications_registered \ + -multirow applications_registered \ + -actions [list "[_ dotlrn-ecommerce.Back_to_Applications]" $return_url "[_ dotlrn-ecommerce.Back_to_Applications]"] \ + -elements { + order_id { + label "[_ dotlrn-ecommerce.Order_ID]" + html { align center } + } + person_name { + label "[_ dotlrn-ecommerce.Applicant]" + } + section_name { + label "[_ dotlrn-ecommerce.Section]" + } + price { + label "[_ dotlrn-ecommerce.Price_Charged]" + html { align center } + } + } +} \ No newline at end of file Index: openacs-4/packages/dotlrn-ecommerce/www/applications.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/dotlrn-ecommerce/www/applications.tcl,v diff -u -r1.45 -r1.46 --- openacs-4/packages/dotlrn-ecommerce/www/applications.tcl 21 Apr 2006 02:14:34 -0000 1.45 +++ openacs-4/packages/dotlrn-ecommerce/www/applications.tcl 9 Jun 2006 19:29:22 -0000 1.46 @@ -51,8 +51,12 @@ if { $enable_applications_p } { lappend filters \ - {"[_ dotlrn-ecommerce.Applications]" "application sent"} \ - {"[_ dotlrn-ecommerce.lt_Approved_Applications]" "application approved"} + {"[_ dotlrn-ecommerce.Applications]" "application sent"} + + if { ![exists_and_not_null section_id] || [dotlrn_ecommerce::section::price $section_id] > 0.01 } { + lappend filters \ + {"[_ dotlrn-ecommerce.lt_Approved_Applications]" "application approved"} + } } lappend filters {"[_ dotlrn-ecommerce.Already_Registered]" "approved"} @@ -65,7 +69,9 @@ lappend bulk_actions "[_ dotlrn-ecommerce.Email_applicants]" "email-applicants" "[_ dotlrn-ecommerce.Email_applicants]" } -lappend bulk_actions "Mark as Paid" application-bulk-payments "Mark as Paid" +if { ![exists_and_not_null section_id] || [dotlrn_ecommerce::section::price $section_id] > 0.01 } { + lappend bulk_actions "[_ dotlrn-ecommerce.Mark_as_Paid]" application-bulk-payments "[_ dotlrn-ecommerce.Mark_as_Paid]" +} set elements {section_name { label "[_ dotlrn-ecommerce.Section]"