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/inxpress/inxpress - Copy (8).asp
<%@ Language="VBScript" %>
<%
Option Explicit
' =========================================================================================
'  inxpress.asp
'  Displays shipment data from inxpress_shipments_parsed with modal details from
'  inxpress_shipments and delivery pricing from orders.
'
'  ⚠️  IMPORTANT:
'  This page uses a custom SafeHTML() fix for the MySQL ODBC memo/text-field bug.
'  Do NOT replace it with IsNull(), CStr(), or error-handling conversions.
'  Accessing memo/text fields twice (even indirectly) can cause them to return Null
'  after the first read. SafeHTML(val & "") forces a single clean read.
'
'  Author: ChatGPT (with Surinder’s field logic refinements)
'  Date:   2025-10-27
' =========================================================================================

'========================
' Constants / config
'========================
Const PAGE_SIZE = 10000
Const DSN = "MySQL_hyperflight"

'========================
' Helper functions
'========================

' SAFER HTML — critical for MySQL ODBC memo fields
' We must coerce to a VBScript string immediately: val & ""
' DO NOT wrap with IsNull() or CStr() first, that can trigger the memo-null bug.
Function SafeHTML(val)
    Dim tmp
    tmp = Trim(val & "")
    SafeHTML = Server.HTMLEncode(tmp)
End Function

Function IIf(expr, truePart, falsePart)
    If expr Then IIf = truePart Else IIf = falsePart
End Function

Function FmtNum(val)
    ' Blank if null/empty/0
    Dim n
    If IsNull(val) Or Trim(val & "") = "" Then
        FmtNum = ""
        Exit Function
    End If
    If Not IsNumeric(val) Then
        FmtNum = SafeHTML(val)
        Exit Function
    End If
    n = CDbl(val)
    If n = 0 Then
        FmtNum = ""
    Else
        FmtNum = FormatNumber(n, 2, -1, 0, -1)
    End If
End Function

Function NumVal(v)
    If IsNull(v) Or Trim(v & "") = "" Then
        NumVal = 0
    ElseIf IsNumeric(v) Then
        NumVal = CDbl(v)
    Else
        NumVal = 0
    End If
End Function

Function CleanServiceType(txt)
    Dim s
    s = Trim(txt & "")
    If Right(s, 10) = " - Package" Then
        s = Left(s, Len(s) - 10)
    End If
    CleanServiceType = Server.HTMLEncode(s)
End Function

Function CountryFlag(code)
    Dim c
    c = Trim(code & "")
    If c = "" Then
        CountryFlag = ""
        Exit Function
    End If
    c = UCase(c)
    CountryFlag = "<img src='/common/geoip/flags/" & c & ".svg' alt='" & c & _
        "' style='width:20px;height:14px;border:1px solid #ccc;margin-right:4px;vertical-align:middle;'>"
End Function

Response.Expires = -1
Response.Buffer = True

'========================
' DB connection
'========================
Dim conn : Set conn = Server.CreateObject("ADODB.Connection")
conn.Open "DSN=" & DSN

'========================
' Read filters / sorting from querystring
'========================
Dim searchText, carrierSel, invoiceSel, countrySel, sortField, sortDir, missingOrders, duplicateRefs
searchText    = Trim(Request("search"))
carrierSel    = Trim(Request("carrier"))
invoiceSel    = Trim(Request("invoice"))
countrySel    = Trim(Request("country"))
sortField     = Trim(Request("sort"))
sortDir       = UCase(Trim(Request("dir")))
missingOrders = (Request("missingorders") = "1")
duplicateRefs = (Request("duplicates")    = "1")

If sortField = "" Then sortField = "shipment_id"
If sortDir <> "DESC" Then sortDir = "ASC"

'========================
' WHERE clause builder
'========================
Dim whereSQL : whereSQL = " WHERE 1=1"

If searchText <> "" Then
    ' IMPORTANT: in earlier versions we used ReceiverName, keep that.
    whereSQL = whereSQL & " AND (s.Reference LIKE '%" & Replace(searchText,"'","''") & _
              "%' OR s.ReceiverName LIKE '%" & Replace(searchText,"'","''") & "%')"
End If

If carrierSel <> "" Then
    whereSQL = whereSQL & " AND s.Carrier='" & Replace(carrierSel,"'","''") & "'"
End If

If invoiceSel <> "" Then
    whereSQL = whereSQL & " AND s.InvoiceNumber='" & Replace(invoiceSel,"'","''") & "'"
End If

If countrySel <> "" Then
    whereSQL = whereSQL & " AND s.DestCountry='" & Replace(countrySel,"'","''") & "'"
End If

If missingOrders Then
    ' no matching order row
    whereSQL = whereSQL & " AND NOT EXISTS (SELECT 1 FROM orders o WHERE o.OrderNo = s.Reference)"
End If

If duplicateRefs Then
    ' show only refs that appear more than once and are not blank
    whereSQL = whereSQL & _
        " AND s.Reference<>'' AND s.Reference IN (" & _
        "SELECT Reference FROM inxpress_shipments_parsed WHERE Reference<>'' " & _
        "GROUP BY Reference HAVING COUNT(*)>1)"
End If

'========================
' Build main SQL
'========================
' We join:
'   inxpress_shipments_parsed  s   (main parsed fields)
'   inxpress_shipments         d   (raw text blocks for modal)
'   orders                     o   (Delivery costs)
'
' And we also grab d.invoice_number AS DetailInvoice.
Dim sql
sql = "SELECT s.*, " & _
      "d.ShipmentDetails AS ShipmentDetails, " & _
      "d.ReceiverAddress AS ReceiverAddress, " & _
      "d.PiecesWeightDimensionsZone AS PiecesWeightDimensionsZone, " & _
      "d.Charges AS DetailCharges, " & _
      "d.Total AS DetailTotal, " & _
      "d.invoice_number AS DetailInvoice, " & _
      "o.Delivery, o.DeliveryAgentCost, o.DeliveryCalculatedCost " & _
      "FROM inxpress_shipments_parsed s " & _
      "LEFT JOIN inxpress_shipments d ON s.shipment_id = d.shipment_id " & _
      "LEFT JOIN orders o ON s.Reference = o.OrderNo " & _
      whereSQL & " ORDER BY s." & sortField & " " & sortDir & " LIMIT " & PAGE_SIZE

Dim rs : Set rs = conn.Execute(sql)

'========================
' Get dropdown data for filters
'========================
Dim rsC, rsI, rsCn
Set rsC  = conn.Execute("SELECT DISTINCT Carrier FROM inxpress_shipments_parsed ORDER BY Carrier")
Set rsI  = conn.Execute("SELECT DISTINCT InvoiceNumber FROM inxpress_shipments_parsed ORDER BY InvoiceNumber DESC")
Set rsCn = conn.Execute("SELECT DISTINCT DestCountry FROM inxpress_shipments_parsed ORDER BY DestCountry")

'========================
' Build dictionary of reference counts for duplicate highlighting
'========================
Dim refCount : Set refCount = Server.CreateObject("Scripting.Dictionary")
If Not rs.EOF Then
    rs.MoveFirst
    Do Until rs.EOF
        Dim r
        r = Trim(rs("Reference") & "")
        If r <> "" Then
            If Not refCount.Exists(r) Then
                refCount.Add r, 1
            Else
                refCount(r) = refCount(r) + 1
            End If
        End If
        rs.MoveNext
    Loop
    rs.MoveFirst
End If

'========================
' Totals accumulators
'========================
Dim totalBase, totalFuel, totalOther, totalNet, totalVAT, totalGrand
Dim totalDelivery, totalDeliveryAgent, totalDeliveryCalc
totalBase          = 0
totalFuel          = 0
totalOther         = 0
totalNet           = 0
totalVAT           = 0
totalGrand         = 0
totalDelivery      = 0
totalDeliveryAgent = 0
totalDeliveryCalc  = 0

'========================
' Count for footer info
'========================
Dim totalCount
'totalCount = conn.Execute("SELECT COUNT(*) FROM inxpress_shipments_parsed s " & Mid(whereSQL, 8))(0)
' Mid(whereSQL,8) to drop initial " WHERE 1=1" so we don't duplicate WHERE

Dim countSQL
If Trim(whereSQL) = "WHERE 1=1" Or Trim(whereSQL) = "WHERE 1=1 " Then
    countSQL = "SELECT COUNT(*) FROM inxpress_shipments_parsed s"
Else
    countSQL = "SELECT COUNT(*) FROM inxpress_shipments_parsed s" & whereSQL
End If
totalCount = conn.Execute(countSQL)(0)


%>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>InXpress Shipments</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet">
<style>
body{padding:20px;}
.table-responsive{max-height:85vh;overflow-y:auto;}
.table thead th{position:sticky;top:0;background:#f8f9fa;z-index:10;}
.table-sm th,.table-sm td{padding:0.4rem 0.5rem;}
tfoot tr{position:sticky;bottom:0;background:#e9f7ef;z-index:5;}
tfoot td{font-weight:bold;border-top:2px solid #999;}
td.num,th.num{text-align:right;}
td.total,th.total{font-weight:bold;background:#f9f9f9;}
tr.duplicate-row td{background-color:#fff6c9!important;}
th a.sort{text-decoration:none;color:inherit;}
th.active-sort{background:#e0f0ff!important;color:#004085;}
th.active-sort.asc a.sort::after{content:" ▲";font-size:0.8em;}
th.active-sort.desc a.sort::after{content:" ▼";font-size:0.8em;}
.small-service{font-size:0.8rem;line-height:1.2rem;}
.modal-lg{max-width:900px;width:90%;}
pre.modal-block{white-space:pre-wrap;font-family:inherit;margin-bottom:1rem;}
.flag-cty{width:20px;height:14px;border:1px solid #ccc;margin-right:4px;vertical-align:middle;}
</style>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"></script>
<script>
function decodeAttr(str){if(!str)return"";return str.replace(/&#10;/g,"\n").trim();}
function formatForModal(str){if(!str)return"";return str.replace(/;/g,"\n").replace(/\n{2,}/g,"\n").trim();}
function showShipment(btn){
  const d=btn.dataset;
  document.getElementById('m_id').textContent      = d.id||"";
  document.getElementById('m_invoice').textContent = d.invoice||"";
  document.getElementById('m_shipdet').textContent = formatForModal(decodeAttr(d.shipdet||""));
  document.getElementById('m_recv').textContent    = formatForModal(decodeAttr(d.recv||""));
  document.getElementById('m_pieces').textContent  = formatForModal(decodeAttr(d.pieces||""));
  document.getElementById('m_charges').textContent = formatForModal(decodeAttr(d.charges||""));
  document.getElementById('m_total').textContent   = d.total||"";
  new bootstrap.Modal(document.getElementById('shipmentModal')).show();
}
</script>
</head>
<body>
<div class="container-fluid">
<h3 class="mb-3">InXpress Shipments</h3>

<form id="filterForm" class="row row-cols-lg-auto g-2 align-items-center mb-3" method="get">
<div class="col">
  <input type="text" name="search" value="<%=SafeHTML(searchText)%>"
         class="form-control" placeholder="Search Reference or Receiver">
</div>
<div class="col">
  <select name="carrier" class="form-select" onchange="this.form.submit()">
    <option value="">All Carriers</option>
    <%
    Do Until rsC.EOF
      Response.Write "<option value='" & SafeHTML(rsC("Carrier")) & "'"
      If carrierSel=rsC("Carrier") Then Response.Write " selected"
      Response.Write ">" & SafeHTML(rsC("Carrier")) & "</option>"
      rsC.MoveNext
    Loop
    rsC.Close
    %>
  </select>
</div>
<div class="col">
  <select name="invoice" class="form-select" onchange="this.form.submit()">
    <option value="">All Invoices</option>
    <%
    Do Until rsI.EOF
      Response.Write "<option value='" & SafeHTML(rsI("InvoiceNumber")) & "'"
      If invoiceSel=rsI("InvoiceNumber") Then Response.Write " selected"
      Response.Write ">" & SafeHTML(rsI("InvoiceNumber")) & "</option>"
      rsI.MoveNext
    Loop
    rsI.Close
    %>
  </select>
</div>
<div class="col">
  <select name="country" class="form-select" onchange="this.form.submit()">
    <option value="">All Countries</option>
    <%
    Do Until rsCn.EOF
      Response.Write "<option value='" & SafeHTML(rsCn("DestCountry")) & "'"
      If countrySel=rsCn("DestCountry") Then Response.Write " selected"
      Response.Write ">" & SafeHTML(rsCn("DestCountry")) & "</option>"
      rsCn.MoveNext
    Loop
    rsCn.Close
    %>
  </select>
</div>
<div class="col form-check">
  <input class="form-check-input" type="checkbox" name="missingorders" value="1" id="missingorders" onchange="this.form.submit()" <%=IIf(missingOrders,"checked","")%>>
  <label class="form-check-label" for="missingorders">Missing Orders</label>
</div>
<div class="col form-check">
  <input class="form-check-input" type="checkbox" name="duplicates" value="1" id="duplicates" onchange="this.form.submit()" <%=IIf(duplicateRefs,"checked","")%>>
  <label class="form-check-label" for="duplicates">Duplicate References</label>
</div>
<div class="col">
  <button class="btn btn-primary btn-sm">Filter</button>
  <a href="inxpress.asp" class="btn btn-secondary btn-sm">Reset</a>
</div>
</form>

<div class="table-responsive">
<table class="table table-sm table-striped table-bordered align-middle">
<thead class="table-light">
<tr>
<%
Dim cols, headers, i, fieldName, headerName, sortClass, numClass, linkDir, linkURL

cols = Array( _
    "shipment_id","ShipDate","Carrier","Reference","ReceiverName","DestCountry","ServiceType","WeightKg","Length", _
    "BaseCharge","FuelSurcharge","OtherCharges","NetAmount","VATAmount","Total", _
    "Delivery","DeliveryAgentCost","DeliveryCalculatedCost" _
)

headers = Array( _
    "ID","Ship Date","Carrier","Reference","Receiver","Country","Service Type","Weight","Length", _
    "Base (£)","Fuel (£)","Other (£)","Net (£)","VAT (£)","Total (£)", _
    "Delivery","Delivery Agent (£)","Delivery Calc (£)" _
)

For i=0 To UBound(cols)
    fieldName  = cols(i)
    headerName = headers(i)

    sortClass = ""
    If sortField = fieldName Then sortClass = "active-sort " & LCase(sortDir)

    numClass = ""
    If InStr(headerName,"£")>0 _
       Or fieldName="WeightKg" _
       Or fieldName="Length" _
       Or fieldName="shipment_id" _
       Or fieldName="Delivery" _
       Or fieldName="DeliveryAgentCost" _
       Or fieldName="DeliveryCalculatedCost" Then
        numClass = "num"
    End If
    If fieldName="Total" Then numClass = numClass & " total"

    If sortDir="ASC" Then
        linkDir="DESC"
    Else
        linkDir="ASC"
    End If

    linkURL = "?sort=" & fieldName & _
              "&dir=" & linkDir & _
              "&search=" & Server.URLEncode(searchText) & _
              "&carrier=" & Server.URLEncode(carrierSel) & _
              "&invoice=" & Server.URLEncode(invoiceSel) & _
              "&country=" & Server.URLEncode(countrySel) & _
              IIf(missingOrders,"&missingorders=1","") & _
              IIf(duplicateRefs,"&duplicates=1","")

    Response.Write "<th class='" & sortClass & " " & numClass & "'>"
    Response.Write "<a class='sort' href='" & linkURL & "'>" & headerName & "</a></th>"
Next
%>
</tr>
</thead>

<tbody>
<%
If Not rs.EOF Then rs.MoveFirst
Do Until rs.EOF
    ' Work out row class for duplicate highlighting (only in normal mode)
    Dim thisRef
    thisRef = Trim(rs("Reference") & "")
    Dim rowClass
    rowClass = ""
    If (Not duplicateRefs) Then
        If thisRef <> "" Then
            If refCount.Exists(thisRef) Then
                If refCount(thisRef) > 1 Then
                    rowClass = " class=""duplicate-row"""
                End If
            End If
        End If
    End If

    ' compute totals we track
    totalBase          = totalBase          + NumVal(rs("BaseCharge"))
    totalFuel          = totalFuel          + NumVal(rs("FuelSurcharge"))
    totalOther         = totalOther         + NumVal(rs("OtherCharges"))
    totalNet           = totalNet           + NumVal(rs("NetAmount"))
    totalVAT           = totalVAT           + NumVal(rs("VATAmount"))
    totalGrand         = totalGrand         + NumVal(rs("Total"))
    totalDelivery      = totalDelivery      + NumVal(rs("Delivery"))
    totalDeliveryAgent = totalDeliveryAgent + NumVal(rs("DeliveryAgentCost"))
    totalDeliveryCalc  = totalDeliveryCalc  + NumVal(rs("DeliveryCalculatedCost"))

    ' prep modal data attributes (must escape quotes & newlines ourselves):
    Dim shipdetAttr, recvAttr, piecesAttr, chargesAttr, tmpVal
    tmpVal = SafeHTML(rs("ShipmentDetails"))
    tmpVal = Replace(tmpVal, """", "&quot;")
    tmpVal = Replace(tmpVal, vbCrLf, "&#10;")
    tmpVal = Replace(tmpVal, vbLf, "&#10;")
    shipdetAttr = tmpVal

    tmpVal = SafeHTML(rs("ReceiverAddress"))
    tmpVal = Replace(tmpVal, """", "&quot;")
    tmpVal = Replace(tmpVal, vbCrLf, "&#10;")
    tmpVal = Replace(tmpVal, vbLf, "&#10;")
    recvAttr = tmpVal

    tmpVal = SafeHTML(rs("PiecesWeightDimensionsZone"))
    tmpVal = Replace(tmpVal, """", "&quot;")
    tmpVal = Replace(tmpVal, vbCrLf, "&#10;")
    tmpVal = Replace(tmpVal, vbLf, "&#10;")
    piecesAttr = tmpVal

    tmpVal = SafeHTML(rs("DetailCharges"))
    tmpVal = Replace(tmpVal, """", "&quot;")
    tmpVal = Replace(tmpVal, vbCrLf, "&#10;")
    tmpVal = Replace(tmpVal, vbLf, "&#10;")
    chargesAttr = tmpVal

    %>
    <tr<%=rowClass%>>
      <td class="num">
        <button type="button"
                class="btn btn-link p-0 m-0"
                onclick="showShipment(this)"
                data-id="<%=rs("shipment_id")%>"
                data-invoice="<%=SafeHTML(rs("DetailInvoice"))%>"
                data-shipdet="<%=shipdetAttr%>"
                data-recv="<%=recvAttr%>"
                data-pieces="<%=piecesAttr%>"
                data-charges="<%=chargesAttr%>"
                data-total="<%=FmtNum(rs("DetailTotal"))%>">
          <%=rs("shipment_id")%>
        </button>
      </td>

      <td>
        <%
        If IsNull(rs("ShipDate")) Then
            Response.Write ""
        Else
            Response.Write Right("0" & Day(rs("ShipDate")),2) & "/" & _
                            Right("0" & Month(rs("ShipDate")),2) & "/" & _
                            Year(rs("ShipDate"))
        End If
        %>
      </td>

      <td><%=SafeHTML(rs("Carrier"))%></td>
      <td><%=SafeHTML(rs("Reference"))%></td>
      <td><%=SafeHTML(rs("ReceiverName"))%></td>

      <td>
        <%=CountryFlag(rs("DestCountry"))%><%=SafeHTML(rs("DestCountry"))%>
      </td>

      <td class="small-service"><%=CleanServiceType(rs("ServiceType"))%></td>

      <td class="num"><%=SafeHTML(rs("WeightKg"))%></td>
      <td class="num"><%=SafeHTML(rs("Length"))%></td>

      <td class="num"><%=FmtNum(rs("BaseCharge"))%></td>
      <td class="num"><%=FmtNum(rs("FuelSurcharge"))%></td>
      <td class="num"><%=FmtNum(rs("OtherCharges"))%></td>
      <td class="num"><%=FmtNum(rs("NetAmount"))%></td>
      <td class="num"><%=FmtNum(rs("VATAmount"))%></td>
      <td class="num total"><%=FmtNum(rs("Total"))%></td>

      <td class="num"><%=FmtNum(rs("Delivery"))%></td>
      <td class="num"><%=FmtNum(rs("DeliveryAgentCost"))%></td>
      <td class="num"><%=FmtNum(rs("DeliveryCalculatedCost"))%></td>
    </tr>
    <%
    rs.MoveNext
Loop
%>
</tbody>

<tfoot>
<tr>
  <td colspan="10" class="text-end fw-bold">Totals:</td>

  <td class="num fw-bold"><%=FmtNum(totalFuel)%></td>
  <td class="num fw-bold"><%=FmtNum(totalOther)%></td>
  <td class="num fw-bold"><%=FmtNum(totalNet)%></td>
  <td class="num fw-bold"><%=FmtNum(totalVAT)%></td>
  <td class="num fw-bold"><%=FmtNum(totalGrand)%></td>

  <td class="num fw-bold"><%=FmtNum(totalDelivery)%></td>
  <td class="num fw-bold"><%=FmtNum(totalDeliveryAgent)%></td>
  <td class="num fw-bold"><%=FmtNum(totalDeliveryCalc)%></td>
</tr>
</tfoot>

</table>
</div>

<p class="text-muted mt-2">Total records: <%=totalCount%></p>
</div>

<!-- Shipment Details Modal -->
<div class="modal fade" id="shipmentModal" tabindex="-1">
  <div class="modal-dialog modal-lg">
    <div class="modal-content">

      <div class="modal-header">
        <h5 class="modal-title">Shipment Details</h5>
        <button type="button" class="btn-close" data-bs-dismiss="modal"></button>
      </div>

      <div class="modal-body">
        <p><strong>ID:</strong> <span id="m_id"></span></p>
        <p><strong>Invoice:</strong> <span id="m_invoice"></span></p>

        <p><strong>Shipment Details:</strong>
        <pre class="modal-block" id="m_shipdet"></pre></p>

        <p><strong>Receiver Address:</strong>
        <pre class="modal-block" id="m_recv"></pre></p>

        <p><strong>Pieces / Weight / Dimensions / Zone:</strong>
        <pre class="modal-block" id="m_pieces"></pre></p>

        <p><strong>Charges:</strong>
        <pre class="modal-block" id="m_charges"></pre></p>

        <p><strong>Total:</strong> £<span id="m_total"></span></p>
      </div>

      <div class="modal-footer">
        <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
      </div>

    </div>
  </div>
</div>

<!-- ===================================================================== -->
<!--  End of inxpress.asp                                                  -->
<!--  SafeHTML ODBC memo fix active — do not modify conversion logic       -->
<!-- ===================================================================== -->

</body>
</html>
<%
' Cleanup
rs.Close : Set rs = Nothing
conn.Close : Set conn = Nothing
%>