PVFC API - Backend Services

Program.cs

using Microsoft.Data.SqlClient;

var builder = WebApplication.CreateBuilder(args);

// services
builder.Services.AddOpenApi();

var app = builder.Build();

if (app.Environment.IsDevelopment())
{
    app.MapOpenApi();
}


app.MapGet("/api/recommendations/{productId}", (int productId, IConfiguration config) =>
{
    List results = new List();

    string connStr = config.GetConnectionString("PVFC");

    using (SqlConnection con = new SqlConnection(connStr))
    {
        con.Open();

        string query = @"
        SELECT DISTINCT p2.Product_Description
        FROM Order_line_t ol1
        JOIN Order_line_t ol2 
            ON ol1.Order_Id = ol2.Order_Id
        JOIN PRODUCT_t p1 ON ol1.Product_Id = p1.Product_Id
        JOIN PRODUCT_t p2 ON ol2.Product_Id = p2.Product_Id
        WHERE ol1.Product_Id = @pid
          AND ol2.Product_Id <> @pid";

        SqlCommand cmd = new SqlCommand(query, con);
        cmd.Parameters.AddWithValue("@pid", productId);

        SqlDataReader reader = cmd.ExecuteReader();

        while (reader.Read())
        {
            results.Add(reader["Product_Description"].ToString());
        }
    }

    return results;
});

app.MapGet("/api/reorder/{customerId}", (int customerId, IConfiguration config) =>
{
    List result = new List();

    string connStr = config.GetConnectionString("PVFC");

    using (SqlConnection con = new SqlConnection(connStr))
    {
        con.Open();

        string query = @"
        SELECT DISTINCT P.Product_Description
        FROM ORDER_t O
        JOIN Order_line_t OL ON O.Order_Id = OL.Order_Id
        JOIN PRODUCT_t P ON P.Product_Id = OL.Product_Id
        WHERE O.Customer_Id = @cid";

        SqlCommand cmd = new SqlCommand(query, con);
        cmd.Parameters.AddWithValue("@cid", customerId);

        SqlDataReader dr = cmd.ExecuteReader();

        while (dr.Read())
        {
            result.Add(dr["Product_Description"].ToString());
        }
    }

    return result;
});

app.MapGet("/api/forecast/{productId}", (int productId, IConfiguration config) =>
{
    List result = new List();

    string connStr = config.GetConnectionString("PVFC");

    using (SqlConnection con = new SqlConnection(connStr))
    {
        con.Open();

        string query = @"
        SELECT TOP 5 
            p2.Product_Description,
            COUNT(*) AS Frequency
        FROM Order_line_t ol1
        JOIN Order_line_t ol2 
            ON ol1.Order_Id = ol2.Order_Id
        JOIN PRODUCT_t p1 ON ol1.Product_Id = p1.Product_Id
        JOIN PRODUCT_t p2 ON ol2.Product_Id = p2.Product_Id
        WHERE ol1.Product_Id = @pid
          AND ol2.Product_Id <> @pid
        GROUP BY p2.Product_Description
        ORDER BY Frequency DESC";

        SqlCommand cmd = new SqlCommand(query, con);
        cmd.Parameters.AddWithValue("@pid", productId);

        SqlDataReader dr = cmd.ExecuteReader();

        while (dr.Read())
        {
            result.Add(new
            {
                Product = dr["Product_Description"].ToString(),
                DemandScore = dr["Frequency"].ToString()
            });
        }
    }

    return result;
});

app.Run();


    

appsettings.json

{
  "ConnectionStrings": {
    "PVFC": "Server=db42115.public.databaseasp.net;Database=db42115;User Id=db42115;Password=qR@4?a7AC9#e;Encrypt=True;TrustServerCertificate=True;MultipleActiveResultSets=True;"
  },

  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.AspNetCore": "Warning"
    }
  },

  "AllowedHosts": "*"
}

Functionality: Recommendation System

search.aspx

<%@ Page Language="VB" AutoEventWireup="false" CodeFile="search.aspx.vb" Inherits="search" %>

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title>Search Products - Pine Valley Furniture</title>
    <link rel="stylesheet" href="style.css" />
</head>
<body>

<form id="form1" runat="server">

<header>
    <h1>Search Products</h1>
</header>

<nav>
    <ul>
        <li><a href="main.aspx">Home</a></li>
        <li><a href="Cart.aspx">Cart</a></li>
    </ul>
</nav>

<div class="container">

    <div style="margin-bottom:20px;">

        <asp:Label Text="Search Product:" runat="server" />

        <asp:TextBox 
            ID="txtSearch" 
            runat="server" 
            style="padding:8px; border-radius:6px; border:1px solid #ccc;">
        </asp:TextBox>

        <asp:Button 
            ID="btnSearch"
            runat="server"
            Text="Search"
            CssClass="btn"
            OnClick="btnSearch_Click" />

        <asp:Button 
            ID="btnShowAll"
            runat="server"
            Text="Show All"
            CssClass="btn"
            OnClick="btnShowAll_Click" />

    </div>

    <asp:Label ID="lblMessage" runat="server"></asp:Label>

    <br /><br />

    <div class="product-grid">

        <asp:Repeater ID="rptProducts" runat="server" OnItemCommand="rptProducts_ItemCommand">

            <ItemTemplate>

                <div class="product-card">

                    <div class="image-box"></div>

                    <h3><%# Eval("Product_Description") %></h3>

                    <p>Finish: <%# Eval("Product_Finish") %></p>

                    <p><strong>$ <%# Eval("Standard_Price") %></strong></p>

                    <div style="margin-top:10px;">
                        Quantity:

                        <asp:TextBox 
                            ID="txtQty" 
                            runat="server" 
                            Width="50px"
                            style="padding:5px; border-radius:6px; border:1px solid #ccc;">
                        </asp:TextBox>
                    </div>

                    <asp:Button 
                        ID="btnAdd"
                        runat="server"
                        Text="Add To Cart"
                        CssClass="btn"
                        style="margin-top:10px; width:100%;"
                        CommandName="AddToCart"
                        CommandArgument='<%# Eval("Product_Id") %>' />

                    <br /><br />

                    <asp:Button 
                        ID="btnRecommend"
                        runat="server"
                        Text="Show Recommendations"
                        CssClass="btn"
                        style="width:100%;"
                        CommandName="Recommend"
                        CommandArgument='<%# Eval("Product_Id") %>' />

                    <br /><br />

                    <asp:BulletedList 
                        ID="blRecommendations"
                        runat="server">
                    </asp:BulletedList>

                </div>

            </ItemTemplate>

        </asp:Repeater>

    </div>

</div>

</form>
</body>
</html>

search.aspx.vb

Imports System.Collections.Generic
Imports System.Configuration
Imports System.Data.SqlClient
Imports System.Net
Imports Newtonsoft.Json

Partial Class search
    Inherits System.Web.UI.Page

    Dim connStr As String =
        ConfigurationManager.ConnectionStrings("PVFC").ConnectionString

    Protected Sub btnSearch_Click(sender As Object, e As EventArgs)

        Dim con As New SqlConnection(connStr)

        Dim query As String =
            "SELECT Product_Id, Product_Description, Product_Finish, Standard_Price " &
            "FROM PRODUCT_t WHERE Product_Description LIKE @search"

        Dim cmd As New SqlCommand(query, con)

        cmd.Parameters.AddWithValue("@search", "%" & txtSearch.Text & "%")

        con.Open()

        Dim dr As SqlDataReader = cmd.ExecuteReader()

        rptProducts.DataSource = dr
        rptProducts.DataBind()

        con.Close()

    End Sub

    Protected Sub btnShowAll_Click(sender As Object, e As EventArgs)

        Dim con As New SqlConnection(connStr)

        Dim query As String =
            "SELECT Product_Id, Product_Description, Product_Finish, Standard_Price FROM PRODUCT_t"

        Dim cmd As New SqlCommand(query, con)

        con.Open()

        Dim dr As SqlDataReader = cmd.ExecuteReader()

        rptProducts.DataSource = dr
        rptProducts.DataBind()

        con.Close()

    End Sub

    Protected Sub rptProducts_ItemCommand(source As Object, e As RepeaterCommandEventArgs)

        If e.CommandName = "AddToCart" Then

            If Session("Customer_Id") Is Nothing Then
                Response.Redirect("CustomerLogin.aspx")
                Exit Sub
            End If

            Dim customerId As Integer =
                Convert.ToInt32(Session("Customer_Id"))

            Dim productId As Integer =
                Convert.ToInt32(e.CommandArgument)

            Dim txtQty As TextBox =
                CType(e.Item.FindControl("txtQty"), TextBox)

            If txtQty.Text = "" Then
                lblMessage.Text = "Enter quantity."
                Exit Sub
            End If

            Dim quantity As Integer =
                Convert.ToInt32(txtQty.Text)

            Dim con As New SqlConnection(connStr)
            con.Open()

            Dim orderId As Integer = 0

            Dim checkOrderQuery As String =
                "SELECT TOP 1 Order_Id FROM ORDER_t WHERE Customer_Id = @cid AND Order_Date = CAST(GETDATE() AS DATE)"

            Dim cmdCheckOrder As New SqlCommand(checkOrderQuery, con)
            cmdCheckOrder.Parameters.AddWithValue("@cid", customerId)

            Dim result = cmdCheckOrder.ExecuteScalar()

            If result Is Nothing Then

                Dim newIdQuery As String =
                    "SELECT ISNULL(MAX(Order_Id),1000)+1 FROM ORDER_t"

                Dim cmdNewId As New SqlCommand(newIdQuery, con)
                orderId = Convert.ToInt32(cmdNewId.ExecuteScalar())

                Dim insertOrderQuery As String =
                    "INSERT INTO ORDER_t VALUES (@oid, @cid, CAST(GETDATE() AS DATE))"

                Dim cmdInsertOrder As New SqlCommand(insertOrderQuery, con)
                cmdInsertOrder.Parameters.AddWithValue("@oid", orderId)
                cmdInsertOrder.Parameters.AddWithValue("@cid", customerId)
                cmdInsertOrder.ExecuteNonQuery()

            Else
                orderId = Convert.ToInt32(result)
            End If

            Dim checkLineQuery As String =
                "SELECT Ordered_Quantity FROM Order_line_t WHERE Order_Id = @oid AND Product_Id = @pid"

            Dim cmdCheckLine As New SqlCommand(checkLineQuery, con)
            cmdCheckLine.Parameters.AddWithValue("@oid", orderId)
            cmdCheckLine.Parameters.AddWithValue("@pid", productId)

            Dim existingQty = cmdCheckLine.ExecuteScalar()

            If existingQty IsNot Nothing Then

                Dim newQty As Integer =
                    Convert.ToInt32(existingQty) + quantity

                Dim updateQuery As String =
                    "UPDATE Order_line_t SET Ordered_Quantity = @qty WHERE Order_Id = @oid AND Product_Id = @pid"

                Dim cmdUpdate As New SqlCommand(updateQuery, con)
                cmdUpdate.Parameters.AddWithValue("@qty", newQty)
                cmdUpdate.Parameters.AddWithValue("@oid", orderId)
                cmdUpdate.Parameters.AddWithValue("@pid", productId)
                cmdUpdate.ExecuteNonQuery()

            Else

                Dim insertLineQuery As String =
                    "INSERT INTO Order_line_t VALUES (@oid, @pid, @qty)"

                Dim cmdInsertLine As New SqlCommand(insertLineQuery, con)
                cmdInsertLine.Parameters.AddWithValue("@oid", orderId)
                cmdInsertLine.Parameters.AddWithValue("@pid", productId)
                cmdInsertLine.Parameters.AddWithValue("@qty", quantity)
                cmdInsertLine.ExecuteNonQuery()

            End If

            con.Close()

            lblMessage.Text = "Product added to YOUR cart!"

        End If

        If e.CommandName = "Recommend" Then

            Dim productId As Integer =
                Convert.ToInt32(e.CommandArgument)

            Dim apiUrl As String =
                "http://localhost:5064/api/recommendations/" & productId

            Dim client As New WebClient()

            Dim json As String =
                client.DownloadString(apiUrl)

            Dim recommendations As List(Of String) =
                JsonConvert.DeserializeObject(Of List(Of String))(json)

            Dim bl As BulletedList =
                CType(e.Item.FindControl("blRecommendations"), BulletedList)

            bl.DataSource = recommendations
            bl.DataBind()

        End If

    End Sub

End Class

Functionality: Reordering Suggestions for Customer

Cart.aspx

<%@ Page Language="VB" AutoEventWireup="true" CodeFile="Cart.aspx.vb" Inherits="Cart" %>

<!DOCTYPE html>
<html>
<head runat="server">
    <title>My Cart</title>
    <link rel="stylesheet" href="style.css" />
</head>
<body>

<form id="form1" runat="server">

    <h2>My Cart</h2>

    
    <asp:GridView ID="gvCart" runat="server" AutoGenerateColumns="False" CssClass="cart-table">

        <Columns>
            <asp:BoundField DataField="Product_Description" HeaderText="Product" />
            <asp:BoundField DataField="Quantity" HeaderText="Quantity" />
            <asp:BoundField DataField="Price" HeaderText="Price" DataFormatString="{0:C}" />
            <asp:BoundField DataField="Total" HeaderText="Total" DataFormatString="{0:C}" />
        </Columns>

    </asp:GridView>

    <br />

    
    <asp:Label ID="lblGrandTotal" runat="server" Font-Bold="True"></asp:Label>

    <br /><br />

    
    <asp:Button 
        ID="btnCheckout" 
        runat="server" 
        Text="Proceed to Checkout" 
        PostBackUrl="Payment.aspx" 
        CssClass="btn" />

    <hr />

   
    <h3>Reordering Suggestions</h3>

    <asp:Button 
        ID="btnReorder"
        runat="server"
        Text="Show Reorder Suggestions"
        CssClass="btn"
        OnClick="btnReorder_Click" />

    <br /><br />

    <asp:BulletedList 
        ID="blReorder"
        runat="server">
    </asp:BulletedList>

</form>

</body>
</html>

Cart.aspx.vb

Imports System.Collections.Generic
Imports System.Configuration
Imports System.Data
Imports System.Data.SqlClient
Imports System.Net
Imports Newtonsoft.Json

Partial Class Cart
    Inherits System.Web.UI.Page

    Private connStr As String =
        ConfigurationManager.ConnectionStrings("PVFC").ConnectionString

    Protected Sub Page_Load(sender As Object, e As EventArgs) Handles Me.Load

        If Not IsPostBack Then
            LoadCart()
        End If

    End Sub

    Private Sub LoadCart()

        If Session("Customer_Id") Is Nothing Then
            Response.Redirect("CustomerLogin.aspx")
            Return
        End If

        Dim customerId As Integer =
            Convert.ToInt32(Session("Customer_Id"))

        Using conn As New SqlConnection(connStr)

            Dim query As String =
                "SELECT p.Product_Description, " &
                "ol.Ordered_Quantity AS Quantity, " &
                "p.Standard_Price AS Price, " &
                "(ol.Ordered_Quantity * p.Standard_Price) AS Total " &
                "FROM ORDER_t o " &
                "INNER JOIN Order_line_t ol ON o.Order_Id = ol.Order_Id " &
                "INNER JOIN PRODUCT_t p ON ol.Product_Id = p.Product_Id " &
                "WHERE o.Customer_Id = @CustomerId " &
                "AND o.Order_Id = (SELECT MAX(Order_Id) FROM ORDER_t WHERE Customer_Id = @CustomerId)"

            Using cmd As New SqlCommand(query, conn)

                cmd.Parameters.AddWithValue("@CustomerId", customerId)

                Dim dt As New DataTable()

                Using da As New SqlDataAdapter(cmd)
                    da.Fill(dt)
                End Using

                gvCart.DataSource = dt
                gvCart.DataBind()

                Dim grandTotal As Decimal = 0

                For Each row As DataRow In dt.Rows
                    grandTotal += Convert.ToDecimal(row("Total"))
                Next

                lblGrandTotal.Text = "Grand Total: " & grandTotal.ToString("C")

            End Using

        End Using

    End Sub

    Protected Sub btnReorder_Click(sender As Object, e As EventArgs)

        If Session("Customer_Id") Is Nothing Then
            Response.Redirect("CustomerLogin.aspx")
            Exit Sub
        End If

        Dim customerId As Integer =
            Convert.ToInt32(Session("Customer_Id"))

        Dim apiUrl As String =
            "http://localhost:5064/api/reorder/" & customerId

        Dim client As New WebClient()

        Dim json As String =
            client.DownloadString(apiUrl)

        Dim items As List(Of String) =
            JsonConvert.DeserializeObject(Of List(Of String))(json)

        blReorder.DataSource = items
        blReorder.DataBind()

    End Sub

End Class

Functionality: Forecasting Demand for Secondary Item

employee_dashboard.aspx

<%@ Page Language="VB" AutoEventWireup="true" CodeFile="employee_dashboard.aspx.vb" Inherits="employee_dashboard" %>

<!DOCTYPE html>
<html>
<head runat="server">
    <title>Employee Dashboard</title>
    <link rel="stylesheet" href="style.css" />
</head>

<body>

<form id="form1" runat="server">

    <header>
        <h1>Employee Dashboard</h1>
    </header>

    <nav>
        <ul>

            <li>
                <asp:HyperLink ID="hlUpdateCatalog" runat="server"
                    NavigateUrl="update_catalog.aspx"
                    Text="Update Product Catalog" />
            </li>

            <li>
                <asp:HyperLink ID="hlUpdateCustomer" runat="server"
                    NavigateUrl="update_customer.aspx"
                    Text="Update Customer" />
            </li>

            <li>
                <asp:HyperLink ID="hlSegmentation" runat="server"
                    NavigateUrl="Segmentation.aspx"
                    Text="Customer Segmentation" />
            </li>

            <li>
                <asp:Button ID="btnLogout" runat="server"
                    Text="Logout"
                    CssClass="btn"
                    OnClick="btnLogout_Click" />
            </li>

        </ul>
    </nav>

    <div class="container">

        <h2>Welcome, Employee!</h2>

        <p>Select an option from the menu above to proceed.</p>

        <hr />

        <h3>Inventory Forecasting (Secondary Items Demand)</h3>

        <asp:Label Text="Enter Primary Product ID:" runat="server" />

        <asp:TextBox ID="txtProductId" runat="server"></asp:TextBox>

        <asp:Button ID="btnForecast"
            runat="server"
            Text="Forecast Demand"
            CssClass="btn"
            OnClick="btnForecast_Click" />

        <br /><br />

        <asp:GridView ID="gvForecast"
            runat="server"
            CssClass="cart-table">
        </asp:GridView>

    </div>

</form>

</body>
</html>

employee_dashboard.aspx.vb

Imports System.Net
Imports Newtonsoft.Json
Imports System.Data

Partial Class employee_dashboard
    Inherits System.Web.UI.Page

    Protected Sub Page_Load(sender As Object, e As EventArgs) Handles Me.Load
        If Session("Role") Is Nothing OrElse Session("Role").ToString() <> "Employee" Then
            Response.Redirect("EmployeeLogin.aspx")
        End If
    End Sub

    Protected Sub btnLogout_Click(sender As Object, e As EventArgs)
        Session.Clear()
        Response.Redirect("LoginChoice.aspx")
    End Sub

    Protected Sub btnForecast_Click(sender As Object, e As EventArgs)

        Dim productId As Integer = Convert.ToInt32(txtProductId.Text)

        Dim apiUrl As String = "http://localhost:5064/api/forecast/" & productId

        Dim client As New WebClient()

        Dim json As String = client.DownloadString(apiUrl)

        Dim dt As DataTable =
            JsonConvert.DeserializeObject(Of DataTable)(json)

        gvForecast.DataSource = dt
        gvForecast.DataBind()

    End Sub

End Class