SQL
ALTER TABLE POHeader ADD [POHeaderGuid] uniqueidentifier NOT NULL DEFAULT NEWID();
USE [PurchaseOrders]
GO
IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[POHeader]') AND type in (N'U'))
ALTER TABLE [dbo].[POHeader] DROP CONSTRAINT IF EXISTS [DF__POHeader__POHead__6C6E1476]
GO
IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[POHeader]') AND type in (N'U'))
ALTER TABLE [dbo].[POHeader] DROP CONSTRAINT IF EXISTS [DF_POHeader_POHeaderIsArchived]
GO
IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[POHeader]') AND type in (N'U'))
ALTER TABLE [dbo].[POHeader] DROP CONSTRAINT IF EXISTS [DF_POHeader_POHeaderOrderNumber]
GO
/****** Object: Table [dbo].[POHeader] Script Date: 13/06/2021 17:54:15 ******/
DROP TABLE IF EXISTS [dbo].[POHeader]
GO
/****** Object: Table [dbo].[POHeader] Script Date: 13/06/2021 17:54:15 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[POHeader](
[POHeaderID] [int] IDENTITY(1,1) NOT NULL,
[POHeaderOrderNumber] [int] NOT NULL,
[POHeaderOrderDate] [datetime] NOT NULL,
[POHeaderSupplierID] [int] NOT NULL,
[POHeaderSupplierAddress1] [nvarchar](50) NULL,
[POHeaderSupplierAddress2] [nvarchar](50) NULL,
[POHeaderSupplierAddress3] [nvarchar](50) NULL,
[POHeaderSupplierPostCode] [nvarchar](10) NULL,
[POHeaderSupplierEmail] [nvarchar](256) NULL,
[POHeaderRequestedBy] [nvarchar](450) NULL,
[POHeaderIsArchived] [bit] NOT NULL,
[POHeaderGuid] [uniqueidentifier] NOT NULL,
CONSTRAINT [PK_POHeader] PRIMARY KEY CLUSTERED
(
[POHeaderID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY]
GO
ALTER TABLE [dbo].[POHeader] ADD CONSTRAINT [DF_POHeader_POHeaderOrderNumber] DEFAULT ((0)) FOR [POHeaderOrderNumber]
GO
ALTER TABLE [dbo].[POHeader] ADD CONSTRAINT [DF_POHeader_POHeaderIsArchived] DEFAULT ((0)) FOR [POHeaderIsArchived]
GO
ALTER TABLE [dbo].[POHeader] ADD DEFAULT (newid()) FOR [POHeaderGuid]
GO
Drop and recreate POHeaderList
USE [PurchaseOrders]
GO
IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[POHeader]') AND type in (N'U'))
ALTER TABLE [dbo].[POHeader] DROP CONSTRAINT IF EXISTS [DF__POHeader__POHead__6C6E1476]
GO
IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[POHeader]') AND type in (N'U'))
ALTER TABLE [dbo].[POHeader] DROP CONSTRAINT IF EXISTS [DF_POHeader_POHeaderIsArchived]
GO
IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[POHeader]') AND type in (N'U'))
ALTER TABLE [dbo].[POHeader] DROP CONSTRAINT IF EXISTS [DF_POHeader_POHeaderOrderNumber]
GO
/****** Object: Table [dbo].[POHeader] Script Date: 13/06/2021 17:54:15 ******/
DROP TABLE IF EXISTS [dbo].[POHeader]
GO
/****** Object: Table [dbo].[POHeader] Script Date: 13/06/2021 17:54:15 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[POHeader](
[POHeaderID] [int] IDENTITY(1,1) NOT NULL,
[POHeaderOrderNumber] [int] NOT NULL,
[POHeaderOrderDate] [datetime] NOT NULL,
[POHeaderSupplierID] [int] NOT NULL,
[POHeaderSupplierAddress1] [nvarchar](50) NULL,
[POHeaderSupplierAddress2] [nvarchar](50) NULL,
[POHeaderSupplierAddress3] [nvarchar](50) NULL,
[POHeaderSupplierPostCode] [nvarchar](10) NULL,
[POHeaderSupplierEmail] [nvarchar](256) NULL,
[POHeaderRequestedBy] [nvarchar](450) NULL,
[POHeaderIsArchived] [bit] NOT NULL,
[POHeaderGuid] [uniqueidentifier] NOT NULL,
CONSTRAINT [PK_POHeader] PRIMARY KEY CLUSTERED
(
[POHeaderID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY]
GO
ALTER TABLE [dbo].[POHeader] ADD CONSTRAINT [DF_POHeader_POHeaderOrderNumber] DEFAULT ((0)) FOR [POHeaderOrderNumber]
GO
ALTER TABLE [dbo].[POHeader] ADD CONSTRAINT [DF_POHeader_POHeaderIsArchived] DEFAULT ((0)) FOR [POHeaderIsArchived]
GO
ALTER TABLE [dbo].[POHeader] ADD DEFAULT (newid()) FOR [POHeaderGuid]
GO
USE [PurchaseOrders]
GO
/****** Object: StoredProcedure [dbo].[spPOHeader_GetOneByGuid] Script Date: 13/06/2021 17:56:43 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
-------------- Stored Proc for SELECT (one)
CREATE PROCEDURE [dbo].[spPOHeader_GetOneByGuid]
-- Needs one parameter for primary key
@POHeaderGuid uniqueidentifier
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 POHeaderGuid= @POHeaderGuid
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
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 System.Guid POHeaderGuid { get; set; }
public string SupplierName { get; }
public decimal TotalOrderValue { get; }
public decimal NetPrice { get; }
public decimal Tax { get; }
}
}
using Dapper;
using Microsoft.Data.SqlClient;
using System;
using System.Collections.Generic;
using System.Data;
using System.Threading.Tasks;
namespace BlazorPurchaseOrders.Data
{
public class POHeaderService : IPOHeaderService
{
// Database connection
private readonly SqlConnectionConfiguration _configuration;
public POHeaderService(SqlConnectionConfiguration configuration)
{
_configuration = configuration;
}
// Add (create) a POHeader table row (SQL Insert)
public async Task<int> POHeaderInsert(
DateTime POHeaderOrderDate,
int POHeaderSupplierID,
string POHeaderSupplierAddress1,
string POHeaderSupplierAddress2,
string POHeaderSupplierAddress3,
string POHeaderSupplierPostCode,
string POHeaderSupplierEmail,
string POHeaderRequestedBy)
{
int newHeaderID = 0;
using (var conn = new SqlConnection(_configuration.Value))
{
var parameters = new DynamicParameters();
parameters.Add("POHeaderOrderDate", POHeaderOrderDate, DbType.Date);
parameters.Add("POHeaderSupplierID", POHeaderSupplierID, DbType.Int32);
parameters.Add("POHeaderSupplierAddress1", POHeaderSupplierAddress1, DbType.String);
parameters.Add("POHeaderSupplierAddress2", POHeaderSupplierAddress2, DbType.String);
parameters.Add("POHeaderSupplierAddress3", POHeaderSupplierAddress3, DbType.String);
parameters.Add("POHeaderSupplierPostCode", POHeaderSupplierPostCode, DbType.String);
parameters.Add("POHeaderSupplierEmail", POHeaderSupplierEmail, DbType.String);
parameters.Add("POHeaderRequestedBy", POHeaderRequestedBy, DbType.String);
parameters.Add("@Output", DbType.Int32, direction: ParameterDirection.Output);
// Stored procedure method
await conn.ExecuteAsync("spPOHeader_Insert", parameters, commandType: CommandType.StoredProcedure);
newHeaderID = parameters.Get<int>("@Output");
};
return newHeaderID;
}
// Get a list of poheader rows (SQL Select)
public async Task<IEnumerable<POHeader>> POHeaderList(string @UserName)
{
IEnumerable<POHeader> poheaders;
var parameters = new DynamicParameters();
parameters.Add("@UserName", UserName);
using (var conn = new SqlConnection(_configuration.Value))
{
poheaders = await conn.QueryAsync<POHeader>("spPOHeader_List", parameters, commandType: CommandType.StoredProcedure);
}
return poheaders;
}
// Get one poheader based on its POHeaderID (SQL Select)
// This only works if you're already created the stored procedure.
public async Task<POHeader> POHeader_GetOne(int @POHeaderID)
{
POHeader poheader = new POHeader();
var parameters = new DynamicParameters();
parameters.Add("@POHeaderID", POHeaderID, DbType.Int32);
using (var conn = new SqlConnection(_configuration.Value))
{
poheader = await conn.QueryFirstOrDefaultAsync<POHeader>("spPOHeader_GetOne", parameters, commandType: CommandType.StoredProcedure);
}
return poheader;
}
public async Task<POHeader> POHeader_GetOneByGuid(Guid @POHeaderGuid)
{
POHeader poheader = new POHeader();
var parameters = new DynamicParameters();
parameters.Add("@POHeaderGuid", POHeaderGuid, DbType.Guid);
using (var conn = new SqlConnection(_configuration.Value))
{
poheader = await conn.QueryFirstOrDefaultAsync<POHeader>("spPOHeader_GetOneByGuid", parameters, commandType: CommandType.StoredProcedure);
}
return poheader;
}
// Update one POHeader row based on its POHeaderID (SQL Update)
// This only works if you're already created the stored procedure.
public async Task<bool> POHeaderUpdate(POHeader poheader)
{
using (var conn = new SqlConnection(_configuration.Value))
{
var parameters = new DynamicParameters();
parameters.Add("POHeaderID", poheader.POHeaderID, DbType.Int32);
parameters.Add("POHeaderOrderNumber", poheader.POHeaderOrderNumber, DbType.Int32);
parameters.Add("POHeaderOrderDate", poheader.POHeaderOrderDate, DbType.Date);
parameters.Add("POHeaderSupplierID", poheader.POHeaderSupplierID, DbType.Int32);
parameters.Add("POHeaderSupplierAddress1", poheader.POHeaderSupplierAddress1, DbType.String);
parameters.Add("POHeaderSupplierAddress2", poheader.POHeaderSupplierAddress2, DbType.String);
parameters.Add("POHeaderSupplierAddress3", poheader.POHeaderSupplierAddress3, DbType.String);
parameters.Add("POHeaderSupplierPostCode", poheader.POHeaderSupplierPostCode, DbType.String);
parameters.Add("POHeaderSupplierEmail", poheader.POHeaderSupplierEmail, DbType.String);
parameters.Add("POHeaderRequestedBy", poheader.POHeaderRequestedBy, DbType.String);
parameters.Add("POHeaderIsArchived", poheader.POHeaderIsArchived, DbType.Boolean);
await conn.ExecuteAsync("spPOHeader_Update", parameters, commandType: CommandType.StoredProcedure);
}
return true;
}
}
}
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
namespace BlazorPurchaseOrders.Data
{
// Each item below provides an interface to a method in POHeaderServices.cs
public interface IPOHeaderService
{
Task<int> POHeaderInsert(
DateTime POHeaderOrderDate,
int POHeaderSupplierID,
string POHeaderSupplierAddress1,
string POHeaderSupplierAddress2,
string POHeaderSupplierAddress3,
string POHeaderSupplierPostCode,
string POHeaderSupplierEmail,
string POHeaderRequestedBy
);
Task<IEnumerable<POHeader>> POHeaderList(string @UserName);
Task<POHeader> POHeader_GetOne(int POHeaderID);
Task<POHeader> POHeader_GetOneByGuid(Guid POHeaderGuid);
Task<bool> POHeaderUpdate(POHeader poheader);
}
}
Index.razor
@page "/"
@using BlazorPurchaseOrders.Data
@inject IPOHeaderService POHeaderService
@inject NavigationManager NavigationManager
@inject IJSRuntime IJS
@attribute [Microsoft.AspNetCore.Authorization.AllowAnonymous]
@inject AuthenticationStateProvider AuthenticationStateProvider
<div class="col-sm-12">
<AuthorizeView>
<NotAuthorized>
<h5>Please Log in</h5>
<h6>or</h6>
<h5>Register to use Blazor Purchase Orders</h5>
</NotAuthorized>
<Authorized>
<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" />
</Authorized>
</AuthorizeView>
</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;
private Guid selectedPOHeaderGuid { get; set; }
WarningPage Warning;
string WarningHeaderMessage = "";
string WarningContentMessage = "";
ConfirmPage ConfirmOrderDelete;
string ConfirmHeaderMessage = "";
string ConfirmContentMessage = "";
public bool ConfirmationChanged { get; set; } = false;
[CascadingParameter]
private Task<AuthenticationState> authenticationStateTask { get; set; }
protected override async Task OnInitializedAsync()
{
//Populate the list of orders objects from the Purchase Order Header table.
await GetOrderList();
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/{Guid.Empty}");
}
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/{selectedPOHeaderGuid}");
}
}
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
{
await IJS.InvokeAsync<object>("open", new object[] { "/previeworder/" + selectedPOHeaderGuid + "", "_blank" });
}
}
}
public void RowSelectHandler(RowSelectEventArgs<POHeader> args)
{
//{args.Data} returns the current selected records.
selectedPOHeaderID = args.Data.POHeaderID;
selectedPOHeaderGuid = args.Data.POHeaderGuid;
}
protected async Task ConfirmOrderArchive(bool archiveConfirmed)
{
if (archiveConfirmed)
{
orderHeader.POHeaderIsArchived = true;
bool Success = await POHeaderService.POHeaderUpdate(orderHeader);
await GetOrderList();
StateHasChanged();
}
}
protected async Task GetOrderList()
{
var user = (await authenticationStateTask).User;
if (user.IsInRole("Admin") || user.IsInRole("Manager"))
{
poheader = await POHeaderService.POHeaderList(null); //leave user name blank
}
else
{
poheader = await POHeaderService.POHeaderList(user.Identity.Name); //pass user name
}
}
}
@page "/previeworder/{POHeaderGuid:guid}"
@layout BlankLayout
@using BlazorPurchaseOrders.Data;
@inject IPOHeaderService POHeaderService
@inject IPOLineService POLineService
@attribute [Microsoft.AspNetCore.Authorization.AllowAnonymous]
<!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();
public int POHeaderID { get; set; }
[Parameter]
public Guid POHeaderGuid { get; set; }
protected override async Task OnInitializedAsync()
{
orderHeader = await POHeaderService.POHeader_GetOneByGuid(POHeaderGuid);
POHeaderID = orderHeader.POHeaderID;
orderLinesByPOHeader = await POLineService.POLine_GetByPOHeader(POHeaderID);
orderLines = orderLinesByPOHeader.ToList(); //Convert from IEnumable to List
}
}
@page "/purchaseorder/{POHeaderGuid:guid}"
@using BlazorPurchaseOrders.Data
@inject NavigationManager NavigationManager
@inject ISupplierService SupplierService
@inject IPOHeaderService POHeaderService
@inject IPOLineService POLineService
@inject IProductService ProductService
@inject ITaxService TaxService
@using Microsoft.AspNetCore.Components.Authorization
@inject AuthenticationStateProvider AuthenticationStateProvider
@using System
@using System.Collections.Generic
<h3>@pagetitle</h3>
<EditForm Model="@orderaddedit" OnValidSubmit="@OrderSave">
<DataAnnotationsValidator />
<div class="grid-container">
<div class="grid-child left-column">
<SfDropDownList DataSource="@supplier"
TItem="Supplier"
TValue="int"
Text="SupplierID"
@bind-Value="orderaddedit.POHeaderSupplierID"
FloatLabelType="@FloatLabelType.Auto"
Placeholder="Select a Supplier"
Enabled="@supplierEnabled">
<DropDownListFieldSettings Text="SupplierName" Value="SupplierID"></DropDownListFieldSettings>
<DropDownListEvents TItem="Supplier" TValue="int" ValueChange="OnChangeSupplier"></DropDownListEvents>
</SfDropDownList>
<SfTextBox Enabled="true" Placeholder="Address"
FloatLabelType="@FloatLabelType.Always"
@bind-Value="orderaddedit.POHeaderSupplierAddress1"></SfTextBox>
<ValidationMessage For="@(() => orderaddedit.POHeaderSupplierAddress1)" />
<SfTextBox Enabled="true" Placeholder=""
FloatLabelType="@FloatLabelType.Never"
@bind-Value="orderaddedit.POHeaderSupplierAddress2"></SfTextBox>
<ValidationMessage For="@(() => orderaddedit.POHeaderSupplierAddress2)" />
<SfTextBox Enabled="true" Placeholder=""
FloatLabelType="@FloatLabelType.Never"
@bind-Value="orderaddedit.POHeaderSupplierAddress3"></SfTextBox>
<ValidationMessage For="@(() => orderaddedit.POHeaderSupplierAddress3)" />
<SfTextBox Enabled="true" Placeholder="Post Code"
FloatLabelType="@FloatLabelType.Never"
@bind-Value="orderaddedit.POHeaderSupplierPostCode"></SfTextBox>
<ValidationMessage For="@(() => orderaddedit.POHeaderSupplierPostCode)" />
<SfTextBox Enabled="true" Placeholder="Email"
FloatLabelType="@FloatLabelType.Auto"
@bind-Value="orderaddedit.POHeaderSupplierEmail"></SfTextBox>
<ValidationMessage For="@(() => orderaddedit.POHeaderSupplierEmail)" />
</div>
<div class="grid-child right-column">
<SfNumericTextBox Enabled="false" Placeholder="Order No"
FloatLabelType="@FloatLabelType.Always"
ShowSpinButton="false"
@bind-Value="orderaddedit.POHeaderOrderNumber"></SfNumericTextBox>
<SfDatePicker TValue="DateTime"
Placeholder='Order Date'
FloatLabelType="@FloatLabelType.Auto"
@bind-Value="orderaddedit.POHeaderOrderDate"></SfDatePicker>
<SfTextBox Enabled="false" Placeholder="Requested by"
FloatLabelType="@FloatLabelType.Always"
@bind-Value="orderaddedit.POHeaderRequestedBy"></SfTextBox>
</div>
</div>
<br />
<SfGrid @ref="OrderLinesGrid"
DataSource="@orderLines"
Toolbar="@Toolbaritems"
AllowResizing="true">
<GridColumns>
<GridColumn Field="@nameof(POLine.POLineProductCode)"
HeaderText="Product"
TextAlign="@TextAlign.Left"
Width="20">
</GridColumn>
<GridColumn Field="@nameof(POLine.POLineProductDescription)"
HeaderText="Description"
TextAlign="@TextAlign.Left"
Width="30">
</GridColumn>
<GridColumn Field="@nameof(POLine.POLineProductQuantity)"
HeaderText="Quantity"
TextAlign="@TextAlign.Right"
Format="n0"
Width="10">
</GridColumn>
<GridColumn Field="@nameof(POLine.POLineProductUnitPrice)"
HeaderText="Unit Price"
TextAlign="@TextAlign.Right"
Format="C2"
Width="10">
</GridColumn>
<GridColumn Field="@nameof(POLine.POLineNetPrice)"
HeaderText="Net Price"
TextAlign="@TextAlign.Right"
Format="C2"
Width="10">
</GridColumn>
<GridColumn Field="@nameof(POLine.POLineTaxRate)"
HeaderText="Tax Rate"
TextAlign="@TextAlign.Right"
Format="p2"
Width="10">
</GridColumn>
<GridColumn Field="@nameof(POLine.POLineTaxAmount)"
HeaderText="Tax"
TextAlign="@TextAlign.Right"
Format="C2"
Width="10">
</GridColumn>
<GridColumn Field="@nameof(POLine.POLineGrossPrice)"
HeaderText="Total"
TextAlign="@TextAlign.Right"
Format="C2"
Width="10">
</GridColumn>
</GridColumns>
<GridAggregates>
<GridAggregate>
<GridAggregateColumns>
<GridAggregateColumn Field=@nameof(POLine.POLineNetPrice) Type="AggregateType.Sum" Format="C2">
<FooterTemplate Context="NetContext">
@{
var aggregate = NetContext as AggregateTemplateContext;
<div>
<p>@aggregate.Sum</p>
</div>
}
</FooterTemplate>
</GridAggregateColumn>
<GridAggregateColumn Field=@nameof(POLine.POLineTaxAmount) Type="AggregateType.Sum" Format="C2">
<FooterTemplate Context="TaxContext">
@{
var aggregate = TaxContext as AggregateTemplateContext;
<div>
<p>@aggregate.Sum</p>
</div>
}
</FooterTemplate>
</GridAggregateColumn>
<GridAggregateColumn Field=@nameof(POLine.POLineGrossPrice) Type="AggregateType.Sum" Format="C2">
<FooterTemplate Context="GrossContext">
@{
var aggregate = GrossContext as AggregateTemplateContext;
<div>
<p>@aggregate.Sum</p>
</div>
}
</FooterTemplate>
</GridAggregateColumn>
</GridAggregateColumns>
</GridAggregate>
</GridAggregates>
<GridEvents RowSelected="RowSelectHandler" OnToolbarClick="ToolbarClickHandler" TValue="POLine"></GridEvents>
</SfGrid>
<br />
<div class="e-footer-content" style="text-align: right; width: 100%;">
<div class="button-container">
<button type="submit" class="e-btn e-normal e-primary">Save</button>
<button type="button" class="e-btn e-normal" @onclick="@Cancel">Cancel</button>
</div>
</div>
</EditForm>
<SfDialog @ref="DialogAddEditOrderLine" IsModal="true" Width="600px" ShowCloseIcon="true" Visible="false">
<DialogTemplates>
<Header> @dialogHeaderText </Header>
</DialogTemplates>
<EditForm Model="@addeditOrderLine" OnValidSubmit="@OrderLineSave">
<DataAnnotationsValidator />
<div class=flex-container>
<SfDropDownList DataSource="@product"
TItem="Product"
TValue="int"
Text="ProductID"
@bind-Value="addeditOrderLine.POLineProductID"
FloatLabelType="@FloatLabelType.Always"
Placeholder="Select a Product"
Enabled="true">
<DropDownListTemplates TItem="Product">
<HeaderTemplate>
<span class='head'>
<span class='productcode'>Code</span>
<span class='description'>Description</span>
</span>
</HeaderTemplate>
<ItemTemplate Context="contextName">
<span class='item'>
<span class='productcode'>@((contextName as Product).ProductCode)</span>
<span class='description'>@((contextName as Product).ProductDescription)</span>
</span>
</ItemTemplate>
</DropDownListTemplates>
<DropDownListFieldSettings Text="ProductCode" Value="ProductID"></DropDownListFieldSettings>
<DropDownListEvents TItem="Product" TValue="int" OnValueSelect="OnChangeProduct"></DropDownListEvents>
</SfDropDownList>
</div>
<div class=flex-container>
<SfTextBox Enabled="true" Placeholder="Product Description"
FloatLabelType="@FloatLabelType.Always"
@bind-Value="addeditOrderLine.POLineProductDescription"></SfTextBox>
</div>
<div class=flex-container>
<ValidationMessage For="@(() => addeditOrderLine.POLineProductDescription)" />
</div><div class=flex-container>
<SfNumericTextBox Enabled="true" Placeholder="Quantity"
FloatLabelType="@FloatLabelType.Always"
ShowSpinButton="false"
Format="n0"
Decimals="0"
ValidateDecimalOnType="true"
CssClass="e-style"
@bind-Value="addeditOrderLine.POLineProductQuantity"
@onfocusout='@POLineCalc'>
</SfNumericTextBox>
<SfNumericTextBox Enabled="true" Placeholder="Unit Price"
FloatLabelType="@FloatLabelType.Always"
ShowSpinButton="false"
Format="c2"
Decimals="2"
ValidateDecimalOnType="true"
CssClass="e-style"
@bind-Value="addeditOrderLine.POLineProductUnitPrice"
@onfocusout='@POLineCalc'>
</SfNumericTextBox>
<SfNumericTextBox Enabled="false" Placeholder="Net Price"
FloatLabelType="@FloatLabelType.Always"
ShowSpinButton="false"
Format="c2"
EnableRtl="true"
@bind-Value="addeditOrderLine.POLineNetPrice">
</SfNumericTextBox>
</div>
<div class=flex-container>
<SfDropDownList DataSource="@tax"
TItem="Tax"
TValue="int"
Text="TaxID"
@bind-Value="addeditOrderLine.POLineTaxID"
FloatLabelType="@FloatLabelType.Always"
Placeholder="Tax Rate"
Enabled="true">
<DropDownListFieldSettings Text="TaxDescription" Value="TaxID"></DropDownListFieldSettings>
<DropDownListEvents TItem="Tax" TValue="int" OnValueSelect="OnChangeTax"></DropDownListEvents>
</SfDropDownList>
<SfNumericTextBox Enabled="false" Placeholder="Tax Rate %"
FloatLabelType="@FloatLabelType.Always"
ShowSpinButton="false"
Format="p2"
EnableRtl="true"
@bind-Value="addeditOrderLine.POLineTaxRate">
</SfNumericTextBox>
<SfNumericTextBox Enabled="false" Placeholder="Tax Amount"
FloatLabelType="@FloatLabelType.Always"
ShowSpinButton="false"
Format="c2"
EnableRtl="true"
@bind-Value="addeditOrderLine.POLineTaxAmount">
</SfNumericTextBox>
</div>
<div class=flex-container>
<SfNumericTextBox Enabled="false" Placeholder="Total Price"
FloatLabelType="@FloatLabelType.Always"
ShowSpinButton="false"
Format="c2"
EnableRtl="true"
@bind-Value="addeditOrderLine.POLineGrossPrice">
</SfNumericTextBox>
</div>
<br />
<div class="e-footer-content">
<div class="button-container">
<button type="submit" class="e-btn e-normal e-primary">Save</button>
<button type="button" class="e-btn e-normal" @onclick="@CloseDialog">Cancel</button>
</div>
</div>
</EditForm>
</SfDialog>
<ConfirmPage @ref="ConfirmDeletion" ConfirmHeaderMessage="@ConfirmHeaderMessage" ConfirmContentMessage="@ConfirmContentMessage" ConfirmationChanged="ConfirmDelete" />
<WarningPage @ref="Warning" WarningHeaderMessage="@WarningHeaderMessage" WarningContentMessage="@WarningContentMessage" />
<ConfirmPage @ref="ConfirmSaveOrder" ConfirmHeaderMessage="@ConfirmHeaderMessage" ConfirmContentMessage="@ConfirmContentMessage" ConfirmationChanged="OrderSaveProcess" />
<style>
.grid-container {
display: grid;
max-width: 900px; /* Maximum width of the whole container - in this case both columns */
grid-template-columns: 1fr 1fr; /* Relative width of each column (1fr 1fr is equivalent to, say, 33fr 33fr */
grid-gap: 75px; /* size of the gap between columns */
}
.flex-container {
display: flex;
flex-direction: row; /* Causes tab to move along row and then onto following row */
justify-content: space-evenly; /* Equal space left and right margin and between elements */
margin: 10px; /* This appears to be vertical margin between rows */
column-gap: 10px; /* Tgap betwen columns */
}
.e-numeric.e-style .e-control.e-numerictextbox {
text-align: right;
padding: 0px 5px 0px 0px;
}
.head, .item {
display: table;
width: 100%;
margin: auto;
text-align: left;
}
.head {
height: 30px;
font-size: 15px;
font-weight: 600;
}
.productcode {
display: table-cell;
vertical-align: middle;
text-align: left;
width: 25%;
}
.description {
display: table-cell;
vertical-align: middle;
text-align: left;
width: 75%;
}
.head .productcode {
text-indent: 17px;
}
.head .description {
text-indent: 14px;
}
</style>
@code {
POHeader orderaddedit = new POHeader();
IEnumerable<Supplier> supplier;
IEnumerable<Product> product;
IEnumerable<Tax> tax;
IEnumerable<POLine> orderLinesByPOHeader;
string pagetitle = "";
string dialogHeaderText = "";
private string UserName;
SfGrid<POLine> OrderLinesGrid;
public List<POLine> orderLines = new List<POLine>();
private List<ItemModel> Toolbaritems = new List<ItemModel>();
private List<int> OrderLinesToBeDeleted = new List<int>();
SfDialog DialogAddEditOrderLine;
public POLine addeditOrderLine = new POLine();
WarningPage Warning;
string WarningHeaderMessage = "";
string WarningContentMessage = "";
ConfirmPage ConfirmDeletion;
ConfirmPage ConfirmSaveOrder;
string ConfirmHeaderMessage = "";
string ConfirmContentMessage = "";
public bool ConfirmationChanged { get; set; } = false;
public bool supplierEnabled { get; set; } = true;
private int tmpPOLineID { get; set; } = 0;
private int selectedPOLineID { get; set; } = 0;
private int POHeaderID { get; set; } = 0;
[Parameter]
public Guid POHeaderGuid { get; set; }
//Executes on page open, sets headings and gets data in the case of edit
protected override async Task OnInitializedAsync()
{
supplier = await SupplierService.SupplierList();
orderaddedit.POHeaderOrderDate = DateTime.Now;
tax = await TaxService.TaxList();
if (POHeaderGuid == Guid.Empty)
{
pagetitle = "Add an Order";
//Get user if logged in and populate the 'Requested by' column
var authState = await AuthenticationStateProvider.GetAuthenticationStateAsync();
var user = authState.User;
if (user.Identity.IsAuthenticated)
{
UserName = user.Identity.Name;
}
else
{
UserName = "The user is NOT authenticated.";
}
orderaddedit.POHeaderRequestedBy = UserName;
}
else
{
pagetitle = "Edit an Order";
orderaddedit = await POHeaderService.POHeader_GetOneByGuid(POHeaderGuid);
POHeaderID = orderaddedit.POHeaderID;
orderLinesByPOHeader = await POLineService.POLine_GetByPOHeader(POHeaderID);
orderLines = orderLinesByPOHeader.ToList(); //Convert from IEnumable to List
supplierEnabled = false;
}
Toolbaritems.Add(new ItemModel() { Text = "Add", TooltipText = "Add a new order line", PrefixIcon = "e-add" });
Toolbaritems.Add(new ItemModel() { Text = "Edit", TooltipText = "Edit selected order line", PrefixIcon = "e-edit" });
Toolbaritems.Add(new ItemModel() { Text = "Delete", TooltipText = "Delete selected order line", PrefixIcon = "e-delete" });
}
private void OnChangeSupplier(Syncfusion.Blazor.DropDowns.ChangeEventArgs<int, Supplier> args)
{
this.orderaddedit.POHeaderSupplierAddress1 = args.ItemData.SupplierAddress1;
this.orderaddedit.POHeaderSupplierAddress2 = args.ItemData.SupplierAddress2;
this.orderaddedit.POHeaderSupplierAddress3 = args.ItemData.SupplierAddress3;
this.orderaddedit.POHeaderSupplierPostCode = args.ItemData.SupplierPostCode;
this.orderaddedit.POHeaderSupplierEmail = args.ItemData.SupplierEmail;
}
// Executes OnValidSubmit of EditForm above
protected async Task OrderSave()
{
if (orderaddedit.POHeaderSupplierID == 0)
{
WarningHeaderMessage = "Warning!";
WarningContentMessage = "Please Select a Supplier before saving the order.";
Warning.OpenDialog();
return;
}
if (orderLines.Count == 0)
{
ConfirmHeaderMessage = "Confirm Save!";
ConfirmContentMessage = "There are no order lines. Please confirm order should be saved.";
ConfirmSaveOrder.OpenDialog();
}
else
{
await OrderSaveProcess(true);
}
}
//Executes if user clicks the Cancel button.
void Cancel()
{
NavigationManager.NavigateTo("/");
}
public async Task ToolbarClickHandler(Syncfusion.Blazor.Navigations.ClickEventArgs args)
{
//Refresh product to select only those products for this supplier (and products with null suppliers)
product = await ProductService.ProductListBySupplier(orderaddedit.POHeaderSupplierID);
if (args.Item.Text == "Add")
{
//Code for adding goes here
dialogHeaderText = "Add an Order Line";
//Check that a supplier has been selected from the drop-down list
if (orderaddedit.POHeaderSupplierID == 0)
{
WarningHeaderMessage = "Warning!";
WarningContentMessage = "Please Select a Supplier before adding order lines.";
Warning.OpenDialog();
}
else
{
addeditOrderLine = new POLine(); // Ensures a blank form when adding
addeditOrderLine.POLineNetPrice = 0;
addeditOrderLine.POLineTaxID = 0;
addeditOrderLine.POLineProductID = 0;
await this.DialogAddEditOrderLine.Show();
}
}
if (args.Item.Text == "Edit")
{
dialogHeaderText = "Edit an Order Line";
//Check that an order line has been selected
if (selectedPOLineID == 0)
{
WarningHeaderMessage = "Warning!";
WarningContentMessage = "Please select an Order Line from the grid.";
Warning.OpenDialog();
}
else
{
//populate addeditOrderLine (temporary data set used for the editing process)
addeditOrderLine = orderLines.Where(x => x.POLineID == selectedPOLineID).FirstOrDefault();
StateHasChanged();
await this.DialogAddEditOrderLine.Show();
}
}
if (args.Item.Text == "Delete")
{
//Code for adding goes here
if (selectedPOLineID == 0)
{
WarningHeaderMessage = "Warning!";
WarningContentMessage = "Please select an Order Line from the grid.";
Warning.OpenDialog();
}
else
{
ConfirmHeaderMessage = "Confirm Deletion";
ConfirmContentMessage = "Please confirm that this order line should be deleted.";
ConfirmDeletion.OpenDialog();
}
}
}
private async Task OrderLineSave()
{
if (addeditOrderLine.POLineID == 0)
{
//Code to save new order line goes here
//Check that a product has been selected from the drop-down list
if (addeditOrderLine.POLineProductCode == null || addeditOrderLine.POLineProductCode == "")
{
WarningHeaderMessage = "Warning!";
WarningContentMessage = "Please select a Product.";
Warning.OpenDialog();
}
//And check that a tax rate has been selected from the drop-down list
else if (addeditOrderLine.POLineTaxID == 0)
{
WarningHeaderMessage = "Warning!";
WarningContentMessage = "Please select a Tax Rate.";
Warning.OpenDialog();
}
else
{
POLineCalc();
tmpPOLineID = tmpPOLineID - 1; //used to provide a temporary ID for POLineID
orderLines.Add(new POLine
{
POLineID = tmpPOLineID,
POLineHeaderID = 0,
POLineProductID = addeditOrderLine.POLineProductID,
POLineProductCode = addeditOrderLine.POLineProductCode,
POLineProductDescription = addeditOrderLine.POLineProductDescription,
POLineProductQuantity = addeditOrderLine.POLineProductQuantity,
POLineProductUnitPrice = addeditOrderLine.POLineProductUnitPrice,
POLineNetPrice = addeditOrderLine.POLineNetPrice,
POLineTaxRate = addeditOrderLine.POLineTaxRate,
POLineTaxAmount = addeditOrderLine.POLineTaxAmount,
POLineGrossPrice = addeditOrderLine.POLineGrossPrice,
POLineTaxID = addeditOrderLine.POLineTaxID
});
OrderLinesGrid.Refresh();
StateHasChanged(); //<----- THIS IS ABSOLUTELY ESSENTIAL
//addeditOrderLine = new POLine(); //<----- THIS gives errors (nulls)
addeditOrderLine.POLineProductID = 0;
addeditOrderLine.POLineProductCode = "";
addeditOrderLine.POLineProductDescription = "";
addeditOrderLine.POLineProductQuantity = 0;
addeditOrderLine.POLineProductUnitPrice = 0;
addeditOrderLine.POLineNetPrice = 0;
//addeditOrderLine.POLineTaxID = 0; //Leave - highly likely to be same as previous record
//addeditOrderLine.POLineTaxRate = 0; //Leave - highly likely to be same as previous record
addeditOrderLine.POLineTaxAmount = 0;
addeditOrderLine.POLineGrossPrice = 0;
//We now have order lines, so prevent user from changing the supplier
supplierEnabled = false;
}
}
else
//An order line is being edited
//Check that a product has been selected from the drop-down list
if (addeditOrderLine.POLineProductCode == null || addeditOrderLine.POLineProductCode == "")
{
WarningHeaderMessage = "Warning!";
WarningContentMessage = "Please select a Product.";
Warning.OpenDialog();
}
//And check that a tax rate has been selected from the drop-down list
else if (addeditOrderLine.POLineTaxID == 0)
{
WarningHeaderMessage = "Warning!";
WarningContentMessage = "Please select a Tax Rate.";
Warning.OpenDialog();
}
else
{
OrderLinesGrid.Refresh();
StateHasChanged(); //<----- THIS IS ABSOLUTELY ESSENTIAL
await CloseDialog(); //No need to keep dialog open
}
}
private async Task CloseDialog()
{
await this.DialogAddEditOrderLine.Hide();
}
private void OnChangeProduct(Syncfusion.Blazor.DropDowns.SelectEventArgs<Product> args)
{
this.addeditOrderLine.POLineProductCode = args.ItemData.ProductCode;
this.addeditOrderLine.POLineProductDescription = args.ItemData.ProductDescription;
this.addeditOrderLine.POLineProductUnitPrice = args.ItemData.ProductUnitPrice;
POLineCalc();
}
private void OnChangeTax(Syncfusion.Blazor.DropDowns.SelectEventArgs<Tax> args)
{
// int testTaxId = args.ItemData.TaxID;
this.addeditOrderLine.POLineTaxRate = args.ItemData.TaxRate;
POLineCalc();
}
private void POLineCalc()
{
addeditOrderLine.POLineNetPrice = addeditOrderLine.POLineProductUnitPrice * addeditOrderLine.POLineProductQuantity;
addeditOrderLine.POLineTaxAmount = addeditOrderLine.POLineNetPrice.Value * addeditOrderLine.POLineTaxRate;
addeditOrderLine.POLineGrossPrice = addeditOrderLine.POLineNetPrice.Value * (1 + addeditOrderLine.POLineTaxRate);
}
public void RowSelectHandler(RowSelectEventArgs<POLine> args)
{
//{args.Data} returns the current selected records.
selectedPOLineID = args.Data.POLineID;
}
private void OrderLineDelete()
{
if (selectedPOLineID > 0)
{
//Order line has already been saved to the database, and was present at start of this order edit
//Add to list of orders to be deleted when order is saved
OrderLinesToBeDeleted.Add(selectedPOLineID);
}
//And then delete from orderLines
var itemToRemove = orderLines.Single(x => x.POLineID == selectedPOLineID);
orderLines.Remove(itemToRemove);
OrderLinesGrid.Refresh();
}
protected void ConfirmDelete(bool deleteConfirmed)
{
if (deleteConfirmed)
{
OrderLineDelete();
StateHasChanged();
selectedPOLineID = 0;
}
}
protected async Task OrderSaveProcess(bool saveConfirmed)
{
if (saveConfirmed)
{
if (POHeaderID == 0)
{
//Save the record - 1st - the POHeader
int HeaderID = await POHeaderService.POHeaderInsert(
orderaddedit.POHeaderOrderDate,
orderaddedit.POHeaderSupplierID,
orderaddedit.POHeaderSupplierAddress1,
orderaddedit.POHeaderSupplierAddress2,
orderaddedit.POHeaderSupplierAddress3,
orderaddedit.POHeaderSupplierPostCode,
orderaddedit.POHeaderSupplierEmail,
orderaddedit.POHeaderRequestedBy
);
//2nd - the POLines
foreach (var individualPOLine in orderLines)
{
individualPOLine.POLineHeaderID = HeaderID;
bool Success = await POLineService.POLineInsert(individualPOLine);
}
NavigationManager.NavigateTo("/");
}
else
{
//Order is being edited
//POHeader
bool Success = await POHeaderService.POHeaderUpdate(orderaddedit);
//POLines
foreach (var individualPOLine in orderLines)
{
//If POLineHeaderID is positive it means it has been edited during the edit of this order
if (individualPOLine.POLineID > 0)
{
Success = await POLineService.POLineUpdate(individualPOLine);
}
else
//If POLineID is negative it means it has been added during the edit of this order
{
individualPOLine.POLineHeaderID = POHeaderID;
Success = await POLineService.POLineInsert(individualPOLine);
}
}
foreach (var individualPOLine in OrderLinesToBeDeleted)
{
Success = await POLineService.POLineDeleteOne(individualPOLine);
}
//Clear the list of POLines to be deleted
OrderLinesToBeDeleted.Clear();
NavigationManager.NavigateTo("/");
}
}
}
}