HEX
Server: Microsoft-IIS/10.0
System: Windows NT ITPWINWEBSVR22 10.0 build 20348 (Windows Server 2022) AMD64
User: www.conferencesearch.co.uk (0)
PHP: 8.3.30
Disabled: NONE
Upload Files
File: D:/web/hyperflight/apps/~tab/index.asp
<%Option Explicit%>
<!--#include virtual="/dbfunctions.asp"-->
<!--#include virtual="/apputils.asp"-->
<%DisableCache%>
<html lang="en">
<head>
<meta http-equiv="content-type" content="text/html; charset=windows-1252"> 
<meta charset="windows-1252" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Orders</title>

<link rel="stylesheet" href="bootstrap/css/bootstrap.min.css">
<!--<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>-->
<script src="jquery/jquery-3.5.1.min.js"></script>
<script src="bootstrap/js/bootstrap.min.js" ></script>

<!--<script type='text/javascript' src='https://s3.amazonaws.com/dynatable-docs-assets/js/jquery-1.9.1.min.js'></script>-->
<link rel="stylesheet" media="all" href="dynatable/jquery.dynatable.css" />
<script type='text/javascript' src='dynatable/jquery.dynatable.js'></script>

<link href="flags.css" rel=stylesheet type="text/css">

<link href="fontawesome/css/all.min.css" rel="stylesheet">

<style>
 /* (SS,9/1/24) added following */
.table-extra td, .table-extra th{
   text-align: center !important;   
}
</style>

</head>

<body>

<%
' (SS,08/08/19) modified to add cookie feature for access outside of these IP addresses, cookie gets created when page accessed in one of these IP addresses
' (SS,03/02/22) modified SQL to use refunds table
' (SS,25/06/22) added Clover (CLO as a payment method)
' (SS,27/06/22) added current time at the top of the page, also added Time to GetOrdersMainSQL
' (SS,28/02/23) v5 - added Function ShowPhoneNoFromShoppingAdmin to shop phone passed from ITP Shopping Admin to help Neil phone the customer quickly from his iPhone
' (SS,09/01/24) v6 - properly sorted the new year (January) date issue, centered columns in top two summary tables, also added new IPs addresses
' (SS,10/01/24) v7 - change to try out last 30 days including day instead of excluding today
' (SS,11/12/24) cookie value change from "t!L^:SZ+6IoK" to "t!L^:SZ+6IoK#42m"
' (SS,24/07/25) v8 modified authentication to password entry (was cookie by IP address)
' (SS,05/12/25) v9 modified Function Authenticated to allows allow because IP restriction has been added in IIS (see web.config of apps folder)

' (SS,14/9/20)
Dim LCmd, LOrderNo
LCmd = Request("cmd")
LOrderNo = Request("OrderNo")

' (SS,24/7/25) moved authentication code to separate routine
If Authenticated Then
    
  ' (SS,14/9/20) needs to be before fetched latests values
  If LCmd = "save" Then
    SaveInternalNotes LOrderNo
    ' redirect to home page
    Response.Redirect "."  
  End If
  
  ' (SS,14/9/20) added If LCmd
  If LCmd = "prevorders" Then
    ShowPreviousOrdersForCustomer(LOrderNo)
  Else
    Response.Write "<small>" & NOW() & "</small>" & BR ' (SS,27/6/22) current time requested by Neil
    If Not ShowPhoneNoFromShoppingAdmin Then ' (SS,27/2/23)
      ShowWIPTable
      ShowComparisonTable  
      ShowOrdersTable
    End If
  End If
  
   ' (SS,14/9/20) added If LCmd
  If LCmd = "edit" Then  
    ShowInternalNotesModal LOrderNo
  End If
End If


  ' following hides the combo (requested by Neil)
%>
<script>
  $("#label-status").hide();
  $("#search-stat").hide();
</script>

</body>
</html>

<%

' (SS,24/7/25) old authentication using cookie
Function Authenticated_old
  Dim LResult
  Dim LIP, LCookie
  Const TAB_ACCESS_COOKIE_VALUE = "t!L^:SZ+6IoK#42m"

  LIP = Request.ServerVariables("REMOTE_ADDR")
  LCookie = GetCookie("TabAccess")

  ' (SS,26/1/22) added 5.101.172.199 to test on ITP server and show detailed error info
  ' (SS,9/1/24) added LIP = "212.159.111.105" new HF IP, also OTW VM IP 94.175.201.242 (removed Or LIP = "80.229.231.82" Or LIP = "86.10.87.170")
  ' (SS,21/4/25) added IP 92.40.196.12 and 82.146.154.74 for Neil for access while he was away on holiday
  If LIP = "192.168.1.2" Or LIP = "88.98.246.98"  Or LIP = "5.101.172.199" Or LIP = "212.159.111.105" Or LIP = "94.175.201.242" Or LIP = "82.146.154.74" Or LCookie = TAB_ACCESS_COOKIE_VALUE Then
    If LCookie = "" Then SetCookie "TabAccess", TAB_ACCESS_COOKIE_VALUE
    
    LResult = True
  Else 
    Response.Write "No access for IP: " & LIP & BR & NL
    LResult = False
  End If
  
  Authenticated = LResult
End Function

' (SS,24/7/25) new authentication requiring password
Function Authenticated
  
  ' (SS,5/12/25) added following because we're now using IP address restriction, commented out below
  Session("Authenticated") = True

  'If Session("Authenticated") <> True Then
  '  Session("Authenticated") = CheckPassword
  'End If
  
  Authenticated = Session("Authenticated")
End Function

' (SS,24/7/25)
Function CheckPassword

  Dim LPassword, LResult
  
  LPassword = CleanRequestForm("password")
  
  If LPassword = "Snipe77" Then
    LResult = True 
  Else
    If LPassword <> "" Then
      Response.Write "<div class=""alert alert-danger mb-0"" role=""alert"">"
      Response.Write "Incorrect password"
      Response.Write "</div>" & BR & NL
    End If
%>
<form method="post">
  <div class="form-row ml-3 mt-3">
  
    <div class="col-auto">
      <label class="sr-only" for="inlineFormInput">Password</label>
      <input type="password" name="password" class="form-control mb-2" id="inlineFormInput" placeholder="Password">
    </div>

    <div class="col-auto">
      <button type="submit" class="btn btn-primary mb-2">Submit</button>
    </div>
  </div>
</form>
<%
  End If

  CheckPassword = LResult
End Function

' (SS,27/2/23) show phone if less than 5 minutes old
Function ShowPhoneNoFromShoppingAdmin
  Dim LPhone, LResult
  'LPhone = GetSQLValueAsString("SELECT FieldValue FROM settings WHERE GroupName = 'Scratch' AND FieldName = 'SendToPhone' AND TIMESTAMPDIFF(MINUTE, LastUpdated, NOW()) < 5")
  'LPhone = GetSQLValueAsString("SELECT FieldValue FROM settings WHERE GroupName = 'Scratch' AND FieldName = 'SendToPhone' AND TIMESTAMPDIFF(MINUTE, LastUpdated, NOW()) < 60")

  LPhone = NB(GetSetting("Scratch", "SendToPhone"))

  If LPhone <> "" Then
   '  Response.Write "###" & LPhone & "###" & BR
%>  <!--<h3>Phone No from ITP Shopping Admin</h3>-->
    <div class="text-center my-5">
      <i class="fa-solid fa-phone fa-3x"></i><br>
      <a class="h2" href="tel:<%=StripSpaces(LPhone)%>"><%=LPhone%></a><br>
    </div>
    
    <div class="text-center my-5">
      <i class="fa-brands fa-skype fa-4x"></i><br>
      <a class="h2" href="skype:<%=StripSpaces(LPhone)%>?call"><%=LPhone%></a><br>
    </div>
    
    <div class="text-center my-5">
      <i class="fa-brands fa-whatsapp fa-4x"></i><br>
      <a class="h2" href="https://wa.me/<%=CleanNum(LPhone)%>"><%=LPhone%></a><br>
    </div>
    
    <div class="text-center my-5">
      <a class="btn btn-primary btn-lg text-center" href=".">Refresh</a>
    </div>
<%
    LResult = True
  Else
    LResult = False
  End If
  
  ' clear the number
  SetSetting "Scratch", "SendToPhone", ""
  
  ShowPhoneNoFromShoppingAdmin = LResult
End Function

' (SS,30/4/19)
Sub ShowWIPTable
  Dim LSQL
  ' , MIN(Date) AS Oldest, MAX(Date) AS Newest 
  LSQL = "SELECT a.Stat, a.Status, COUNT(*) AS Orders, FORMAT(SUM(Total), 0) AS Total FROM (" & GetOrdersSQL & ") a INNER JOIN status s ON s.Status = a.Status GROUP BY Status ORDER BY s.SortOrder"
  
  OpenQuery(LSQL)
  ShowTableHeader "S" ' should be after OpenQuery 
  Do While Not EndOfQuery
    ShowTableRecord "S"
    NextQueryRecord
  Loop
  ShowTableFooter "S"
  
End Sub

' (SS,27/8/19)
Dim FMaximum
Sub ClearMaximum
  FMaximum = 0
End Sub

' (SS,27/8/19)
Sub SetMaximum(AValue)
  If AValue > FMaximum Then FMaximum = AValue
End Sub

' (SS,27/8/19)
Function GetMaximum
  GetMaximum = FMaximum
End Function

' comparison of orders over last 30 day period
' (SS,3/2/22) old version, see new version below that uses new refunds table
Sub ShowComparisonTable_old
  Dim LSQL
  ' (SS,2/1/20) failed in the new year due to not return any records because of "between" being 12-03 and 01-01, fixed by adding OR and reverse "between"
  ' (SS,16/9/20) replaced " ROUND(SUM(GrandTotal - RefundAmount), 0) AS Total, " &_ with new version which removes the VAT
  LSQL = "SELECT YEAR(DateTimeOrdered) AS Year, COUNT(*) AS Orders, " &_
    " ROUND(SUM(GrandTotal - VATIncluded - (RefundAmount - IF(RefundAmount = GrandTotal, VATIncluded, RefundAmount - ROUND(RefundAmount / (1 + ROUND((VATIncluded / (GrandTotal - VATIncluded)), 2)), 2)))), 2) AS Total, " &_    
    "'100%' AS Performance FROM orders" &_
    " WHERE Status <> 'CANCELLED' AND Status <> 'ORDER PLACED' AND" &_
    " (DATE_FORMAT(DateTimeOrdered, '%m-%d') BETWEEN DATE_FORMAT(DATE_SUB(CURDATE(), INTERVAL 30 DAY), '%m-%d') AND DATE_FORMAT(DATE_SUB(CURDATE(), INTERVAL 1 DAY), '%m-%d')" &_
    " OR DATE_FORMAT(DateTimeOrdered, '%m-%d') BETWEEN DATE_FORMAT(DATE_SUB(CURDATE(), INTERVAL 1 DAY), '%m-%d') AND DATE_FORMAT(DATE_SUB(CURDATE(), INTERVAL 30 DAY), '%m-%d'))" &_ 
    " AND" &_
    " YEAR(DateTimeOrdered) >= YEAR(CURDATE()) - 5" &_
    " GROUP BY Year" &_
    " ORDER BY Year DESC"
    
  OpenQuery(LSQL)
  
  ' (SS,27/8/19) determine maximum value
  ClearMaximum
  Do While Not EndOfQuery
    SetMaximum GetFieldValue("Total")
    NextQueryRecord
  Loop  
  FirstQueryRecord
  
  Response.Write("<small>Last 30 days excluding today</small>")
  ShowTableHeader "O" ' should be after OpenQuery
  Do While Not EndOfQuery
    ShowTableRecord "O"
    NextQueryRecord
  Loop
  ShowTableFooter "O"
End Sub

' comparison of orders over last 30 day period
' (SS,3/2/22) new version that uses new refunds table
Sub ShowComparisonTable_old2
  Dim LSQL
  ' (SS,2/1/20) failed in the new year due to not return any records because of "between" being 12-03 and 01-01, fixed by adding OR and reverse "between"
  ' (SS,16/9/20) replaced " ROUND(SUM(GrandTotal - RefundAmount), 0) AS Total, " &_ with new version which removes the VAT
  LSQL = "SELECT YEAR(DateTimeOrdered) AS Year, COUNT(*) AS Orders, " &_
    " ROUND(SUM(GrandTotal - VATIncluded - (RefundAmount - IF(RefundAmount = GrandTotal, VATIncluded, RefundAmount - ROUND(RefundAmount / (1 + ROUND((VATIncluded / (GrandTotal - VATIncluded)), 2)), 2)))), 2) AS Total, " &_    
    "'100%' AS Performance FROM orders" &_
    " WHERE Status <> 'CANCELLED' AND Status <> 'ORDER PLACED' AND" &_
    " (DATE_FORMAT(DateTimeOrdered, '%m-%d') BETWEEN DATE_FORMAT(DATE_SUB(CURDATE(), INTERVAL 30 DAY), '%m-%d') AND DATE_FORMAT(DATE_SUB(CURDATE(), INTERVAL 1 DAY), '%m-%d')" &_
    " OR DATE_FORMAT(DateTimeOrdered, '%m-%d') BETWEEN DATE_FORMAT(DATE_SUB(CURDATE(), INTERVAL 1 DAY), '%m-%d') AND DATE_FORMAT(DATE_SUB(CURDATE(), INTERVAL 30 DAY), '%m-%d'))" &_ 
    " AND" &_
    " YEAR(DateTimeOrdered) >= YEAR(CURDATE()) - 5" &_
    " GROUP BY Year" &_
    " ORDER BY Year DESC"
    
  ' (SS,9/1/24) added variable for CURDATE() to help with debugging, it was incorrect in January, replaced all CURDATE() references in SQL below with @curdate
  'ExecuteQuery "SET @curdate = CURDATE()"
  'ExecuteQuery "SET @curdate = 20240109"
  ExecuteQuery "SET @curdate = 20231231"
    
  LSQL = "SELECT o.Year, o.Orders, ROUND(o.InvoiceNet - COALESCE(r.RefundNet, 0), 2) AS Total, '100%' AS Performance " &_
    "FROM " &_
    "(" &_     
    "SELECT YEAR(DateTimeOrdered) AS Year, COUNT(*) AS Orders," &_
    " ROUND(SUM(GrandTotal - VATIncluded), 2) AS InvoiceNet," &_
    " '100%' AS Performance FROM orders" &_
    " WHERE Status <> 'CANCELLED' AND Status <> 'ORDER PLACED' AND" &_
    " (DATE_FORMAT(DateTimeOrdered, '%m-%d') BETWEEN DATE_FORMAT(DATE_SUB(@curdate, INTERVAL 30 DAY), '%m-%d') AND DATE_FORMAT(DATE_SUB(@curdate, INTERVAL 1 DAY), '%m-%d')" &_
    " OR DATE_FORMAT(DateTimeOrdered, '%m-%d') BETWEEN DATE_FORMAT(DATE_SUB(@curdate, INTERVAL 1 DAY), '%m-%d') AND DATE_FORMAT(DATE_SUB(@curdate, INTERVAL 30 DAY), '%m-%d'))" &_
    " AND" &_
    " YEAR(DateTimeOrdered) >= YEAR(CURDATE()) - 5" &_
    " GROUP BY Year" &_     
    ") o" &_
    " LEFT JOIN" &_
    "(" &_
    "SELECT YEAR(RefundDate) AS Year, COUNT(*) AS Refunds," &_
    " ROUND(SUM(RefundNet), 2) AS RefundNet" &_
    " FROM refunds" &_
    " INNER JOIN orders ON orders.OrderNo = refunds.OrderNo" &_     
    " WHERE Status <> 'CANCELLED' AND Status <> 'ORDER PLACED' AND" &_
    " (DATE_FORMAT(DateTimeOrdered, '%m-%d') BETWEEN DATE_FORMAT(DATE_SUB(@curdate, INTERVAL 30 DAY), '%m-%d') AND DATE_FORMAT(DATE_SUB(@curdate, INTERVAL 1 DAY), '%m-%d')" &_
    " OR DATE_FORMAT(DateTimeOrdered, '%m-%d') BETWEEN DATE_FORMAT(DATE_SUB(@curdate, INTERVAL 1 DAY), '%m-%d') AND DATE_FORMAT(DATE_SUB(@curdate, INTERVAL 30 DAY), '%m-%d'))" &_
    " AND" &_
    " YEAR(DateTimeOrdered) >= YEAR(CURDATE()) - 5" &_
    " GROUP BY Year" &_
    ") r" &_
    " ON r.Year = o.Year" &_
    " ORDER BY Year DESC"   


  Response.Write "###" & BR & LSQL & BR & "###" & BR
    
  OpenQuery(LSQL)
  
  ' (SS,27/8/19) determine maximum value
  ClearMaximum
  Do While Not EndOfQuery
    SetMaximum GetFieldValue("Total")
    NextQueryRecord
  Loop  
  FirstQueryRecord
  
  Response.Write("<small>Last 30 days excluding today</small>")
  ShowTableHeader "O" ' should be after OpenQuery
  Do While Not EndOfQuery
    ShowTableRecord "O"
    NextQueryRecord
  Loop
  ShowTableFooter "O"
End Sub

' comparison of orders over last 30 day period
' (SS,3/2/22) new version that uses new refunds table
' (SS,9/1/24) new version that properly fixes the date range issue that occurs in new year (in January), does this by create a "tilde_tab_date_range" date range table
Sub ShowComparisonTable
  Dim LSQL

  CreateXDaysYearDateRangeTable 30, 5
      
  LSQL = "SELECT o.Year, o.Orders, ROUND(o.InvoiceNet - COALESCE(r.RefundNet, 0), 2) AS Total, '100%' AS Performance " &_
    "FROM " &_
    "(" &_     
    "SELECT dr.Year, COUNT(*) AS Orders," &_
    " ROUND(SUM(GrandTotal - VATIncluded), 2) AS InvoiceNet," &_
    " '100%' AS Performance FROM orders" &_
    " INNER JOIN tilde_tab_date_range dr ON DATE(orders.DateTimeOrdered) BETWEEN dr.StartDate AND dr.EndDate" &_
    " WHERE Status <> 'CANCELLED' AND Status <> 'ORDER PLACED'" &_
    " GROUP BY Year" &_     
    ") o" &_
    " LEFT JOIN" &_
    "(" &_
    "SELECT dr.Year, COUNT(*) AS Refunds," &_
    " ROUND(SUM(RefundNet), 2) AS RefundNet" &_
    " FROM refunds" &_
    " INNER JOIN orders ON orders.OrderNo = refunds.OrderNo" &_     
    " INNER JOIN tilde_tab_date_range dr ON refunds.RefundDate BETWEEN dr.StartDate AND dr.EndDate" &_
    " WHERE Status <> 'CANCELLED' AND Status <> 'ORDER PLACED'" &_           
    " GROUP BY Year" &_
    ") r" &_
    " ON r.Year = o.Year" &_
    " ORDER BY Year DESC"   

   ' Response.Write "###" & BR & LSQL & BR & "###" & BR
    
  OpenQuery(LSQL)
  
  ' (SS,27/8/19) determine maximum value
  ClearMaximum
  Do While Not EndOfQuery
    SetMaximum GetFieldValue("Total")
    NextQueryRecord
  Loop  
  FirstQueryRecord
  
  'Response.Write("<small>Last 30 days excluding today</small>")
  ' (SS,10/1/24) replaced above with following
  Response.Write("<small>Last 30 days including today</small>")
  ShowTableHeader "O" ' should be after OpenQuery
  Do While Not EndOfQuery
    ShowTableRecord "O"
    NextQueryRecord
  Loop
  ShowTableFooter "O"
End Sub

' (SS,9/1/24) aded this new function to create date range condition for same 30 or x days in each of the last 5 or x years, to overcome issue where it was going wring in January
' no longer used, replaced by CreateXDaysYearDateRangeTable
Function GetXDaysYearDateRangeSQLWhere(ADateFieldName, AXDays, AYears)
  Dim i, LResult, LSQL, LStartDate, LEndDate
  LResult = ""
  
  'ExecuteQuery "SET @curdate = 20231231"
  ExecuteQuery "SET @curdate = CURDATE()"
  ExecuteQuery "SET @startdate = DATE_SUB(@curdate, INTERVAL 30 DAY)"
  ExecuteQuery "SET @enddate = DATE_SUB(@curdate, INTERVAL 1 DAY)"
  
  For i = 0 To AYears
    If GetSQL2Values("SELECT DATE_SUB(@startdate, INTERVAL " & i & " YEAR) AS StartDate, DATE_SUB(@enddate, INTERVAL " & i & " YEAR) AS EndDate", LStartDate, LEndDate) Then
      Response.Write "###" & LStartDate & ", " & LEndDate & "###" & BR
      If LResult <> "" Then LResult = LResult + " OR "
      LResult = LResult + "DATE(" + ADateFieldName + ") BETWEEN '" & LStartDate & "' AND '" & LEndDate & "'"
    End If
  Next
  'Response.Write "###" & BR & LResult & BR & "###" & BR
  GetXDaysYearDateRangeSQLWhere = LResult
End Function

' (SS,9/1/24) aded this new function to create date range condition for same 30 or x days in each of the last 5 or x years, to overcome issue where it was going wring in January
Sub CreateXDaysYearDateRangeTable(AXDays, AYears)
  Dim i, LResult, LSQL, LStartDate, LEndDate
  LResult = ""
  
  'ExecuteQuery "SET @curdate = 20231231"
  ExecuteQuery "SET @curdate = CURDATE()"
  'ExecuteQuery "SET @startdate = DATE_SUB(@curdate, INTERVAL 30 DAY)"
  'ExecuteQuery "SET @enddate = DATE_SUB(@curdate, INTERVAL 1 DAY)"
  ' (SS,10/1/24) replaced above with following to try out 30 days including today
  ExecuteQuery "SET @startdate = DATE_SUB(@curdate, INTERVAL 29 DAY)"
  ExecuteQuery "SET @enddate = @curdate"  
  
  ' don't create again if end date matches to ensure it's done just once a table
  If GetSQLRecordExists("SELECT * FROM tilde_tab_date_range WHERE EndDate = @enddate") Then 
    Exit Sub
  End If
  
  'ExecuteQuery "DROP TABLE IF EXISTS tilde_tab_date_range"
  'ExecuteQuery "CREATE TABLE tilde_tab_date_range (Year INT(11) NOT NULL, StartDate DATE NOT NULL, EndDate DATE NOT NULL) ENGINE = MyISAM"
  ' now truncates instead of creating, because it's now a permanent table
  ExecuteQuery "TRUNCATE TABLE tilde_tab_date_range"
  
  LSQL = ""
  For i = 0 To AYears
    ExecuteQuery "INSERT INTO tilde_tab_date_range (StartDate, EndDate, Year) VALUES (DATE_SUB(@startdate, INTERVAL " & i & " YEAR), DATE_SUB(@enddate, INTERVAL " & i & " YEAR), YEAR(DATE_SUB(@enddate, INTERVAL " & i & " YEAR)))"
  Next
End Sub

Sub ShowOrdersTable
  OpenQuery(GetOrdersSQL)
  ShowTableHeader "D" ' should be after OpenQuery 
  Do While Not EndOfQuery
    ShowTableRecord "D"
    NextQueryRecord
  Loop
  ShowTableFooter "D"
End Sub

' (SS,30/4/19)
' (SS,3/2/22) see new version below
Function GetOrdersSQL_old
  Dim LSQL1, LSQL2

  LSQL1 = GetOrdersMainSQL ' (SS,14/9/20) SQL here moved to Function GetOrdersMainSQL
  
  LSQL2 = "(" + LSQL1 + " WHERE orders.Status <> 'CANCELLED' AND orders.Status  <> 'COMPLETED')" ' no limit on status other than CANCELLED and COMPLETED
  
  'LSQL2 = LSQL2 + " UNION ALL (" + LSQL1 + " WHERE orders.Status  = 'CANCELLED' OR orders.Status  = 'COMPLETED' ORDER BY OrderNo DESC LIMIT 1000)" ' limit for CANCELLED or COMPLETED
  ' (SS,159/9/20) replaced LIMIT 1000 with 3 month date limit i.e. 90 days (with DATE(DateTimeOrdered) BETWEEN CURDATE() - INTERVAL 90 DAY AND CURDATE())
  LSQL2 = LSQL2 + " UNION ALL (" + LSQL1 + " WHERE (DATE(DateTimeOrdered) BETWEEN CURDATE() - INTERVAL 90 DAY AND CURDATE()) AND (orders.Status  = 'CANCELLED' OR orders.Status  = 'COMPLETED') ORDER BY OrderNo DESC)"
  
  
  LSQL2 = LSQL2 + " ORDER BY OrderNo DESC"
  GetOrdersSQL = LSQL2
End Function

' (SS,30/4/19)
' (SS,3/2/22) new version that works with separate refunds table
Function GetOrdersSQL
  Dim LSQL1, LSQL2, LSQL3

  ' (SS,14/9/20) SQL here moved to Function GetOrdersMainSQL
  ' (SS,3/2/22) added AWhere clause to GetOrdersMainSQL
  ' WHERE clause note: no limit on status other than CANCELLED and COMPLETED
  LSQL1 = GetOrdersMainSQL("WHERE orders.Status <> 'CANCELLED' AND orders.Status <> 'COMPLETED'")
  
  'LSQL2 = LSQL2 + " UNION ALL (" + LSQL1 + " WHERE orders.Status  = 'CANCELLED' OR orders.Status  = 'COMPLETED' ORDER BY OrderNo DESC LIMIT 1000)" ' limit for CANCELLED or COMPLETED
  ' (SS,159/9/20) replaced LIMIT 1000 with 3 month date limit i.e. 90 days (with DATE(DateTimeOrdered) BETWEEN CURDATE() - INTERVAL 90 DAY AND CURDATE())  
  LSQL2 = GetOrdersMainSQL("WHERE (DATE(DateTimeOrdered) BETWEEN CURDATE() - INTERVAL 90 DAY AND CURDATE()) AND (orders.Status  = 'CANCELLED' OR orders.Status  = 'COMPLETED')")
  
  LSQL3 = "(" + LSQL1 + ")" + " UNION ALL (" + LSQL2 + ") ORDER BY OrderNo DESC"
    
  GetOrdersSQL = LSQL3
End Function

' (SS,14/9/20) move here, used in GetOrdersSQL and new GetPreviousOrdersSQL
' (SS,3/2/22) old version, refunds now moved to separate refunds table
Function GetOrdersMainSQL_old
  Dim LSQL
  ' (SS,25/5/19) removed FORMAT from GrandTotal to fix issue where values with commas were ignored in WIP totals
  ' (SS,16/9/20) replaced  "GrandTotal AS Total, " &_ with new version that removes VAT and refund
  LSQL = "SELECT OrderNo, DATE_FORMAT(DateTimeOrdered, '%d/%m') AS Date, " &_
    "orders.Status, status.Stat, " &_
    "PaymentMethod AS Pay, " &_
    "countries.CodeA2 AS Country, " &_
    "ROUND(GrandTotal - VATIncluded - (RefundAmount - IF(RefundAmount = GrandTotal, VATIncluded, RefundAmount - ROUND(RefundAmount / (1 + ROUND((VATIncluded / (GrandTotal - VATIncluded)), 2)), 2))), 2) AS Total, " &_
    "TRIM(CONCAT(FirstName, ' ', Surname)) AS Name, " &_
    "Telephone, EmailAddress AS Email, " &_
    "Message AS CustomerMessage, Notes AS InternalNotes, SessionID, IPAddress " &_
    "FROM orders " &_
    "LEFT JOIN countries ON countries.Country = IF(orders.DeliveryAddressSameAsInvoice, orders.Country, orders.DeliveryCountry) " &_
    "INNER JOIN status ON status.Status = orders.Status "
  GetOrdersMainSQL = LSQL
End Function

' (SS,14/9/20) move here, used in GetOrdersSQL and new GetPreviousOrdersSQL
' (SS,3/2/22) new version which gets refunds from a new refunds table
' had to add AWhere clause parameter to pass here because it's no longer possible to add later
Function GetOrdersMainSQL(AWhere)
  Dim LSQL
  
  ' (SS,25/5/19) removed FORMAT from GrandTotal to fix issue where values with commas were ignored in WIP totals
  ' (SS,16/9/20) replaced  "GrandTotal AS Total, " &_ with new version that removes VAT and refund
  ' (SS,27/6/22) added time
  LSQL = "SELECT o.OrderNo, Date, Status, Stat, Pay, Country, InvoiceNet - COALESCE(RefundNet, 0) AS Total, Name, Time, Telephone, Email, CustomerMessage, InternalNotes, SessionID, IPAddress " &_
    "FROM " &_
    "(" &_
    "SELECT OrderNo, DATE_FORMAT(DateTimeOrdered, '%d/%m') AS Date, " &_
    "DATE_FORMAT(DateTimeOrdered, '%H:%i') AS Time, " &_
    "orders.Status, status.Stat, " &_
    "PaymentMethod AS Pay, " &_
    "countries.CodeA2 AS Country, " &_
    "ROUND(GrandTotal - VATIncluded, 2) AS InvoiceNet, " &_
    "TRIM(CONCAT(FirstName, ' ', Surname)) AS Name, " &_
    "Telephone, EmailAddress AS Email, " &_
    "Message AS CustomerMessage, Notes AS InternalNotes, SessionID, IPAddress " &_
    "FROM orders " &_
    "LEFT JOIN countries ON countries.Country = IF(orders.DeliveryAddressSameAsInvoice, orders.Country, orders.DeliveryCountry) " &_
    "INNER JOIN status ON status.Status = orders.Status " &_  
    AWhere &_
    ") o " &_   
    "LEFT JOIN " &_
    "(" &_
    "SELECT refunds.OrderNo, ROUND(SUM(RefundNet), 2) AS RefundNet " &_
    "FROM refunds " &_
    "INNER JOIN orders ON orders.OrderNo = refunds.OrderNo " &_
    AWhere & " " &_ 
    "GROUP BY refunds.OrderNo " &_         
    ") r " &_
    "ON r.OrderNo = o.OrderNo " &_
    "ORDER BY o.OrderNo DESC"

  GetOrdersMainSQL = LSQL
End Function


' (SS,14/9/20)
Function GetPreviousOrdersSQL(AOrderNo)

  Dim LResult, LCustomerID, LEmail
  
  ' get email address and customer ID for given order
  LResult = GetSQL2Values("SELECT CustomerID, EmailAddress FROM orders WHERE OrderNo = '" & CleanSQLStr(AOrderNo) & "'", LCustomerID, LEmail)
 
  Dim LSQL
  ' (SS,3/2/22) added WHERE clause as parameter, moved from separate command below
  LSQL = GetOrdersMainSQL("WHERE EmailAddress = '" & CleanSQLStr(LEmail) & "' OR CustomerID = '" & LCustomerID & "'")
  ' (SS,3/2/22) removed removed, added as parameter above
  ' LSQL = LSQL & " WHERE EmailAddress = '" & CleanSQLStr(LEmail) & "' OR CustomerID = '" & LCustomerID & "' ORDER BY OrderNo DESC"
  
  GetPreviousOrdersSQL = LSQL
  
End Function


' (SS,14/9/20) show previous orders
Sub ShowPreviousOrdersForCustomer(AOrderNo)
  OpenQuery(GetPreviousOrdersSQL(AOrderNo))
  ShowTableHeader "P" ' should be after OpenQuery 
  Do While Not EndOfQuery
    ShowTableRecord "P"
    NextQueryRecord
  Loop
  ShowTableFooter "P"
End Sub


Sub ShowTableHeader(AType)
  ' for each field
  Dim LoRS
  Set LoRS = oRS ' *** oRS is a global defined in dbfunctions.asp perhaps create a function to return this, or a create a different solutions 
  
  %>
<div class="dynatable-demo">  

<%If AType = "D" Then%>
<div id="search-example-status-filter" style="float: left; margin: 5px">
  <span id="label-status">Status:</span>
  <select id="search-stat" name="stat">
    <option></option>
    <option>CMP</option>
    <option>REC</option>
    <option>POA</option>
    <option>AWT</option>
    <option>PLA</option>
    <option>CAN</option>    
  </select>
  
  Search: <input type="search" id="dynatable-query-search" data-dynatable-query="search" style="width:150px">
  <button type="button" class="btn btn-primary btn-sm px-3" data-dynatable-query="search" >Go</button>
  <button id="clear-search-button" type="button" class="btn btn-primary btn-sm">Clear</button>
  <a class="btn btn-primary btn-sm" href=".">Refresh</a>
</div>
<%Else%>
<script>
function ClickStatus(AStat) {
  $('#search-stat').val(AStat).change();
}
</script>
<%End If%>


<%

' (SS,9/1/24) for centering top two tables
Dim LExtraTableClass
If AType = "S" or AType = "O" Then
  LExtraTableClass = " table-extra"
Else
  LExtraTableClass = ""
End If

' (SS,14/9/20) heading and link to home for previous orders page
If AType = "P" Then%>

<div>
<a class="btn btn-primary" href=".">Home</a><big><strong>&nbsp;Previous orders</strong></big>
</div>

<%End If %>


<table id="search-example-<%=AType%>" class="table table-responsive table-sm table-bordered table-striped<%=LExtraTableClass%>"> 
  <thead>
    <tr>
  <%
  Dim i, LFieldName, LFieldCount
  
  LFieldCount = oRS.Fields.Count
    
  For i = 0 To LFieldCount - 1
    LFieldName = LoRS.Fields.Item(i).Name
    If LFieldName = "OrderNo" Then
      LFieldName = "Order"
    'ElseIf LFieldName = "Status" Then
    '  LFieldName = "Stat"
    ElseIf LFieldName = "Country" Then
      LFieldName = "Ctry"
    ElseIf LFieldName = "CustomerMessage" Then
      LFieldName = "Customer&nbsp;Message" & "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"
    ElseIf LFieldName = "InternalNotes" Then
      LFieldName = "Internal&nbsp;Notes" & "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"      
    End If
    ' (SS,14/9/20) added Or AType = "P"
    ' (SS,15/9/20) added Or LFieldName = "DateTimeOrdered" to not show this field which was recently added
    If Not (((AType = "D" Or AType = "P") And LFieldName = "Status") Or LFieldName = "SessionID" Or LFieldName = "IPAddress") Then
      Response.Write "<th>" & LFieldName & "</th>"
    End If    
  Next
%>  
    </tr>
  </thead>
  <tbody>
<%
End Sub

' (SS,14/9/20) new AType of "P" for previous orders
Sub ShowTableRecord(AType)
  ' for each field
  Dim LoRS
  Set LoRS = oRS ' *** oRS is a global defined in dbfunctions.asp perhaps create a function to return this, or a create a different solutions
  
  %>
    <tr>
  <%
  Dim i, LFieldName, LFieldValue, LFieldCount
  
  LFieldCount = oRS.Fields.Count
  
  For i = 0 To LFieldCount - 1
    LFieldName = LoRS.Fields.Item(i).Name
    LFieldValue = LoRS.Fields.Item(i)
    ' if OrderNo then added the link to show order in new tab
    If LFieldName = "OrderNo" Then
      LFieldValue = "<a target=""_blank"" href=""/order-details.asp?orderno=" & LFieldValue & "&sid=" & GetFieldValue("SessionID") & "&ip=" & GetFieldValue("IPAddress") & """>" & LFieldValue & "</a>"
      
    ElseIf LFieldName = "Date" Then
      ' (SS,14/9/20) make date field clickable to show orders for this customer
      If AType = "D" Then
        LFieldValue = "<a href=""?cmd=prevorders&orderno=" & GetFieldValue("OrderNo")  & """>" & LFieldValue & "</a>"
      End If

    ElseIf LFieldName = "Status" Then
      LFieldValue = "<a href=""#"" onclick=""ClickStatus('" &  GetFieldValue("Stat") & "')"">" & LFieldValue & "</a>"
    '  If LFieldValue = "COMPLETED" Then
    '    LFieldValue = "CMP"
    '  ElseIf LFieldValue = "PAYMENT RECEIVED" Then
    '    LFieldValue = "REC"
    '  ElseIf LFieldValue = "PAYMENT ON ACCOUNT" Then
    '    LFieldValue = "POA"
    '  ElseIf LFieldValue = "AWAITING PAYMENT" Then
    '    LFieldValue = "AWT"
    '  ElseIf LFieldValue = "ORDER PLACED" Then
    '    LFieldValue = "PLA"
    '  ElseIf LFieldValue = "CANCELLED" Then
    '    LFieldValue = "CAN"
    '  Else
    '    LFieldValue = "???"
    '  End If
    ElseIf LFieldName = "Pay" Then
      If LFieldValue = "CHEQUE" Then
        LFieldValue = "CHQ"
      ElseIf LFieldValue = "CASH" Then
        LFieldValue = "CSH"
      ElseIf LFieldValue = "OTHER" Then
        LFieldValue = "OTH"
      ElseIf LFieldValue = "PAYPAL" Then
        LFieldValue = "PP"
      ElseIf LFieldValue = "PAYPAL MANUAL" Then
        LFieldValue = "PPM"
      ElseIf LFieldValue = "PAYZONE" Then
        LFieldValue = "PZ" 
      ' (SS,22/1/21) added NetPay
      ElseIf LFieldValue = "NETPAY" Then
        LFieldValue = "NP"
      ' (SS,25/6/22) added Clover, started with CV, then CLV, then CLO, then CL
      ElseIf LFieldValue = "CLOVER" Then
        LFieldValue = "CL"
      ElseIf LFieldValue = "BANK TRANSFER" Then
        LFieldValue = "B"
      ElseIf LFieldValue = "BANK TRANSFER - GBP" Then
        LFieldValue = "BGB"
      ElseIf LFieldValue = "BANK TRANSFER - EUR" Then
        LFieldValue = "BEU"
      ElseIf LFieldValue = "BANK TRANSFER - USD" Then
        LFieldValue = "BUS"
      ElseIf LFieldValue = "" Then
        LFieldValue = ""
      Else
        LFieldValue = "???"
      End If      
    ElseIf LFieldName = "Country" Then
      LFieldValue = "<img src=""blank.gif"" class=""flag flag-" & LCase(LFieldValue) & """ />" & "&nbsp;" & LFieldValue
    ElseIf LFieldName = "Email" Then
      LFieldValue = "<a href=""mailto:" & LFieldValue & """>" & LFieldValue & "</a>"
    ElseIf LFieldName = "Total" Then
      LFieldValue = "&pound;" & FormatNumber(LFieldValue, 0) ' (SS,25/5/19) added FormatNumber here rather than in SQL because summary WIP SQL was ignoring records with commas in Total
    ElseIf LFieldName = "Name" Then
      'LFieldValue = ReplaceStr(LFieldValue, " ", "&nbsp;")
      ' (SS,14/9/20) replaced above with following to internal notes edit
      LFieldValue = "<a href=""?cmd=edit&orderno=" & GetFieldValue("OrderNo") & """>" & ReplaceStr(LFieldValue, " ", "&nbsp;") & "</a>"
   
    ' (SS,14/9/20)   
    ElseIf LFieldName = "InternalNotes" Or LFieldName = "CustomerMessage" Then
      LFieldValue = HTMLEncode(LFieldValue)
    
    ' (SS,27/8/19)
    ElseIf LFieldName = "Performance" Then
      LFieldValue = CStr(ROUND(GetFieldValue("Total") / GetMaximum * 100, 0)) & "%"
    End If
    
    ' (SS,14/9/20) added Or AType = "P"
    If Not (((AType = "D" Or AType = "P") And LFieldName = "Status") Or LFieldName = "SessionID" Or LFieldName = "IPAddress") Then
      Response.Write "<td>" & LFieldValue & "</td>"
    End If
  Next
%>  
    </tr>
<%
End Sub

Sub ShowTableFooter(AType)
%>
  </tbody>
</table>
</div>

<script>
(function() {
  var dynatable = $('#search-example-<%=AType%>').dynatable({
    features: {
      paginate: <%=IIF(AType = "D", "true", "false")%>,
      recordCount: <%=IIF(AType = "D", "true", "false")%>,
      sorting: false,
      perPageSelect: false,
      search: false
    },
    dataset: {
      perPageDefault: 100
    }
  }).data('dynatable');

  $('#search-stat').change( function() {
    var value = $(this).val();
    if (value === "") {
      dynatable.queries.remove("stat");
    } else {
      dynatable.queries.add("stat",value);
    }
    dynatable.process();
  });
  
  $('#dynatable-query-search').change(function() {
		var value = $(this).val();
		if (value === "") {
			dynatable.queries.remove("search");
		} else {
      ClickStatus(""); // (SS,1/5/19) clear the status filter to ensure search across all instead of selected status
			dynatable.queries.add("search", value);
		}
		dynatable.process();
	});
  
  
  $('#clear-search-button').click( function(e) {
    dynatable.sorts.clear();
    dynatable.queries.remove("search");
    $('#dynatable-query-search').val("");
    dynatable.process();
    e.preventDefault()
  });
  
})();


// (SS,2/5/19) following from https://techoverflow.net/2018/03/30/copying-strings-to-the-clipboard-using-pure-javascript/
function copyStringToClipboard(str) {
   // Create new element
   var el = document.createElement('textarea');
   // Set value (string to be copied)
   el.value = str;
   // Set non-editable to avoid focus and move outside of view
   el.setAttribute('readonly', '');
   el.style = {position: 'absolute', left: '-9999px'};
   document.body.appendChild(el);
   // Select text inside element
   el.select();
   // Copy text to clipboard
   document.execCommand('copy');
   // Remove temporary element
   document.body.removeChild(el);
}
</script>
<%
End Sub

' (SS,14/9/20)
Sub ShowInternalNotesModal(AOrderNo)

  Dim LName, LInternalNotes
  
  If Not GetSQL2Values("SELECT TRIM(CONCAT(FirstName, ' ', Surname)) AS Name, Notes FROM orders WHERE OrderNo = '" & CleanSQLStr(AOrderNo) & "'", LName, LInternalNotes) Then
    Exit Sub
  End If  

%>

<script>

    
  $(window).on('load', function(){
    $('#myModal').modal('show');
  });
   

$(function () {
    $('body').on('click', '.odom-submit', function (e) {
        /*alert($('#orderno').val()); */
        $(this.form).submit();
        $('#myModal').modal('hide');
    });
});

    
</script>    

<div class="modal fade show" id="myModal" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel">
  <div class="modal-dialog" role="document">
    <div class="modal-content">
      <div class="modal-header">
        <h5 class="modal-title" id="exampleModalLabel">Internal Notes</h5>
        
        <button type="button" class="close" data-dismiss="modal" aria-label="Close">
          <span aria-hidden="true">&times;</span>
        </button>
      </div>
      <form id="myForm" method="post" action="index.asp">      
      <div class="modal-body">
          Order No <strong><%=AOrderNo%></strong> for <strong><%=LName%></strong>
          <div class="form-group">
            <input type="hidden" value="save" name="cmd">
            <input type="hidden" value="<%=AOrderNo%>" id="orderno" name="orderno">
            <label for="message-text" class="col-form-label">Internal Notes:</label>
            <textarea rows="4" class="form-control" name="internal-notes"><%=LInternalNotes%></textarea>
          </div>
        
      </div>
      <div class="modal-footer">
        <button type="button" class="btn btn-secondary" data-dismiss="modal">Cancel</button>
        <button type="button" class="btn btn-primary odom-submit">Save</button>
      </div>
      </form>
    </div>
  </div>
</div>
<%

End Sub

' (SS,14/9/20)
Sub SaveInternalNotes(AOrderNo)
  Dim LInternalNotes
  
  LInternalNotes = Request("internal-notes")
  
  'Response.Write BR & "###" & "OrderNo:" & AOrderNo & BR
  'Response.Write BR & "###" & "Notes:" & HTMLEncode(LInternalNotes) & BR
  
  Dim LSQL
  LSQL = "UPDATE orders SET Notes = """ & CleanSQLStr(LInternalNotes) & """ WHERE OrderNo = """ & CleanSQLStr(AOrderNo) & """"
  ExecuteQuery LSQL
End Sub


%>