File: D:/web/hyperflight/apps/stockflow/index-v1.asp
<%
Option Explicit
' ADO Constants for Parameterized Queries
Const adCmdText = 1
Const adParamInput = 1
Const adVarChar = 200
Const adInteger = 3
Dim productCode, conn, cmd, rs
Dim productID, recordedNumInStock, currentCalculatedStock, discrepancy
Dim transactionDate, transType, qty, ref, status
Dim startingStockInput, startingStock, startDate
Dim sqlOrders, sqlInvoices
' Initialize variables from form submission
productCode = Trim(Request.Form("ProductCode"))
startingStockInput = Trim(Request.Form("StartingStock"))
startDate = Trim(Request.Form("StartDate"))
' Default starting stock to 0 if left blank or invalid
If IsNumeric(startingStockInput) Then
startingStock = CLng(startingStockInput)
Else
startingStock = 0
End If
productID = 0
recordedNumInStock = 0
currentCalculatedStock = startingStock ' Set our baseline
If productCode <> "" Then
' 1. Open Database Connection using the requested DSN
Set conn = Server.CreateObject("ADODB.Connection")
conn.Open "DSN=MySQL_hyperflight;"
' 2. Get ProductID and Current System Stock
Set cmd = Server.CreateObject("ADODB.Command")
Set cmd.ActiveConnection = conn
cmd.CommandType = adCmdText
cmd.CommandText = "SELECT ProductID, NumInStock FROM products WHERE ProductCode = ?"
cmd.Parameters.Append cmd.CreateParameter("@ProdCode", adVarChar, adParamInput, 20, productCode)
Set rs = cmd.Execute()
If Not rs.EOF Then
productID = rs("ProductID")
If Not IsNull(rs("NumInStock")) Then
recordedNumInStock = CLng(rs("NumInStock"))
End If
End If
rs.Close
Set cmd = Nothing
' 3. Run the transaction query if a valid product was found
If productID > 0 Then
Set cmd = Server.CreateObject("ADODB.Command")
Set cmd.ActiveConnection = conn
cmd.CommandType = adCmdText
' Base Queries - Added AND o.IsInvoice = 1 to the orders query
sqlOrders = "SELECT o.DateTimeOrdered AS TransDate, 'OUT' AS TransType, od.Qty AS Amount, CAST(o.OrderNo AS VARCHAR(50)) AS Ref, o.Status " & _
"FROM orders o " & _
"INNER JOIN orderdetails od ON o.OrderNo = od.OrderNo " & _
"WHERE od.ProductID = ? " & _
"AND o.Status IN ('COMPLETED', 'PAYMENT RECEIVED', 'AWAITING PAYMENT', 'PAYMENT ON ACCOUNT') " & _
"AND o.IsInvoice = 1 "
sqlInvoices = "SELECT CAST(pi.InvoiceDate AS DATETIME) AS TransDate, 'IN' AS TransType, pil.QtyAddedToStock AS Amount, CAST(pi.PurchaseInvoiceID AS VARCHAR(50)) AS Ref, pi.InvoiceStatus AS Status " & _
"FROM purchase_invoices pi " & _
"INNER JOIN purchase_invoice_lines pil ON pi.PurchaseInvoiceID = pil.PurchaseInvoiceID " & _
"INNER JOIN purchase_order_lines pol ON pil.PurchaseOrderLineID = pol.PurchaseOrderLineID " & _
"WHERE pol.ProductID = ? "
' Dynamically append the date filter if a Start Date was provided
If startDate <> "" Then
sqlOrders = sqlOrders & " AND o.DateTimeOrdered >= ? "
sqlInvoices = sqlInvoices & " AND pi.InvoiceDate >= ? "
End If
' Combine the queries
cmd.CommandText = sqlOrders & " UNION ALL " & sqlInvoices & " ORDER BY TransDate ASC"
' Append parameters in the exact order they appear in the combined SQL string
' 1. ProductID for Orders
cmd.Parameters.Append cmd.CreateParameter("@ProdID1", adInteger, adParamInput, , productID)
' 2. StartDate for Orders (if applicable)
If startDate <> "" Then
cmd.Parameters.Append cmd.CreateParameter("@StartDate1", adVarChar, adParamInput, 20, startDate & " 00:00:00")
End If
' 3. ProductID for Invoices
cmd.Parameters.Append cmd.CreateParameter("@ProdID2", adInteger, adParamInput, , productID)
' 4. StartDate for Invoices (if applicable)
If startDate <> "" Then
cmd.Parameters.Append cmd.CreateParameter("@StartDate2", adVarChar, adParamInput, 20, startDate)
End If
Set rs = cmd.Execute()
End If
End If
%>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Stock Ledger & Audit</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet">
<style>
.table-responsive { max-width: 1000px; }
.qty-in { color: #198754; font-weight: bold; }
.qty-out { color: #dc3545; font-weight: bold; }
</style>
</head>
<body class="bg-light pb-5">
<div class="container mt-5">
<div class="card shadow-sm mb-4" style="max-width: 1000px;">
<div class="card-header bg-primary text-white">
<h4 class="mb-0">Stock Ledger & Audit</h4>
</div>
<div class="card-body">
<form method="post" action="index.asp" class="row g-3 align-items-center">
<div class="col-auto">
<label for="ProductCode" class="col-form-label fw-bold">Product Code:</label>
</div>
<div class="col-auto">
<input type="text" id="ProductCode" name="ProductCode" class="form-control" value="<%=Server.HTMLEncode(productCode)%>" required>
</div>
<div class="col-auto ms-2">
<label for="StartingStock" class="col-form-label fw-bold">Start Stock:</label>
</div>
<div class="col-auto">
<input type="number" id="StartingStock" name="StartingStock" class="form-control" style="width: 100px;" value="<%=startingStock%>">
</div>
<div class="col-auto ms-2">
<label for="StartDate" class="col-form-label fw-bold">Start Date:</label>
</div>
<div class="col-auto">
<input type="date" id="StartDate" name="StartDate" class="form-control" value="<%=Server.HTMLEncode(startDate)%>">
</div>
<div class="col-auto ms-3">
<button type="submit" class="btn btn-primary">Run Ledger</button>
</div>
</form>
</div>
</div>
<% If productCode <> "" Then %>
<% If productID = 0 Then %>
<div class="alert alert-warning" style="max-width: 1000px;">
Product code <strong><%=Server.HTMLEncode(productCode)%></strong> was not found in the database.
</div>
<% ElseIf IsObject(rs) Then %>
<h5 class="mb-3">Ledger for: <span class="text-primary"><%=Server.HTMLEncode(productCode)%></span></h5>
<div class="table-responsive bg-white shadow-sm rounded">
<table class="table table-striped table-hover table-bordered mb-0">
<thead class="table-dark">
<tr>
<th>Date</th>
<th>Type</th>
<th>Internal Ref</th>
<th>Status</th>
<th>Qty Change</th>
<th>Running Stock</th>
</tr>
</thead>
<tbody>
<tr class="table-secondary">
<td><em><% If startDate <> "" Then Response.Write Server.HTMLEncode(startDate) Else Response.Write "Baseline" End If %></em></td>
<td colspan="4"><em>Initial Starting Stock</em></td>
<td class="fw-bold"><%=startingStock%></td>
</tr>
<%
If rs.EOF Then
Response.Write "<tr><td colspan='6' class='text-center'>No transactions found for this period.</td></tr>"
Else
Do While Not rs.EOF
If IsNull(rs("TransDate")) Then
transactionDate = "Not Recorded"
Else
transactionDate = rs("TransDate")
End If
transType = rs("TransType")
qty = 0
If Not IsNull(rs("Amount")) Then qty = CLng(rs("Amount"))
ref = rs("Ref")
status = rs("Status")
If qty > 0 Then
If transType = "IN" Then
currentCalculatedStock = currentCalculatedStock + qty
ElseIf transType = "OUT" Then
currentCalculatedStock = currentCalculatedStock - qty
End If
%>
<tr>
<td><%=transactionDate%></td>
<td>
<% If transType = "IN" Then %>
<span class="badge bg-success">IN (Purchase)</span>
<% Else %>
<span class="badge bg-danger">OUT (Order)</span>
<% End If %>
</td>
<td><%=ref%></td>
<td><span class="badge bg-secondary"><%=status%></span></td>
<td class="<%=IfHelper(transType="IN", "qty-in", "qty-out")%>">
<%=IfHelper(transType="IN", "+", "-")%><%=qty%>
</td>
<td class="fw-bold"><%=currentCalculatedStock%></td>
</tr>
<%
End If
rs.MoveNext
Loop
End If
rs.Close
Set rs = Nothing
Set cmd = Nothing
conn.Close
Set conn = Nothing
%>
</tbody>
</table>
</div>
<% discrepancy = currentCalculatedStock - recordedNumInStock %>
<div class="card mt-4 shadow-sm" style="max-width: 500px;">
<div class="card-header bg-dark text-white fw-bold">
Audit Result
</div>
<ul class="list-group list-group-flush">
<li class="list-group-item d-flex justify-content-between align-items-center">
Starting Stock Baseline
<span class="badge bg-secondary rounded-pill fs-6"><%=startingStock%></span>
</li>
<li class="list-group-item d-flex justify-content-between align-items-center">
<strong>Expected Stock Level</strong>
<span class="badge bg-primary rounded-pill fs-6"><%=currentCalculatedStock%></span>
</li>
<li class="list-group-item d-flex justify-content-between align-items-center">
Database `NumInStock`
<span class="badge bg-info rounded-pill fs-6"><%=recordedNumInStock%></span>
</li>
<li class="list-group-item d-flex justify-content-between align-items-center fw-bold">
Discrepancy (Expected vs Database)
<% If discrepancy = 0 Then %>
<span class="badge bg-success rounded-pill fs-6">Match (0)</span>
<% Else %>
<span class="badge bg-warning text-dark rounded-pill fs-6"><%=discrepancy%></span>
<% End If %>
</li>
</ul>
</div>
<% End If %>
<% End If %>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>
<%
Function IfHelper(condition, trueResult, falseResult)
If condition Then
IfHelper = trueResult
Else
IfHelper = falseResult
End If
End Function
%>