From c51573febfcaf244bd18df1718ab7874796d761b Mon Sep 17 00:00:00 2001 From: Chuck Scott Date: Fri, 19 Jul 2019 11:23:18 -0400 Subject: [PATCH] Fix problems with availability levels and over-sell * Fixed extra ";" in cart.inc * Fixed missing "$" for parameter in if() call to make sure all data is loaded for a specific ticket in support.php * Added better testing for unavailable tickets in support.php * Added more messages for tickets removed and testing for having at least 1 ticket in cart for checkout in support.php * Fixed problem with inventory calendar updates not working properly after edit dialog closed by clicking "X". --- .project | 11 ++ models/front/actions/Shop/cart.inc | 2 +- models/front/actions/Shop/checkout.inc | 13 ++- models/front/actions/Shop/checkoutSubmit.inc | 16 +-- models/front/actions/Shop/start.inc | 8 +- models/front/classes/support.php | 75 ++++++++---- version.txt | 5 + views/admin/tickets/Ticket/inventory.html | 76 +++++++------ views/front/PointerBoat/Shop/cart.html | 73 ++++++------ views/front/PointerBoat/Shop/checkout.html | 114 +++++++++---------- 10 files changed, 224 insertions(+), 169 deletions(-) create mode 100644 .project create mode 100644 version.txt diff --git a/.project b/.project new file mode 100644 index 0000000..eb581b6 --- /dev/null +++ b/.project @@ -0,0 +1,11 @@ + + + CommonApps-EventManagement_V3 + + + + + + + + diff --git a/models/front/actions/Shop/cart.inc b/models/front/actions/Shop/cart.inc index 2232bc0..b51b347 100644 --- a/models/front/actions/Shop/cart.inc +++ b/models/front/actions/Shop/cart.inc @@ -122,7 +122,7 @@ if ($this->config->option->ticket_selection->show_cart_sticky_items && $cartStic // Check if there's been anything added to the cart and get cart contents $cart = $Support->checkCart(); -; + // If we're already locked into checkout, go there if ($cart['forceCheckoutPhase']) { $this->reason[] = 'You have partially paid for your purchases. We have returned you to checkout to complete your purchase.'; diff --git a/models/front/actions/Shop/checkout.inc b/models/front/actions/Shop/checkout.inc index bd84346..2b74065 100644 --- a/models/front/actions/Shop/checkout.inc +++ b/models/front/actions/Shop/checkout.inc @@ -35,11 +35,13 @@ if (isset($checkoutCart)) { $cart = $Support->checkCart(true); } -if (!$cart['cartHasContents']) { +if (!$cart['cartHasContents'] || !$cart['totals']['tickets'] || $cart['totals']['tickets'] <= 0) { $this->reason[] = 'Your cart is currently empty.'; + $this->reason = array_merge($this->reason, $cart['reason']); include EVENT_MANAGEMENT_APP_BASE.'models/front/actions/Shop/cart.inc'; return; } + $this->page->cartHasContents = true; // Check if there been partial payment and we're in a forced checkout phase - no cart changes or additions @@ -185,24 +187,23 @@ if ($formData['centralPayment']) { // If this an admin user $noPaymentReasons = false; if ($this->page->adminUser) { - + // Get the misc settings require_once EVENT_MANAGEMENT_APP_BASE.'models/admin/classes/misc.php'; $Misc = new EventManagementAdminMisc($this->dbh, $this->config); $miscDetail = $Misc->getEntry(1); - + // If we have reasons for no payment if (trim($miscDetail['no_payment_reasons']) != '') { // Break it into an array and add to page data $noPaymentReasons = explode(PHP_EOL, $miscDetail['no_payment_reasons']); $this->page->noPaymentReasons = $noPaymentReasons; - + } } - unset($formData['payment']); // Otherwise we're OK to continue showing the cart @@ -213,7 +214,7 @@ $this->page->cartHasOneVenueOnly = $cart['cartHasOneVenueOnly']; $this->page->cartRequiresPayment = $cart['cartRequiresPayment']; $this->page->totals = $this->bindArrayToObject($cart['totals']); $this->page->formData = $this->bindArrayToObject($formData); // Blank form data for cleared fields -$this->reason = array_merge($this->reason, $cart['reason']); +$this->page->reason = array_merge($this->reason, $cart['reason']); $this->templateFile = "Shop/checkout.html"; diff --git a/models/front/actions/Shop/checkoutSubmit.inc b/models/front/actions/Shop/checkoutSubmit.inc index dea6f69..9989b37 100644 --- a/models/front/actions/Shop/checkoutSubmit.inc +++ b/models/front/actions/Shop/checkoutSubmit.inc @@ -27,7 +27,14 @@ $checkoutReturnFlag = false; // Need this before we put together the E-Mail summaries $this->page->promoCode = $_SESSION['GLM_EVENT_MGT_FRONT']['PromoCode']; -// Check if there hasn't been a complete checkout yet. +// If there's a problem with the cart, send the user back to the cart page +if ($cart['status'] == false || $cart['blockCheckout']) { + $this->reason = array_merge($this->reason, $cart['reason']); + include EVENT_MANAGEMENT_APP_BASE.'models/front/actions/Shop/cart.inc'; + return; +} + +// Check if there hasn't been a complete checkout yet if (!$cart['checkoutComplete']) { // Check for empty cart @@ -37,13 +44,6 @@ if (!$cart['checkoutComplete']) { return; } - // If there's a problem with the cart, send the user back to the cart page - if ($cart['status'] == false) { - $this->reason = array_merge($this->reason, $cart['reason']); - include EVENT_MANAGEMENT_APP_BASE.'models/front/actions/Shop/checkout.inc'; - return; - } - /* * Check the submitted input for required and valid fields */ diff --git a/models/front/actions/Shop/start.inc b/models/front/actions/Shop/start.inc index 8f15c57..a494e45 100644 --- a/models/front/actions/Shop/start.inc +++ b/models/front/actions/Shop/start.inc @@ -15,8 +15,13 @@ require_once EVENT_MANAGEMENT_APP_BASE.'models/front/classes/support.php'; $Support = new EventManagementFrontSupport($this->dbh, $this->config); -// Check If we're already locked into checkout, if so then go there +// Get and check cart and save any problem reasons $cart = $Support->checkCart(); +if (isset($cart['reason']) && is_array($cart['reason'])) { + $this->reason = array_merge($this->reason, $cart['reason']); +} + +// Check If we're already locked into checkout, if so then go there if ($cart['forceCheckoutPhase']) { $this->reason[] = 'You have partially paid for your purchases. We have returned you to checkout to complete your purchase.'; include EVENT_MANAGEMENT_APP_BASE.'models/front/actions/Shop/checkout.inc'; @@ -118,7 +123,6 @@ $this->addDebug("Shop/start.inc", 'Array: $inventory', print_r($inventory, 1)); // If we didn't get any performances to select from if (!$havePerformances) { -echo "...."; $this->reason[] = 'There are no available '.$this->config->term->event->plur.'.'; } diff --git a/models/front/classes/support.php b/models/front/classes/support.php index 4308f81..7bf2c59 100644 --- a/models/front/classes/support.php +++ b/models/front/classes/support.php @@ -547,6 +547,7 @@ class EventManagementFrontSupport // Get available and held quantities. $sql = " SELECT I.available as available, + I.active as active, T.unlimited_quant as unlimited_quant, ( SELECT SUM(quant) @@ -995,7 +996,7 @@ class EventManagementFrontSupport $performanceDetail = $this->getPerformanceData($ticketDetail['performance_id']); // Make sure we have all needed information - Perhaps something has been deleted - if ($ticketDetail && $memberDetail && $memberDetail['active']['value'] && $sectionDetail && performanceDetail) { + if ($ticketDetail && $memberDetail && $memberDetail['active']['value'] && $sectionDetail && $performanceDetail) { // If Venue/Member hasn't been added yet $membID = $memberDetail['id']; @@ -1230,7 +1231,17 @@ class EventManagementFrontSupport $tickets[$ticID]['packageData'] = $packageData; } + // Check to make sure that the selected number of tickets is currently available + if ($c['quant'] > $tickets[$ticID]['thisSessionSelectable'] || !$invStatus['active'] || $c['quant'] <= 0) { + // Remove this item from the cart + unset($_SESSION[GLM_EVENT_SESSION]['TicketCart'][$invID]); + unset($tickets[$ticID]); + $cartItemRemoved = true; + $totalTickets -= $c['quant']; + $reason[] = "A ticket was removed from your cart because it's no longer available."; + + } // We apparently don't have all needed data for this cart entry // Something has been turned off or deleted @@ -1325,12 +1336,15 @@ class EventManagementFrontSupport */ // Sort Members - uasort ($rCart, function ($a, $b) { - if ($a['sort'] == $b['sort']) { - return 0; - } - return ($a['sort'] < $b['sort']) ? -1 : 1; - }); + if (is_array($rCart)) { + uasort ($rCart, function ($a, $b) { + if ($a['sort'] == $b['sort']) { + return 0; + } + return ($a['sort'] < $b['sort']) ? -1 : 1; + }); + } + // For each Member while (list($k1, $v1) = each($rCart)) { @@ -1338,12 +1352,14 @@ class EventManagementFrontSupport $rCart[$k1]['isCentralPaymentMember'] = false; // Sort Performances - uasort ($rCart[$k1]['performances'], function ($a, $b) { - if ($a['sort'] == $b['sort']) { - return 0; - } - return ($a['sort'] < $b['sort']) ? -1 : 1; - }); + if (is_array($rCart[$k1]['performances'])) { + uasort ($rCart[$k1]['performances'], function ($a, $b) { + if ($a['sort'] == $b['sort']) { + return 0; + } + return ($a['sort'] < $b['sort']) ? -1 : 1; + }); + } // For each Performance while (list($k2, $v2) = each($rCart[$k1]['performances'])) { @@ -1354,23 +1370,27 @@ class EventManagementFrontSupport while (list($k3, $v3) = each($rCart[$k1]['performances'][$k2]['dates'])) { // Sort Sections - uasort ($rCart[$k1]['performances'][$k2]['dates'][$k3]['sections'], function ($a, $b) { - if ($a['sort'] == $b['sort']) { - return 0; - } - return ($a['sort'] < $b['sort']) ? -1 : 1; - }); - - // For each Section - while (list($k4, $v4) = each($rCart[$k1]['performances'][$k2]['dates'][$k3]['sections'])) { - - // Sort Tickets - uasort ($rCart[$k1]['performances'][$k2]['dates'][$k3]['sections'][$k4]['tickets'], function ($a, $b) { + if (is_array($rCart[$k1]['performances'][$k2]['dates'][$k3]['sections'])) { + uasort ($rCart[$k1]['performances'][$k2]['dates'][$k3]['sections'], function ($a, $b) { if ($a['sort'] == $b['sort']) { return 0; } return ($a['sort'] < $b['sort']) ? -1 : 1; }); + } + + // For each Section + while (list($k4, $v4) = each($rCart[$k1]['performances'][$k2]['dates'][$k3]['sections'])) { + + // Sort Tickets + if (is_array($rCart[$k1]['performances'][$k2]['dates'][$k3]['sections'][$k4]['tickets'])) { + uasort ($rCart[$k1]['performances'][$k2]['dates'][$k3]['sections'][$k4]['tickets'], function ($a, $b) { + if ($a['sort'] == $b['sort']) { + return 0; + } + return ($a['sort'] < $b['sort']) ? -1 : 1; + }); + } } // Sections } // Dates @@ -1517,6 +1537,11 @@ class EventManagementFrontSupport $r['cartRequiresPayment'] = false; } + // If total tickets is now 0, then we need to block checkout + if ($totalTickets <= 0) { + $r['blockCheckout'] = true; + } + // Return cart output data and indicate success $r['cartData'] = $cartData; $r['cartItemRemoved'] = $cartItemRemoved; diff --git a/version.txt b/version.txt new file mode 100644 index 0000000..9a1fe55 --- /dev/null +++ b/version.txt @@ -0,0 +1,5 @@ +Gaslight Media - Event Management V3 +On-Line Ticketing System +Version: 3.0.1 +Revision Date: 7/19/19 +Revision Author: Chuck Scott diff --git a/views/admin/tickets/Ticket/inventory.html b/views/admin/tickets/Ticket/inventory.html index 0e2563c..09bfabc 100644 --- a/views/admin/tickets/Ticket/inventory.html +++ b/views/admin/tickets/Ticket/inventory.html @@ -24,7 +24,7 @@
Sat
{foreach:m.weeks,w} - {if:w.weekUsed} + {if:w.weekUsed}
{foreach:w.days,d} {if:d.isDate} @@ -38,7 +38,7 @@
{d.dom}
+
@@ -51,7 +51,7 @@
Quantity:
Unlimited
- {else:} + {else:}
Quantity:
{d.quant}
@@ -75,58 +75,58 @@
{d.dom}
- +
-
- {end:} +
+ {end:} {else:}
 
{end:} - {end:} + {end:}
{end:} {end:} {end:} - + - + {startScript:h} $(function() { - + // Send user notice if they click a non-inventory cell $('.emCalDateCellNotice').click( function() { alert('This is not within the date range for the {term.performance.norm}. To add inventory for this date, edit the {term.performance.norm} and change the start or end date.'); }); - + // Toggle date cell on-off $('.emCalDateCellSelectable').click( function() { - + var thisCell = $(this); - var thisId = $(this).attr('invId'); + var thisId = $(this).attr('invId'); var invStatus; - + // If the cell is currently selected if (thisCell.hasClass("emCalDateCellSelected")) { invStatus = 0; // Change to not selected } else { invStatus = 1; // Otherwise change to selected } - - + + $.ajax({ url: "{adminURL}&Action=Ticket_setActive&TicketInventoryID=" + thisId + "&TicketInventoryStatus=" + invStatus, - success: function() { + success: function() { // Update cell status display if (invStatus == 1) { thisCell.addClass('emCalDateCellSelected'); @@ -134,7 +134,7 @@ thisCell.removeClass('emCalDateCellSelected'); } } , - error: function() { + error: function() { alert( 'There was an error while submitting this information.\n' + 'The information may not have been updated.\n' + @@ -142,21 +142,29 @@ ); } }); - + }); + var editDialog = false; // Pop-up calendar edit forms $('.emCalDateEditIcon').click( function() { + // If there's a remnant of a prior calEdit dialog, destroy it + if (editDialog) { + editDialog.remove(); + editDialog = false; + } + // get needed parameters var dateTime = $(this).attr('calDate'); - var thisId = $(this).attr('invId'); + var thisId = $(this).attr('invId'); var thisTime = $('#ticket_time_' + dateTime).html(); var thisQuant = $('#quant_' + dateTime).html(); var thisAvail = $('#avail_' + dateTime).html(); var thisSold = $('#sold_' + dateTime).html(); + // Place edit form in cell edit container $('#edit_'+dateTime).html(' \
\ @@ -191,8 +199,8 @@
\ '); - // Start dialog pop-up - $('#calEdit').dialog({ + // Start dialog pop-up + editDialog = $('#calEdit').dialog({ autoOpen: true, modal: true, position: { @@ -207,11 +215,11 @@ $('#calEditPleaseWait').html('
Storing, Please Wait...
'); var tf = $(this); - - // Submit form + + // Submit form $('#calEditForm').ajaxForm({ - success: function(data) { - + success: function(data) { + // Copy data from pop-up back to selected calendar date var valEditTime = $("#calEditTime").val(); var valEditQuant = $("#calEditQuant").val(); @@ -221,42 +229,42 @@ $('#quant_' + dateTime).html( valEditQuant ); $('#avail_' + dateTime).html( valEditAvail ); $('#sold_' + dateTime).html( valEditSold ); - + // Destroy dialog pop-up tf.dialog( "close" ); tf.dialog('destroy').remove(); return false; - + } , error: function() { - + // If the data was not able to be submitted alert( 'There was an error while submitting this information.\n' + 'The information may not have been updated.\n' + 'Please try again later or call for support.' ); - + // Destroy dialog pop-up tf.dialog( "close" ); tf.dialog('destroy').remove(); return false; - + } }); - + // Kick ajaxForm submission $('#calEditForm').submit(); } } }); - + return false; }); f_restartOnTabSelect(); - + }); diff --git a/views/front/PointerBoat/Shop/cart.html b/views/front/PointerBoat/Shop/cart.html index f92072f..59bc262 100755 --- a/views/front/PointerBoat/Shop/cart.html +++ b/views/front/PointerBoat/Shop/cart.html @@ -28,13 +28,14 @@ {end:} - {end:} - {if:havePromoCodes} -
-
-
If you have a {term.promo.norm}, please enter it here:
-
-
+ {else:} + {if:havePromoCodes} +
+
+
If you have a {term.promo.norm}, please enter it here:
+
+
+ {end:} {end:} {foreach:cart,c}
@@ -48,7 +49,7 @@ {end:}
- +
{c.name:h} - {p.name}
{if:p.descr}
{p.descr:h}
{end:} @@ -65,7 +66,7 @@ {if:d.dateSpecific} {d.fullDate} {else:} - + {if:c.likelyDate} - Likely Date {c.likelyDate} {end:} @@ -122,7 +123,7 @@ {end:} {if:option.cart_images}{if:i.image}
- {end:}{end:} + {end:}{end:}
{i.descr:h}
@@ -212,7 +213,7 @@ {end:} {end:} {end:} -  
+  
{end:} {if:option.ask_for_likely_date} @@ -231,7 +232,7 @@ {end:}
- {end:} + {end:} {if:!c.needAssignment} {if:option.cart_images}{if:c.image} @@ -249,23 +250,23 @@
- {if:cartHasContents} + {if:cartHasContents}
Grand Total   {totals.price}
- {if:totals.tickets} + {if:totals.tickets} {term.nav.checkout} {else:} Your cart is currently empty. {end:}
{else:} -

Your cart is currently empty.

+

Your cart is currently empty.

{end:}
@@ -281,12 +282,12 @@
{if:p.start_date}

- Dates: {p.start_date.date} + Dates: {p.start_date.date}

{end:} {if:p.short_descr}
{p.short_descr:h}
{end:} - {if:p.short_descr}
{p.short_descr:h}
{end:} + {if:p.short_descr}
{p.short_descr:h}
{end:}
{end:} @@ -308,7 +309,7 @@ // Convert input fields to select lists $('.glmCartQuant').each(function() { - + var id = $(this).attr('id'); var ticket = $(this).attr('data-ticket'); var addon = $(this).attr('data-addon'); @@ -320,14 +321,14 @@ // Build a picklist for this input for (var i = 0 ; i {lte:h} max ; i++) { if (value == i) { - numbSel = numbSel.concat(''); + numbSel = numbSel.concat(''); } else { numbSel = numbSel.concat(''); - } + } } - + $('#quant_' + id).html('' + units); - + }); // Get or set vertical scroll to return to same place when cart reloads @@ -339,7 +340,7 @@ if (vertScroll == 0) { var vertScroll = document.body.scrollTop; } - return vertScroll; + return vertScroll; } // When a cart value changes, submit it as a cart update. @@ -348,10 +349,10 @@ var ticket = $(this).attr('data-ticket'); var addon = $(this).attr('data-addon'); var value = $(this).val(); - + setBlocker(); window.location = "{baseSCRIPT}&Action=Shop_cart&cart=update&ticket_inv=" + ticket + "&addon=" + addon + "&quant=" + value + "&vertScroll=" + vertScroll; - + }); // When there's a change in the promo code input, submit it. @@ -373,14 +374,14 @@ // When a likely departure date changes, submit it so it's in the session $('.glmLikelyDateChange').change(function() { - vertScroll = getVertScroll(); + vertScroll = getVertScroll(); var member = $(this).attr('data-Member'); var likelyDate = $(this).val(); setBlocker(); window.location = "{baseSCRIPT}&Action=Shop_cart&cart=update_likelyDate&member=" + member + "&likely_date=" + likelyDate + "&vertScroll=" + vertScroll; - + }); - + // Code to start datepicker for each date input if($("#likelyDateInput").length > 0) { $("#likelyDateInput").datepicker({ @@ -388,30 +389,30 @@ minDate: -1, maxDate: 365 }); - } + } // Checkout action $('#GLMcheckoutBtn').click(function() { - setBlocker(); + setBlocker(); window.location = "{baseSCRIPT}&Action=Shop_checkout"; }); function setBlocker() { $('#glmReloadBlocker').show(); } - + $('#GLMnavSelectEvent').on('click', function() { // Return to Event Selection setBlocker(); window.location = '{startURL:h}'; }); -/* Not using right now +/* Not using right now // Reprint order button $('#reprintVoucher').on('keypress', function(event) { if(event.which == '13'){ var orderID = $(this).val(); - var voucherWindow = window.open('{appAdminURL}&Action=Order_printVoucher&OrderID=' + orderID, - "voucherPrint", + var voucherWindow = window.open('{appAdminURL}&Action=Order_printVoucher&OrderID=' + orderID, + "voucherPrint", "height=750,width=600,menubar=yes,toolbar=yes,alwaysRaised=yes,menu" ); voucherWindow.focus(); @@ -420,7 +421,7 @@ } }); */ - + if ({vertScroll}) { window.scrollTo(0,{vertScroll}); } diff --git a/views/front/PointerBoat/Shop/checkout.html b/views/front/PointerBoat/Shop/checkout.html index 91673e2..e3cb5dd 100755 --- a/views/front/PointerBoat/Shop/checkout.html +++ b/views/front/PointerBoat/Shop/checkout.html @@ -1,4 +1,4 @@ - @@ -13,7 +13,7 @@ {term.nav.show_selected} {if:!option.ticket_selection.start_at_cart} {term.nav.select_more} - {end:} + {end:} @@ -188,8 +188,8 @@
Receive E-Newsletter?
- {if:formData.contact.email_ok} -
+ {if:formData.contact.email_ok} +
{else:}
{end:} @@ -239,26 +239,26 @@
{end:} - - + +
- + {foreach:cart,c} {if:c.performances}
{term.prop.cap}: {c.name:h}
- +-->
- + {foreach:c.performances,p} -
+
@@ -269,7 +269,7 @@
-
+
{foreach:p.dates,d}
@@ -277,7 +277,7 @@ {if:d.dateSpecific} {d.fullDate} {else:} - + {if:c.likelyDate} - Likely Date {c.likelyDate} {end:} @@ -313,7 +313,7 @@ {if:i.time_specific.value} {else:} - + {end:} {if:i.show_price}{i.price}{end:} @@ -331,7 +331,7 @@ {if:i.image}
{end:} - {end:} + {end:}
{i.descr:h}
@@ -377,7 +377,7 @@
Please read and agree to our policy for this {term.performance.norm}. -
+

{p.policy:h}

@@ -391,7 +391,7 @@
{end:} -
+
{end:}
@@ -410,7 +410,7 @@ {if:!formData.centralPayment}
- +--> {if:c.paymentResult} {if:c.paymentResult.approved}
Card Payment Approved
@@ -497,7 +497,7 @@ {end:} - + {end:} - -{if:cartRequiresPayment} - {if:formData.centralPayment} + +{if:cartRequiresPayment} + {if:formData.centralPayment}
{if:formData.centralPayment.havePaymentMethod} - + {foreach:formData.centralPayment.paymentForm,p} {if:p.cctype} - +
@@ -652,7 +652,7 @@ No payment info required for Admin User. @@ -814,17 +814,17 @@
Reason for no payment information required:
{end:} {end:} - +
- {if:!blockCheckout} + {if:!blockCheckout} {term.nav.purchase} {else:} Unable to checkout - please see above. @@ -849,15 +849,15 @@ var checkoutButtonPressed = false; var duration = 400; - + // Checkout action $('#GLMcheckoutBtn').click(function() { - + // Prevent multiple submissions if (checkoutButtonPressed == true) { return; } - + // Check policy acceptance var needPolicyChecked = false; $(".glmPolicyCheckbox").each(function() { @@ -872,13 +872,13 @@ } checkoutButtonPressed = true; - setBlocker(); + setBlocker(); $('#GLMcheckoutForm').submit(); - + }); // Navigation buttons - $('#GLMnavCart').on('click', function() { // Add to Cart + $('#GLMnavCart').on('click', function() { // Add to Cart window.location = flex_baseSCRIPT + '&Action=Shop_cart'; }); $('#GLMnavSelectEvent').on('click', function() { // Return to Event Selection @@ -914,9 +914,9 @@ $('#AdminNoPaymentInfo').on('click', function() { checkNoPaymentInfo(); }); - + // Show or hide no payment info reasons list - function checkNoPaymentInfo() { + function checkNoPaymentInfo() { if ($('#AdminNoPaymentInfo').is(':checked')) { $('#AdminNoPaymentInfoReason').show(0); } else { @@ -926,7 +926,7 @@ // Check is reasons are shown on startup. checkNoPaymentInfo(); - + // Show submit access blocker function setBlocker() { $('#glmReloadBlocker').show(); -- 2.17.1