C#
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();
}
}
}
@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" />
</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 >
@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 >
Order No<br />
Order Date<br />
Contact
</td>
<td >
: @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
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