File: D:/web/hyperflight/apps/~tab/sales - Copy (3).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>Sales by Country (12 months)</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;
}
table td:nth-child(1) {text-align: right;}
table td:nth-child(3) {text-align: right;}
table td:nth-child(4) {text-align: right;}
table td:nth-child(5) {text-align: right;}
table td:nth-child(6) {text-align: right;}
table td:nth-child(7) {text-align: right;}
table td:nth-child(8) {text-align: right;}
table td:nth-child(9) {text-align: right;}
table td:nth-child(10) {text-align: right;}
table td:nth-child(11) {text-align: right;}
table td:nth-child(12) {text-align: right;}
table td:nth-child(13) {text-align: right;}
table td:nth-child(14) {text-align: right;}
th {color: #fff; }
</style>
</head>
<body>
<%
' (SS,11/09/25) sale.asp to show sales fron past year per country, (code taken from index.asp (~tab) and modified for this purpose
' (SS,24/7/25) moved authentication code to separate routine
If Authenticated Then
' ShowOrdersTable
ShowSalesTable
End If
' following hides the combo (requested by Neil)
%>
</body>
</html>
<%
' (SS,24/7/25) new authentication requiring password
Function Authenticated
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
Sub ShowOrdersTable
OpenQuery(GetOrdersSQL)
ShowTableHeader "D" ' should be after OpenQuery
Do While Not EndOfQuery
ShowTableRecord "D"
NextQueryRecord
Loop
ShowTableFooter "D"
End Sub
' (SS,11/9/25)
Sub ShowSalesTable
Dim LRecNo
OpenQuery(GetSalesSQL)
LRecNo = 0
ShowTableHeader "D" ' should be after OpenQuery
Do While Not EndOfQuery
LRecNo = LRecNo + 1
ShowTableRecord "D", LRecNo
NextQueryRecord
Loop
ShowTableFooter "D"
End Sub
' (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) 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
' gets data for the past year
Function GetSalesSQL
Dim LSQL
LSQL = "DROP TEMPORARY TABLE IF EXISTS tmp_answer1;" & NL
ExecuteQuery LSQL
LSQL = "CREATE TEMPORARY TABLE tmp_answer1 SELECT countries.Country, COUNT(*) AS Orders, SUM(ROUND(Delivery / (1 + ROUND(((VATIncluded + VATDeducted) / (GrandTotal - VATIncluded)), 2)), 2)) AS Delivery, ROUND(SUM(GrandTotal - VATIncluded), 2) AS InvoiceNet," &_
" ROUND(SUM(VATIncluded), 2) AS InvoiceVAT, ROUND(SUM(GrandTotal), 2) AS InvoiceTotal FROM orders LEFT JOIN countries ON countries.Country = IF(COALESCE(orders.DeliveryCountry, '') = '', orders.Country, orders.DeliveryCountry) INNER JOIN common.Calendar c ON" &_
" c.CalendarDate = DATE(DateTimePaid) WHERE PaymentReceived = TRUE AND DateTimePaid >= DATE_SUB(CURDATE(), INTERVAL 1 YEAR) AND GrandTotal <> 0 GROUP BY Country;" & NL
ExecuteQuery LSQL
LSQL = "DROP TEMPORARY TABLE IF EXISTS tmp_answer2;" & NL
ExecuteQuery LSQL
LSQL = "CREATE TEMPORARY TABLE tmp_answer2 SELECT countries.Country, SUM(RefundNet) AS RefundNet, SUM(RefundVAT) AS RefundVAT, SUM(RefundAmount) AS RefundTotal , SUM(IF(Status = 'CANCELLED' AND RefundAmount = GrandTotal, 1, 0)) AS OrdersCancelled FROM refunds" &_
" INNER JOIN orders ON orders.OrderNo = refunds.OrderNo LEFT JOIN countries ON countries.Country = IF(COALESCE(orders.DeliveryCountry, '') = '', orders.Country, orders.DeliveryCountry)" &_
" INNER JOIN common.Calendar c ON c.CalendarDate = DATE(RefundDate) WHERE PaymentReceived = TRUE AND RefundDate >= DATE_SUB(CURDATE(), INTERVAL 1 YEAR) AND RefundDate < 20250912 AND RefundAmount <> 0 GROUP BY Country;" & NL
ExecuteQuery LSQL
LSQL = "DROP TEMPORARY TABLE IF EXISTS tmp_answer3;" & NL
ExecuteQuery LSQL
LSQL = "CREATE TEMPORARY TABLE tmp_answer3 SELECT t1.Country, ROUND(InvoiceNet - Delivery, 2) AS Goods, Delivery, InvoiceNet, InvoiceVAT, InvoiceTotal, RefundNet, RefundVAT, RefundTotal, InvoiceNet - COALESCE(RefundNet, 0) AS NetSales, " &_
" Orders - COALESCE(OrdersCancelled, 0) AS Orders, ROUND((InvoiceNet - COALESCE(RefundNet, 0)) / NULLIF((Orders - COALESCE(OrdersCancelled, 0)), 0), 2) AS NetSalesPerOrder, InvoiceTotal - COALESCE(RefundTotal, 0) AS NetTakings FROM tmp_answer1 t1" &_
" LEFT JOIN tmp_answer2 t2 ON t1.Country = t2.Country;" & NL
ExecuteQuery LSQL
LSQL = "SELECT NULL AS No, t.*, c.CodeA2, c.Currency, IF(c.Currency <> '', c.Currency, IF(c.PostalArea = 'EU', 'EUR', IF(c.PostalArea = 'RW', 'USD', 'GBP'))) AS CurrencyUsed, c.PostalArea, c.RegionCode FROM tmp_answer3 t LEFT JOIN countries c ON c.Country = t.Country ORDER BY Goods DESC, Country"
GetSalesSQL = LSQL
End Function
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">
<%
' (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
%>
<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 = "No" Then
LFieldName = "#"
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
' (SS,11/9/25) added ARecNo
Sub ShowTableRecord(AType, ARecNo)
' 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 = "No" Then
LFieldValue = ARecNo
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 = "Country" Then
LFieldValue = "<a href=""/google-shopping.asp?country=" & GetFieldValue("CodeA2") & "¤cy=" & GetFieldValue("CurrencyUsed") & "&type=table"" target=""_blank"">" & LFieldValue & "</a>"
ElseIf LFieldName = "CodeA2" Then
LFieldValue = "<img src=""blank.gif"" class=""flag flag-" & LCase(LFieldValue) & """ />" & " " & LFieldValue
ElseIf LFieldName = "Email" Then
LFieldValue = "<a href=""mailto:" & LFieldValue & """>" & LFieldValue & "</a>"
ElseIf LFieldName = "Goods" Or LFieldName = "Delivery" Or LFieldName = "InvoiceNet" Or LFieldName = "InvoiceVAT" Or LFieldName = "InvoiceTotal" Or LFieldName = "RefundNet" Or LFieldName = "RefundVAT" Or LFieldName = "RefundTotal" Or LFieldName = "NetSales" Or LFieldName = "NetSalesPerOrder" Or LFieldName = "NetTakings" Then
If LFieldValue <> "" Then
LFieldValue = "£" & 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
End If
ElseIf LFieldName = "Name" Then
'LFieldValue = ReplaceStr(LFieldValue, " ", " ")
' (SS,14/9/20) replaced above with following to internal notes edit
LFieldValue = "<a href=""?cmd=edit&orderno=" & GetFieldValue("OrderNo") & """>" & ReplaceStr(LFieldValue, " ", " ") & "</a>"
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: false,
recordCount: true,
sorting: false,
perPageSelect: false,
search: false
},
dataset: {
perPageDefault: 100
}
}).data('dynatable');
})();
*/
</script>
<%
End Sub
%>