Preview an Order - Code

C#

POHeader.cs

using System;
using System.ComponentModel.DataAnnotations;
// This is the model for one row in the database table.
namespace BlazorPurchaseOrders.Data
{
    public class POHeader
    {
        [Required]
        public int POHeaderID { get; set; }

        [Required]
        public int POHeaderOrderNumber { get; set; }

        [Required]
        public DateTime POHeaderOrderDate { get; set; }

        [Required]
        public int POHeaderSupplierID { get; set; }

        [StringLength(50, ErrorMessage = "'Address' has a maximum length of 50 characters.")]
        public string POHeaderSupplierAddress1 { get; set; }

        [StringLength(50, ErrorMessage = "'Address' has a maximum length of 50 characters.")]
        public string POHeaderSupplierAddress2 { get; set; }

        [StringLength(50, ErrorMessage = "'Address' has a maximum length of 50 characters.")]
        public string POHeaderSupplierAddress3 { get; set; }

        [StringLength(10, ErrorMessage = "'Post Code' has a maximum length of 10 characters.")]
        public string POHeaderSupplierPostCode { get; set; }

        [StringLength(256, ErrorMessage = "'Email' has a maximum length of 256 characters.")]
        [EmailAddress(ErrorMessage = "Invalid Email Address format.")]
        public string POHeaderSupplierEmail { get; set; }

        [StringLength(450)]
        public string POHeaderRequestedBy { get; set; }

        [Required]
        public bool POHeaderIsArchived { get; set; }

        public string SupplierName { get; }

        public decimal TotalOrderValue { get; }
        public decimal NetPrice { get; }

        public decimal Tax { get; }
    }
}

Index.razor

@page "/"
@using BlazorPurchaseOrders.Data

@inject IPOHeaderService POHeaderService
@inject NavigationManager NavigationManager
@inject IJSRuntime IJS

<div class="col-sm-12">
    <h3>Purchase Orders</h3>
    <br />
    <SfGrid DataSource="@poheader"
            Toolbar="Toolbaritems">
        <GridEvents RowSelected="RowSelectHandler" OnToolbarClick="ToolbarClickHandler" TValue="POHeader"></GridEvents>
        <GridColumns>
            <GridColumn Field="@nameof(POHeader.POHeaderOrderNumber)"
                        HeaderText="No"
                        TextAlign="@TextAlign.Left"
                        Width="10">
            </GridColumn>
            <GridColumn Field="@nameof(POHeader.POHeaderOrderDate)"
                        HeaderText="Date"
                        Format="d"
                        Type="ColumnType.Date"
                        TextAlign="@TextAlign.Center"
                        Width="15">
            </GridColumn>
            <GridColumn Field="@nameof(POHeader.SupplierName)"
                        HeaderText="Supplier"
                        TextAlign="@TextAlign.Left"
                        Width="40">
            </GridColumn>
            <GridColumn Field="@nameof(POHeader.TotalOrderValue)"
                        HeaderText="Value"
                        TextAlign="@TextAlign.Right"
                        Format="C2"
                        Width="20">
            </GridColumn>
            <GridColumn Field="@nameof(POHeader.POHeaderRequestedBy)"
                        HeaderText="Requested by"
                        TextAlign="@TextAlign.Left"
                        Width="40">
            </GridColumn>
        </GridColumns>
    </SfGrid>

    <WarningPage @ref="Warning" WarningHeaderMessage="@WarningHeaderMessage" WarningContentMessage="@WarningContentMessage" />

    <ConfirmPage @ref="ConfirmOrderDelete" ConfirmHeaderMessage="@ConfirmHeaderMessage" ConfirmContentMessage="@ConfirmContentMessage" ConfirmationChanged="ConfirmOrderArchive" />
</div>

@code {

    // Create an empty list, named poheader, of empty POHeader objects.
    IEnumerable<POHeader> poheader;
    POHeader orderHeader = new POHeader();

    private List<ItemModel> Toolbaritems = new List<ItemModel>();

    int POHeaderID = 0;

    private int selectedPOHeaderID { get; set; } = 0;

    WarningPage Warning;
    string WarningHeaderMessage = "";
    string WarningContentMessage = "";

    ConfirmPage ConfirmOrderDelete;
    string ConfirmHeaderMessage = "";
    string ConfirmContentMessage = "";
    public bool ConfirmationChanged { get; set; } = false;

    protected override async Task OnInitializedAsync()
    {
        //Populate the list of countries objects from the Countries table.
        poheader = await POHeaderService.POHeaderList();

        Toolbaritems.Add(new ItemModel() { Text = "Add", TooltipText = "Add a new order", PrefixIcon = "e-add" });
        Toolbaritems.Add(new ItemModel() { Text = "Edit", TooltipText = "Edit selected order", PrefixIcon = "e-edit" });
        Toolbaritems.Add(new ItemModel() { Text = "Delete", TooltipText = "Delete selected order", PrefixIcon = "e-delete" });
        Toolbaritems.Add(new ItemModel() { Text = "Preview", TooltipText = "Preview selected order", PrefixIcon = "e-print" });
    }


    public async Task ToolbarClickHandler(Syncfusion.Blazor.Navigations.ClickEventArgs args)
    {
        if (args.Item.Text == "Add")
        {
            //Code for adding goes here
            POHeaderID = 0;
            NavigationManager.NavigateTo($"/purchaseorder/{POHeaderID}");

        }

        if (args.Item.Text == "Edit")
        {

            //Code for editing - Check that an Order has been selected from the grid
            if (selectedPOHeaderID == 0)
            {
                WarningHeaderMessage = "Warning!";
                WarningContentMessage = "Please select an Order from the grid.";
                Warning.OpenDialog();
            }
            else
            {
                NavigationManager.NavigateTo($"/purchaseorder/{selectedPOHeaderID}");
            }

        }

        if (args.Item.Text == "Delete")
        {
            //Code for deleting
            if (selectedPOHeaderID == 0)    //Check that an order has been selected
            {
                WarningHeaderMessage = "Warning!";
                WarningContentMessage = "Please select an Order from the grid.";
                Warning.OpenDialog();
            }
            else
            {
                //Populate orderHeader using selectedPOHeaderID
                orderHeader = await POHeaderService.POHeader_GetOne(selectedPOHeaderID);

                ConfirmHeaderMessage = "Confirm Deletion";
                ConfirmContentMessage = "Please confirm that this order should be deleted.";
                ConfirmOrderDelete.OpenDialog();
            }
        }

        if (args.Item.Text == "Preview")
        {

            //Code for editing - Check that an Order has been selected from the grid
            if (selectedPOHeaderID == 0)
            {
                WarningHeaderMessage = "Warning!";
                WarningContentMessage = "Please select an Order from the grid.";
                Warning.OpenDialog();
            }
            else
            {
                //NavigationManager.NavigateTo($"/previeworder/");
                //NavigationManager.NavigateTo($"/previeworder/{selectedPOHeaderID}");
                await IJS.InvokeAsync<object>("open", new object[] { "/previeworder/" + selectedPOHeaderID + "", "_blank" });
            }

        }
    }

    public void RowSelectHandler(RowSelectEventArgs<POHeader> args)
    {
        //{args.Data} returns the current selected records.
        selectedPOHeaderID = args.Data.POHeaderID;
    }

    protected async Task ConfirmOrderArchive(bool archiveConfirmed)
    {
        if (archiveConfirmed)
        {
            orderHeader.POHeaderIsArchived = true;
            bool Success = await POHeaderService.POHeaderUpdate(orderHeader);
            poheader = await POHeaderService.POHeaderList();
            StateHasChanged();
        }
    }
}

PreviewOrderPage.razor

@page "/previeworder/{POHeaderID:int}"
@layout BlankLayout


@using BlazorPurchaseOrders.Data;
@inject IPOHeaderService POHeaderService
@inject IPOLineService POLineService

<!DOCTYPE html>
<html>

<body>
    <div class="invoice-box">
        <table>
            <tr class="addressbar">
                <td class="addressbar-left">
                    <img src="https://blazorcode.uk/media/files/blazorcode_logo_small.png" style="width: 100%; max-width: 300px" />
                </td>

                <td class="addressbar-right">
                    blazorcode.uk<br />
                    5 High Street<br />
                    Trumpington <br />
                    TR4A IRS
                </td>
            </tr>
        </table>
        <br />
        <table>
            <tr class="addressbar">
                <td style="width:50%">
                    @orderHeader.SupplierName<br />
                    @if (!String.IsNullOrEmpty(orderHeader.POHeaderSupplierAddress1))
                    {
                        @orderHeader.POHeaderSupplierAddress1<br />
                    }
                    @if (!String.IsNullOrEmpty(orderHeader.POHeaderSupplierAddress2))
                    {
                        @orderHeader.POHeaderSupplierAddress2<br />
                    }
                    @if (!String.IsNullOrEmpty(orderHeader.POHeaderSupplierAddress3))
                    {
                        @orderHeader.POHeaderSupplierAddress3<br />
                    }
                    @orderHeader.POHeaderSupplierPostCode<br />
                </td>
                <td style="width:15%">
                    Order No<br />
                    Order Date<br />
                    Contact
                </td>
                <td style="width:35%">
                    : @orderHeader.POHeaderOrderNumber<br />
                    : @orderHeader.POHeaderOrderDate.ToShortDateString()<br />
                    : @orderHeader.POHeaderRequestedBy
                </td>
            </tr>
        </table>
        <table>
            <tr class="doctype">
                <td>PURCHASE ORDER</td>
            </tr>
        </table>
        <table>
            <tr class="heading">
                <th>Code</th>
                <th>Description</th>
                <th class="column-right">Quantity</th>
                <th class="column-right">Unit Price</th>
                <th class="column-right">Net Price</th>
                <th class="column-right">Tax Rate</th>
                <th class="column-right">Tax</th>
                <th class="column-right">Total</th>
            </tr>
            @foreach (var orderline in orderLines)
            {
                <tr class="item">
                    <td>@orderline.POLineProductCode</td>
                    <td>@orderline.POLineProductDescription</td>
                    <td class="column-right">@String.Format("{0:N0}", orderline.POLineProductQuantity)</td>
                    <td class="column-right">@String.Format("{0:C2}", orderline.POLineProductUnitPrice)</td>
                    <td class="column-right">@String.Format("{0:C2}", orderline.POLineNetPrice)</td>
                    <td class="column-right">@String.Format("{0:P2}", orderline.POLineTaxRate)</td>
                    <td class="column-right">@String.Format("{0:C2}", orderline.POLineTaxAmount)</td>
                    <td class="column-right">@String.Format("{0:C2}", orderline.POLineGrossPrice)</td>
                </tr>
            }
            <tr class="totals">
                <td></td>
                <td class="column-left">Order Total:</td>
                <td></td>
                <td></td>
                <td>@String.Format("{0:C2}", orderHeader.NetPrice)</td>
                <td></td>
                <td>@String.Format("{0:C2}", orderHeader.Tax)</td>
                <td>@String.Format("{0:C2}", orderHeader.TotalOrderValue)</td>
            </tr>
        </table>

    </div>
</body>
</html>

<style>
    .invoice-box {
        max-width: 1000px;
        margin: auto;
        padding: 30px;
        border: 1px solid #eee;
        box-shadow: 0 0 10px rgba(0, 0, 0, 0.15);
        font-size: 16px;
        line-height: 24px;
        font-family: 'Helvetica Neue', 'Helvetica', Helvetica, Arial, sans-serif;
        color: #555;
    }

        .invoice-box table {
            width: 100%;
            line-height: inherit;
            text-align: left;
        }

    .addressbar {
        vertical-align: top;
    }

    .addressbar-left {
        text-align: left;
    }

    .addressbar-right {
        text-align: right;
        font-weight: bold;
        padding-top: 5px;
    }

    .doctype {
        font-size: 20px;
        line-height: 80px;
        color: #333;
        font-weight: bold;
        text-align: center
    }

    .heading {
        background: #eee;
        border-bottom: 1px solid #ddd;
        font-weight: bold;
    }

    .column-left {
        text-align: left;
    }

    .column-right {
        text-align: right;
    }

    .item {
        border-bottom: 1px solid #eee;
    }

    .totals {
        background: #eee;
        font-weight: bold;
        line-height: 40px;
        text-align: right;
    }
</style>

@code {
    IEnumerable<POLine> orderLinesByPOHeader;
    public List<POLine> orderLines = new List<POLine>();
    POHeader orderHeader = new POHeader();

    [Parameter]
    public int POHeaderID { get; set; }

    protected override async Task OnInitializedAsync()
    {
        orderHeader = await POHeaderService.POHeader_GetOne(POHeaderID);
        orderLinesByPOHeader = await POLineService.POLine_GetByPOHeader(POHeaderID);
        orderLines = orderLinesByPOHeader.ToList(); //Convert from IEnumable to List
    }

}

BlankLayout.razor

  @inherits LayoutComponentBase

@Body

SQL

POHeader_GetOne

USE [PurchaseOrders]
GO

/****** Object:  StoredProcedure [dbo].[spPOHeader_GetOne] ******/
DROP PROCEDURE [dbo].[spPOHeader_GetOne]
GO

/****** Object:  StoredProcedure [dbo].[spPOHeader_GetOne] ******/
SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO


--------------  Stored Proc for SELECT (one)
CREATE PROCEDURE [dbo].[spPOHeader_GetOne]
-- Needs one parameter for primary key
@POHeaderID int
AS 
BEGIN
-- SQL Select for one table row
SELECT  dbo.POHeader.POHeaderID, dbo.POHeader.POHeaderOrderNumber, dbo.POHeader.POHeaderOrderDate, dbo.POHeader.POHeaderSupplierID, dbo.POHeader.POHeaderSupplierAddress1, dbo.POHeader.POHeaderSupplierAddress2, dbo.POHeader.POHeaderSupplierAddress3, dbo.POHeader.POHeaderSupplierPostCode, dbo.POHeader.POHeaderSupplierEmail, dbo.POHeader.POHeaderRequestedBy, 
           dbo.POHeader.POHeaderIsArchived, dbo.Supplier.SupplierName, SUM(ISNULL(dbo.POLine.POLineProductQuantity * dbo.POLine.POLineProductUnitPrice, 0)) AS NetPrice, SUM(ISNULL(dbo.POLine.POLineProductQuantity * dbo.POLine.POLineProductUnitPrice * dbo.POLine.POLineTaxRate, 0)) AS Tax, SUM(ISNULL((dbo.POLine.POLineProductQuantity * dbo.POLine.POLineProductUnitPrice) 
           * (1 + dbo.POLine.POLineTaxRate), 0)) AS TotalOrderValue
FROM    dbo.POHeader LEFT OUTER JOIN
           dbo.POLine ON dbo.POHeader.POHeaderID = dbo.POLine.POLineHeaderID LEFT OUTER JOIN
           dbo.Supplier ON dbo.POHeader.POHeaderSupplierID = dbo.Supplier.SupplierID
		   WHERE POHeaderID= @POHeaderID
GROUP BY dbo.POHeader.POHeaderID, dbo.POHeader.POHeaderOrderNumber, dbo.POHeader.POHeaderOrderDate, dbo.POHeader.POHeaderSupplierID, dbo.POHeader.POHeaderSupplierAddress1, dbo.POHeader.POHeaderSupplierAddress2, dbo.POHeader.POHeaderSupplierAddress3, dbo.POHeader.POHeaderSupplierPostCode, dbo.POHeader.POHeaderSupplierEmail, dbo.POHeader.POHeaderRequestedBy, 
           dbo.Supplier.SupplierName, dbo.POHeader.POHeaderIsArchived

END

GO