Products and sales pages complete #12
Merged
barhen
merged 1 commits from BISK2023-4-item-search-feature
into dev
2 years ago
62 changed files with 2539 additions and 231 deletions
@ -0,0 +1,26 @@ |
|||
using Microsoft.JSInterop; |
|||
|
|||
namespace Biskilog_Accounting.Client.Elements |
|||
{ |
|||
public partial class Headbar |
|||
{ |
|||
protected override void OnInitialized() |
|||
{ |
|||
m_searchService.ClearTextBox += ClearTextBox; |
|||
base.OnInitialized(); |
|||
} |
|||
|
|||
private void ClearTextBox() |
|||
{ |
|||
ClearInputField("mainSearch"); |
|||
} |
|||
private async Task ClearInputField(string elementId) |
|||
{ |
|||
await JSRuntime.InvokeVoidAsync("eval", $"document.getElementById('{elementId}').value = ''"); |
|||
} |
|||
private void SearchInput(string a_key) |
|||
{ |
|||
m_searchService.PerformSearch(a_key); |
|||
} |
|||
} |
|||
} |
@ -0,0 +1,19 @@ |
|||
@page "/products/brands" |
|||
@using Biskilog_Accounting.Shared.Interfaces; |
|||
@using Biskilog_Accounting.Shared.POSModels; |
|||
@inject IProduct m_productRepo |
|||
@inject ContextMenuService ContextMenuService |
|||
@inject DialogService m_dialogService |
|||
@inject ISearchService m_searchControl |
|||
@implements IDisposable |
|||
|
|||
<div class="row" style="display:grid;justify-content:space-between;padding: 5px;margin-right:10px;"> |
|||
<h3>Product Brands</h3> |
|||
</div> |
|||
<RadzenDataGrid AllowPaging="true" PageSize="50" AllowSorting="true" Data="@m_brands" TItem="Tblbrand" GridLines="DataGridGridLines.Horizontal"> |
|||
<Columns> |
|||
<RadzenDataGridColumn TItem="Tblbrand" Property="Id" Title="Brand ID" Resizable Reorderable /> |
|||
<RadzenDataGridColumn TItem="Tblbrand" Property="Brand" Title="Brand Name" Resizable Reorderable /> |
|||
<RadzenDataGridColumn TItem="Tblbrand" Property="BranchId" Title="Branch" Resizable Reorderable /> |
|||
</Columns> |
|||
</RadzenDataGrid> |
@ -0,0 +1,37 @@ |
|||
using Biskilog_Accounting.Shared.POSModels; |
|||
|
|||
namespace Biskilog_Accounting.Client.Pages.Product |
|||
{ |
|||
public partial class Brands |
|||
{ |
|||
private IEnumerable<Tblbrand> m_brands { get; set; } = new List<Tblbrand>(); |
|||
protected override void OnInitialized() |
|||
{ |
|||
m_productRepo.BrandsChanged += BrandFetchComplete; |
|||
m_searchControl.SearchValueChanged += SearchValueChanged; |
|||
|
|||
LoadBrands(string.Empty); |
|||
base.OnInitialized(); |
|||
} |
|||
|
|||
private void SearchValueChanged(string a_searchKey) |
|||
{ |
|||
LoadBrands(a_searchKey); |
|||
} |
|||
|
|||
public void Dispose() |
|||
{ |
|||
m_productRepo.BrandsChanged -= BrandFetchComplete; |
|||
m_searchControl.SearchValueChanged -= SearchValueChanged; |
|||
} |
|||
private void BrandFetchComplete(object? sender, EventArgs e) |
|||
{ |
|||
LoadBrands(string.Empty); |
|||
} |
|||
private void LoadBrands(string a_productKey) |
|||
{ |
|||
m_brands = m_productRepo.GetBrands(a_productKey); |
|||
StateHasChanged(); |
|||
} |
|||
} |
|||
} |
@ -0,0 +1,19 @@ |
|||
@page "/products/categories" |
|||
@using Biskilog_Accounting.Shared.POSModels; |
|||
@using Biskilog_Accounting.Shared.Interfaces |
|||
@inject IProduct m_productRepo |
|||
@inject ContextMenuService ContextMenuService |
|||
@inject DialogService m_dialogService |
|||
@inject ISearchService m_searchControl |
|||
@implements IDisposable |
|||
|
|||
<div class="row" style="display:flex;justify-content:space-between;padding: 5px;margin-right:10px;"> |
|||
<h3>Categories</h3> |
|||
</div> |
|||
<RadzenDataGrid AllowPaging="true" PageSize="50" AllowSorting="true" Data="@m_categories" TItem="Tblcategory" GridLines="DataGridGridLines.Horizontal"> |
|||
<Columns> |
|||
<RadzenDataGridColumn TItem="Tblcategory" Property="Id" Title="Category ID" Resizable Reorderable /> |
|||
<RadzenDataGridColumn TItem="Tblcategory" Property="Category" Title="Category Name" Resizable Reorderable /> |
|||
<RadzenDataGridColumn TItem="Tblcategory" Property="BranchId" Title="Branch" Resizable Reorderable /> |
|||
</Columns> |
|||
</RadzenDataGrid> |
@ -0,0 +1,37 @@ |
|||
using Biskilog_Accounting.Shared.POSModels; |
|||
|
|||
namespace Biskilog_Accounting.Client.Pages.Product |
|||
{ |
|||
public partial class Categories |
|||
{ |
|||
private IEnumerable<Tblcategory> m_categories { get; set; } = new List<Tblcategory>(); |
|||
protected override void OnInitialized() |
|||
{ |
|||
m_productRepo.CategoriesChanged += CategoryFetchComplete; |
|||
m_searchControl.SearchValueChanged += SearchValueChanged; |
|||
|
|||
LoadCategories(string.Empty); |
|||
base.OnInitialized(); |
|||
} |
|||
|
|||
private void SearchValueChanged(string a_searchKey) |
|||
{ |
|||
LoadCategories(a_searchKey); |
|||
} |
|||
|
|||
public void Dispose() |
|||
{ |
|||
m_productRepo.CategoriesChanged -= CategoryFetchComplete; |
|||
m_searchControl.SearchValueChanged -= SearchValueChanged; |
|||
} |
|||
private void CategoryFetchComplete(object? sender, EventArgs e) |
|||
{ |
|||
LoadCategories(string.Empty); |
|||
} |
|||
private void LoadCategories(string a_productKey) |
|||
{ |
|||
m_categories = m_productRepo.GetCategories(a_productKey); |
|||
StateHasChanged(); |
|||
} |
|||
} |
|||
} |
@ -0,0 +1,186 @@ |
|||
@page "/products/{product}" |
|||
@using Biskilog_Accounting.Shared.CustomModels; |
|||
@using Biskilog_Accounting.Shared.Interfaces; |
|||
@inject IProduct m_productRepo |
|||
@inject ICalculator m_calculator |
|||
|
|||
<RadzenCard Style="margin-bottom: 20px;"> |
|||
<div class="row" style="justify-content: end;height: 20px;display: grid;"> |
|||
<RadzenStack Orientation="Radzen.Orientation.Horizontal" AlignItems="AlignItems.Center" Gap="0.5rem"> |
|||
<RadzenSwitch @bind-Value="m_editMode" /> |
|||
<RadzenLabel Text="Edit Mode" /> |
|||
</RadzenStack> |
|||
</div> |
|||
<div class="row align-items-center" style="justify-content: center;"> |
|||
<img src="assets/img/box.png" style="width:200px;" /> |
|||
</div> |
|||
@if (m_editMode) |
|||
{ |
|||
<div class="row"> |
|||
<div class="col-md-6 align-items-center d-flex"> |
|||
<RadzenFieldset Text="Product Info" Style="width:100%;"> |
|||
<div class="row"> |
|||
<div class="col-md-4 align-items-center d-flex"> |
|||
<RadzenLabel Text="Product Id" /> |
|||
</div> |
|||
<div class="col-md-8"> |
|||
<RadzenTextBox Disabled="true" style="width: 100%;" Name="pcode" @bind-Value=@(Product.Product!.Pcode) /> |
|||
</div> |
|||
</div> |
|||
<div class="row" style="margin-top:5px;"> |
|||
<div class="col-md-4 align-items-center d-flex"> |
|||
<RadzenLabel Text="Product Name" /> |
|||
</div> |
|||
<div class="col-md-8"> |
|||
<RadzenTextBox Disabled="true" style="width: 100%;" Name="productName" @bind-Value=@(Product.Product!.ProductName) /> |
|||
</div> |
|||
</div> |
|||
|
|||
<div class="row" style="margin-top:5px;"> |
|||
<div class="col-md-4 align-items-center d-flex"> |
|||
<RadzenLabel Text="Description" /> <b></b> |
|||
</div> |
|||
<div class="col-md-8"> |
|||
<RadzenTextArea Disabled="true" @bind-Value=@(Product.Product!.Pdesc) Cols="25" Rows="4" /> |
|||
</div> |
|||
</div> |
|||
|
|||
</RadzenFieldset> |
|||
</div> |
|||
<div class="col-md-6"> |
|||
<RadzenFieldset Text="Other Units Of Measure"> |
|||
<div class="row" style="justify-content: end;height: 20px;display: grid;"> |
|||
<RadzenButton Icon="add_circle_outline" ButtonStyle="ButtonStyle.Light" /> |
|||
</div> |
|||
<div class="row" style="margin-top:5px;"> |
|||
<div class="col-md-6 align-items-center d-flex"> |
|||
<RadzenLabel Text="Unit Of Measure" /> <b></b> |
|||
</div> |
|||
<div class="col-md-6 align-items-center d-flex"> |
|||
<RadzenLabel Text="Quantity" /> <b></b> |
|||
</div> |
|||
</div> |
|||
@foreach (ProductUnits unit in Product.Units) |
|||
{ |
|||
<div class="row" style="margin-top:5px;"> |
|||
<div class="col-md-6 align-items-center d-flex"> |
|||
<RadzenDropDown @bind-Value=@(unit.UnitCode) Data=@(m_productRepo.GetUnitofmeasures()) TextProperty="UnitName" ValueProperty="UnitCode" /> |
|||
</div> |
|||
<div class="col-md-6 align-items-center d-flex"> |
|||
<RadzenNumeric Placeholder="10" Step="1" @bind-Value=@(unit.QuantityUnit) /> |
|||
</div> |
|||
</div> |
|||
} |
|||
</RadzenFieldset> |
|||
</div> |
|||
</div> |
|||
<div class="row"> |
|||
<div class="col-md-6 align-items-center d-flex"> |
|||
<RadzenFieldset Text="Base Unit" Style="width:100%;"> |
|||
<div class="row"> |
|||
<div class="col-md-4 align-items-center d-flex"> |
|||
<RadzenLabel Text="Base Unit" /> |
|||
</div> |
|||
<div class="col-md-8"> |
|||
<RadzenDropDown @bind-Value=@(Product.BaseUnit) Data=@(m_productRepo.GetUnitofmeasures()) TextProperty="UnitName" ValueProperty="UnitCode" /> |
|||
</div> |
|||
</div> |
|||
</RadzenFieldset> |
|||
</div> |
|||
<div class="col-md-6"> |
|||
<RadzenFieldset Text="Re-order Level"> |
|||
<div class="row"> |
|||
<div class="col-md-6 align-items-center d-flex"> |
|||
<RadzenLabel Text="Quantity" /> |
|||
</div> |
|||
<div class="col-md-6 align-items-center d-flex"> |
|||
<RadzenNumeric Placeholder="10" Step="1" @bind-Value=@(Product.Restocklevel!.WarnLevel) /> |
|||
</div> |
|||
</div> |
|||
<div class="row" style="margin-top:5px;"> |
|||
<div class="col-md-6 align-items-center d-flex"> |
|||
<RadzenLabel Text="Unit Of Measure" /> |
|||
</div> |
|||
<div class="col-md-6 align-items-center d-flex"> |
|||
<RadzenDropDown @bind-Value=@(Product.Restocklevel!.Unit) Data=@(m_reorderUnits) TextProperty="UnitName" ValueProperty="UnitCode" /> |
|||
</div> |
|||
</div> |
|||
</RadzenFieldset> |
|||
</div> |
|||
</div> |
|||
<div class="row" style="display:flex;justify-content:safe center;margin-top:10px;margin-bottom:10px;"> |
|||
<RadzenButton Text="Save" Style="width:fit-content;background-color:green;margin-right:10px;" /> |
|||
<RadzenButton Text="Cancel" Style="width:fit-content;background-color:Darkred;" /> |
|||
</div> |
|||
} |
|||
else |
|||
{ |
|||
//Read Only View |
|||
<RadzenFieldset Text="Product Info" Style="width:100%;"> |
|||
<div class="row"> |
|||
<div class="col-md-4 align-items-center d-flex"> |
|||
<RadzenLabel Text="Product Id" /> |
|||
</div> |
|||
<div class="col-md-8"> |
|||
<RadzenTextBox Disabled="true" style="width: 100%;" Name="pcode" @bind-Value=@(Product.Product!.Pcode) /> |
|||
</div> |
|||
</div> |
|||
<div class="row" style="margin-top:5px;"> |
|||
<div class="col-md-4 align-items-center d-flex"> |
|||
<RadzenLabel Text="Product Name" /> |
|||
</div> |
|||
<div class="col-md-8"> |
|||
<RadzenTextBox Disabled="true" style="width: 100%;" Name="productName" @bind-Value=@(Product.Product!.ProductName) /> |
|||
</div> |
|||
</div> |
|||
|
|||
<div class="row" style="margin-top:5px;"> |
|||
<div class="col-md-4 align-items-center d-flex"> |
|||
<RadzenLabel Text="Description" /> <b></b> |
|||
</div> |
|||
<div class="col-md-8"> |
|||
<RadzenTextArea Disabled="true" @bind-Value=@(Product.Product!.Pdesc) Cols="45" Rows="4" /> |
|||
</div> |
|||
</div> |
|||
<div class="row" style="margin-top:5px;"> |
|||
<div class="col-md-4 align-items-center d-flex"> |
|||
<RadzenLabel Text="Base Unit" /> <b></b> |
|||
</div> |
|||
<div class="col-md-8"> |
|||
<RadzenTextBox Disabled="true" Value=@(m_productRepo.GetUnitName(Product.Product!.BaseUnit)) /> |
|||
</div> |
|||
</div> |
|||
<div class="row" style="margin-top:5px;"> |
|||
<div class="col-md-4 align-items-center d-flex"> |
|||
<RadzenLabel Text="Quantity" /> <b></b> |
|||
</div> |
|||
<div class="col-md-8"> |
|||
<RadzenNumeric Disabled="true" @bind-Value=@(Product.Stock!.Quantity) /> |
|||
</div> |
|||
</div> |
|||
<div class="row" style="margin-top:5px;"> |
|||
<RadzenDataGrid Data="@(Product.Units.OrderBy(t => t.PriceUnit))" TItem="ProductUnits" GridLines="DataGridGridLines.Horizontal"> |
|||
<Columns> |
|||
<RadzenDataGridColumn TItem="ProductUnits" Property="UnitCode" Title="Unit Of Measure"> |
|||
<Template Context="detail"> |
|||
@(m_productRepo.GetUnitName(detail.UnitCode)) |
|||
</Template> |
|||
</RadzenDataGridColumn> |
|||
<RadzenDataGridColumn TItem="ProductUnits" Property="QuantityUnit" Title="Quantity" /> |
|||
<RadzenDataGridColumn TItem="ProductUnits" Property="PriceUnit" Title="Price Per Unit"> |
|||
<Template Context="detail"> |
|||
@(m_calculator.FormatMoneyWithCurrency((double)detail.PriceUnit)) |
|||
</Template> |
|||
</RadzenDataGridColumn> |
|||
</Columns> |
|||
</RadzenDataGrid> |
|||
</div> |
|||
</RadzenFieldset> |
|||
<div class="row" style="display:flex;justify-content:safe center;margin-top:10px;margin-bottom:10px;"> |
|||
<RadzenButton Text="Print Barcode" Style="width:fit-content;margin-right:10px;background-color:forestgreen;" /> |
|||
<RadzenButton Text="Print Tags" Style="width:fit-content;margin-right:10px;background-color:cornflowerblue;" /> |
|||
<RadzenButton Text="Add Stock" Style="width:fit-content;background-color:#435971;" /> |
|||
</div> |
|||
} |
|||
|
|||
</RadzenCard> |
@ -0,0 +1,25 @@ |
|||
using Biskilog_Accounting.Shared.CustomModels; |
|||
using Microsoft.AspNetCore.Components; |
|||
|
|||
namespace Biskilog_Accounting.Client.Pages.Product.Elements |
|||
{ |
|||
public partial class ProductDialog |
|||
{ |
|||
[Parameter] |
|||
public ProductItem Product { get; set; } |
|||
|
|||
private bool m_editMode { get; set; } = false; |
|||
private List<ProductUnits> m_reorderUnits { get; set; } = new List<ProductUnits>(); |
|||
protected override void OnParametersSet() |
|||
{ |
|||
var list = Product.Units.Select(c => c.UnitCode); |
|||
m_reorderUnits = m_productRepo.GetUnitofmeasures().Where(t => t.UnitCode == Product.BaseUnit || list.Contains(t.UnitCode)) |
|||
.Select(t => new ProductUnits |
|||
{ |
|||
UnitCode = t.UnitCode, |
|||
UnitName = t.Unitname, |
|||
}).ToList(); |
|||
base.OnParametersSet(); |
|||
} |
|||
} |
|||
} |
@ -0,0 +1,29 @@ |
|||
@page "/products/inventory" |
|||
@using Biskilog_Accounting.Shared.CustomModels; |
|||
@using Biskilog_Accounting.Shared.Interfaces; |
|||
@inject IProduct m_productRepo |
|||
@inject ContextMenuService ContextMenuService |
|||
@inject DialogService m_dialogService |
|||
@inject ISearchService m_searchControl |
|||
@implements IDisposable |
|||
|
|||
|
|||
<div class="row" style="display:flex;justify-content:space-between;padding: 5px;margin-right:10px;"> |
|||
<h3>Products</h3> |
|||
</div> |
|||
<RadzenDataGrid AllowPaging="true" PageSize="50" AllowSorting="true" Data="@m_products" TItem="ProductItem" GridLines="DataGridGridLines.Horizontal" |
|||
SelectionMode="DataGridSelectionMode.Single" @bind-Value=@m_selectedProducts CellContextMenu="@OnCellContextMenu"> |
|||
<Columns> |
|||
<RadzenDataGridColumn TItem="ProductItem" Property="Product.Pcode" Title="Product ID" Width="15%" Resizable Reorderable /> |
|||
<RadzenDataGridColumn TItem="ProductItem" Property="Product.ProductName" Title="Product Name" Width="20%" Resizable Reorderable /> |
|||
<RadzenDataGridColumn TItem="ProductItem" Property="Product.Pdesc" Title="Description" Width="25%" Resizable Reorderable /> |
|||
<RadzenDataGridColumn TItem="ProductItem" Property="Stock.Quantity" Title="Quantity" Width="10%" Resizable Reorderable /> |
|||
<RadzenDataGridColumn TItem="ProductItem" Property="BaseUnit" Title="Unit" Width="10%" Reorderable Resizable> |
|||
<Template Context="detail"> |
|||
@(m_productRepo.GetUnitName(detail.BaseUnit)) |
|||
</Template> |
|||
</RadzenDataGridColumn> |
|||
<RadzenDataGridColumn TItem="ProductItem" Property="Product.Status" Title="Status" Width="10%" Reorderable Resizable /> |
|||
<RadzenDataGridColumn TItem="ProductItem" Property="Product.BranchId" Title="Branch" Width="10%" Resizable Reorderable /> |
|||
</Columns> |
|||
</RadzenDataGrid> |
@ -0,0 +1,68 @@ |
|||
using Biskilog_Accounting.Client.Pages.Product.Elements; |
|||
using Biskilog_Accounting.Shared.CustomModels; |
|||
using Radzen; |
|||
|
|||
namespace Biskilog_Accounting.Client.Pages.Product |
|||
{ |
|||
public partial class Products |
|||
{ |
|||
private IEnumerable<ProductItem> m_products { get; set; } = Enumerable.Empty<ProductItem>(); |
|||
private IList<ProductItem> m_selectedProducts { get; set; } = new List<ProductItem>(); |
|||
|
|||
protected override void OnInitialized() |
|||
{ |
|||
m_productRepo.ProductsChanged += ProductsFetchComplete; |
|||
m_searchControl.SearchValueChanged += SearchValueChanged; |
|||
|
|||
LoadProducts(string.Empty); |
|||
base.OnInitialized(); |
|||
} |
|||
|
|||
private void SearchValueChanged(string a_searchKey) |
|||
{ |
|||
LoadProducts(a_searchKey); |
|||
} |
|||
|
|||
public void Dispose() |
|||
{ |
|||
m_productRepo.ProductsChanged -= ProductsFetchComplete; |
|||
m_searchControl.SearchValueChanged -= SearchValueChanged; |
|||
} |
|||
private void ProductsFetchComplete(object? sender, EventArgs e) |
|||
{ |
|||
LoadProducts(string.Empty); |
|||
} |
|||
private void LoadProducts(string a_productKey) |
|||
{ |
|||
m_products = m_productRepo.GetProducts(a_productKey); |
|||
StateHasChanged(); |
|||
} |
|||
private void OnCellContextMenu(DataGridCellMouseEventArgs<ProductItem> args) |
|||
{ |
|||
m_selectedProducts = new List<ProductItem>() { args.Data }; |
|||
|
|||
ContextMenuService.Open(args, |
|||
new List<ContextMenuItem> { |
|||
new ContextMenuItem(){ Text = "Open", Value = 1 }, |
|||
new ContextMenuItem(){ Text = m_selectedProducts.First().Product!.Status == "INACTIVE" ? |
|||
"Activate" : "Deactivate", Value = 2}, |
|||
new ContextMenuItem(){ Text = "Change Price", Value = 3}, |
|||
new ContextMenuItem(){ Text = "Add Stock", Value = 4}, |
|||
new ContextMenuItem(){ Text = "View Performance History", Value = 5}, |
|||
}, |
|||
(e) => |
|||
{ |
|||
OpenProductDialog(m_selectedProducts.First()); |
|||
Console.WriteLine($"Menu item with Value={e.Value} clicked. Column: {args.Column.Property}, EmployeeID: {args.Data.Product.Pcode}"); |
|||
} |
|||
); |
|||
} |
|||
|
|||
async Task OpenProductDialog(ProductItem a_productItem) |
|||
{ |
|||
await m_dialogService.OpenAsync<ProductDialog>($"{a_productItem.Product!.ProductName}", |
|||
new Dictionary<string, object>() { { "Product", a_productItem } }, |
|||
new DialogOptions() { Width = "1020px", Height = "900px", Resizable = false, Draggable = true }); |
|||
} |
|||
} |
|||
} |
@ -0,0 +1,95 @@ |
|||
@page "/transactions/receipt/{receiptID}" |
|||
@using Biskilog_Accounting.Shared.Interfaces; |
|||
@using Biskilog_Accounting.Shared.POSModels; |
|||
@inject ICalculator m_calculator |
|||
@inject IProduct m_productRepo |
|||
@inject ISalesInterface m_saleInterface |
|||
@inject ICompanyInfo m_companyInfo |
|||
|
|||
<div class="container" style="padding-top:10px;"> |
|||
<div class="row"> |
|||
<div class="row" style="display:grid;justify-content:center;"> |
|||
<small>@(m_companyName)</small> |
|||
</div> |
|||
<div class="row" style="display:grid;justify-content:center;"> |
|||
<small>@m_branch?.BranchName</small> |
|||
</div> |
|||
<div class="row" style="display:grid;justify-content:center;"> |
|||
<small>@m_branch?.City</small> |
|||
</div> |
|||
<div class="row" style="display:grid;justify-content:center;"> |
|||
<small>@m_branch?.BranchTelephone</small> |
|||
</div> |
|||
<hr /> |
|||
<div class="row" style="display:block;justify-content:space-between;"> |
|||
<small> <em>Date</em> </small> |
|||
<small> @m_date </small> |
|||
</div> |
|||
<div class="row" style="display:block;justify-content:space-between;"> |
|||
<small> <em>Cashier</em> </small> |
|||
<small> @m_cashier </small> |
|||
</div> |
|||
<div class="row" style="display:block;justify-content:space-between;"> |
|||
<small> <em>Receipt Number</em> </small> |
|||
<small> <em>@ReceiptId</em> </small> |
|||
</div> |
|||
<hr /> |
|||
<RadzenDataGrid TItem="Tblcart" Data="ReceiptDetail" GridLines="DataGridGridLines.Horizontal" Style="padding:0px;"> |
|||
<Columns> |
|||
<RadzenDataGridColumn TItem="Tblcart" Property="Transno" Title="Item" Width="60%"> |
|||
<Template Context="detail"> |
|||
<small>@detail.Id <br />x@(detail.Quantity) @(detail.Unit)</small> |
|||
</Template> |
|||
</RadzenDataGridColumn> |
|||
<RadzenDataGridColumn TItem="Tblcart" Property="Total" Title="Total" Width="40%"> |
|||
<Template Context="detail"> |
|||
<small>@(m_calculator.FormatMoneyWithCurrency((double)detail.Total))</small> |
|||
</Template> |
|||
</RadzenDataGridColumn> |
|||
</Columns> |
|||
</RadzenDataGrid> |
|||
<div class="row" style="display:grid;justify-content:end;"> |
|||
<RadzenStack Orientation="Radzen.Orientation.Horizontal"> |
|||
<small> <em>Sub Total</em> </small> |
|||
<small> <em>@m_subtotal</em> </small> |
|||
</RadzenStack> |
|||
</div> |
|||
<div class="row" style="display:grid;justify-content:end;"> |
|||
<RadzenStack Orientation="Radzen.Orientation.Horizontal"> |
|||
<small> <em>Discount</em> </small> |
|||
<small> <em>@m_discount</em> </small> |
|||
</RadzenStack> |
|||
</div> |
|||
<div class="row" style="display:grid;justify-content:end;"> |
|||
<RadzenStack Orientation="Radzen.Orientation.Horizontal"> |
|||
<small> <em>VAT</em> </small> |
|||
<small> <em>@m_vat</em> </small> |
|||
</RadzenStack> |
|||
</div> |
|||
<hr /> |
|||
<div class="row" style="display:grid;justify-content:end;"> |
|||
<RadzenStack Orientation="Radzen.Orientation.Horizontal"> |
|||
<small> <em>Bill Total</em> </small> |
|||
<small> <em>@m_total</em> </small> |
|||
</RadzenStack> |
|||
</div> |
|||
<div class="row" style="display:grid;justify-content:end;"> |
|||
<RadzenStack Orientation="Radzen.Orientation.Horizontal"> |
|||
<small> <em>Balance</em> </small> |
|||
<small> <em>@m_balance</em> </small> |
|||
</RadzenStack> |
|||
</div> |
|||
<div class="row" style="display:grid;justify-content:end;"> |
|||
<RadzenStack Orientation="Radzen.Orientation.Horizontal"> |
|||
<small> <em>Tendered</em> </small> |
|||
<small> <em>@m_tendered</em> </small> |
|||
</RadzenStack> |
|||
</div> |
|||
<hr /> |
|||
<div class="row" style="display:grid;justify-content:center;"> |
|||
<small style="margin-bottom: 5px;margin-left: 20px"><em>COME BACK SOON !!! CHEERS</em> </small> |
|||
<div id="barcode">@barcode</div> |
|||
<div id="barcode_text">@barcode_text</div> |
|||
</div> |
|||
</div> |
|||
</div> |
@ -0,0 +1,67 @@ |
|||
using Biskilog_Accounting.Shared.POSModels; |
|||
using Microsoft.AspNetCore.Components; |
|||
using Net.ConnectCode.Barcode; |
|||
|
|||
namespace Biskilog_Accounting.Client.Pages.Transactions.Elements |
|||
{ |
|||
public partial class ReceiptDialog |
|||
{ |
|||
[Parameter] |
|||
public string ReceiptId { get; set; } |
|||
|
|||
private IEnumerable<Tblcart> ReceiptDetail { get; set; } = Enumerable.Empty<Tblcart>(); |
|||
string barcode = ""; |
|||
string barcode_text = ""; |
|||
private string m_balance { get; set; } |
|||
private string m_tendered { get; set; } |
|||
private string m_total { get; set; } |
|||
private string m_subtotal { get; set; } |
|||
private string m_discount { get; set; } = "0.00"; |
|||
private string m_vat { get; set; } |
|||
private string m_cashier { get; set; } |
|||
private string m_date { get; set; } |
|||
private Tblbranch m_branch { get; set; } |
|||
private string m_companyName { get; set; } = string.Empty; |
|||
void GenerateBarcode() |
|||
{ |
|||
BarcodeFonts bcf = new BarcodeFonts(); |
|||
bcf.BarcodeType = BarcodeFonts.BarcodeEnum.Code39; |
|||
bcf.CheckDigit = BarcodeFonts.YesNoEnum.Yes; |
|||
bcf.Data = ReceiptId; |
|||
bcf.encode(); |
|||
barcode = bcf.EncodedData; |
|||
barcode_text = ReceiptId; |
|||
} |
|||
protected override async Task OnParametersSetAsync() |
|||
{ |
|||
ReceiptDetail = await m_saleInterface.GetReceiptDetail(ReceiptId); |
|||
SetParams(); |
|||
GenerateBarcode(); |
|||
StateHasChanged(); |
|||
return; |
|||
} |
|||
private void SetParams() |
|||
{ |
|||
if (ReceiptDetail.Count() > 0) |
|||
{ |
|||
double total = (double)ReceiptDetail.Sum(t => t.Total).Value; |
|||
double discount = (double)ReceiptDetail.First().Discount.Value; |
|||
double vat = (double)ReceiptDetail.First().ValueAddTax.Value; |
|||
double billTotal = (vat + total); |
|||
|
|||
m_cashier = ReceiptDetail.First().Cashier; |
|||
|
|||
m_subtotal = m_calculator.FormatMoneyWithCurrency(total); |
|||
m_tendered = m_calculator.FormatMoneyWithCurrency((double)ReceiptDetail.First().Tendered.Value); |
|||
m_balance = m_calculator.FormatMoneyWithCurrency((double)ReceiptDetail.First().Balance.Value); |
|||
m_vat = (vat).ToString("0.00") + "%"; |
|||
m_date = ReceiptDetail.First().Date.Value.ToString("dd MMMM, yyyy HH:mm:ss"); |
|||
m_total = m_calculator.FormatMoneyWithCurrency(billTotal); |
|||
|
|||
string branchId = ReceiptDetail.First().BranchId; |
|||
m_branch = m_companyInfo.FetchBranches().ToList().First(t => t.BranchId == branchId); |
|||
m_companyName = m_companyInfo.GetCompanyName(); |
|||
} |
|||
} |
|||
} |
|||
} |
@ -0,0 +1,25 @@ |
|||
@using Biskilog_Accounting.Shared.Interfaces |
|||
@inject ICalculator m_calculator |
|||
<RadzenCard Style="margin-bottom:10px;"> |
|||
<div class="row" style="margin:8px;display:grid;justify-content:center;"> |
|||
@if (RecentTrans) |
|||
{ |
|||
<h5>Transaction summary for the past @(TotalNbrTransactions) transactions</h5> |
|||
|
|||
}else{ |
|||
<h5>Transaction summary for the period between : @(StartRange.ToString("dd MMM, yyyy")) to @(EndRange.ToString("dd MMM, yyyy"))</h5> |
|||
} |
|||
</div> |
|||
<div class="row" style="margin:8px;"> |
|||
<small>Total number of transactions made during the period : <b>@(TotalNbrTransactions)</b> </small> |
|||
</div> |
|||
<div class="row" style="margin:8px;"> |
|||
<small>Total Revenue Generated during the period : <b>@(m_calculator.FormatMoneyWithCurrency(TotalRevenue))</b></small> |
|||
</div> |
|||
<div class="row" style="margin:8px;"> |
|||
<small>Total number of cancelled transactions during the period : <b>@(TotalNbrCancelledRevenue)</b> </small> |
|||
</div> |
|||
<div class="row" style="margin:8px;"> |
|||
<small>Total Revenue lost to cancelled receipts during the period : <b>@(m_calculator.FormatMoneyWithCurrency(TotalCancelledRevenue))</b></small> |
|||
</div> |
|||
</RadzenCard> |
@ -0,0 +1,24 @@ |
|||
using Microsoft.AspNetCore.Components; |
|||
|
|||
namespace Biskilog_Accounting.Client.Pages.Transactions.Elements |
|||
{ |
|||
public partial class SaleSummary |
|||
{ |
|||
[Parameter] |
|||
public DateTime StartRange { get; set; } |
|||
[Parameter] |
|||
public DateTime EndRange { get; set; } |
|||
[Parameter] |
|||
public double TotalRevenue { get; set; } |
|||
[Parameter] |
|||
public int TotalNbrTransactions { get; set; } |
|||
[Parameter] |
|||
public int TotalNbrCancelledRevenue { get; set; } |
|||
[Parameter] |
|||
public string TopSalesMan { get; set; } |
|||
[Parameter] |
|||
public double TotalCancelledRevenue { get; set; } |
|||
[Parameter] |
|||
public bool RecentTrans { get; set; } |
|||
} |
|||
} |
@ -0,0 +1,77 @@ |
|||
@page "/transactions/sales" |
|||
@using Biskilog_Accounting.Shared.CustomModels; |
|||
@using Biskilog_Accounting.Shared.Interfaces; |
|||
@using Biskilog_Accounting.Client.Pages.Transactions.Elements; |
|||
@using BlazorDateRangePicker |
|||
@using Faso.Blazor.SpinKit |
|||
@inject ICalculator m_calculator |
|||
@inject ISalesInterface m_salesRepo |
|||
@inject ContextMenuService ContextMenuService |
|||
@inject DialogService m_dialogService |
|||
@inject ISearchService m_searchControl |
|||
@implements IDisposable |
|||
@inject IMainInterface m_mainInterface |
|||
|
|||
<h3>Sales</h3> |
|||
<div class="row" style="display:grid;justify-content:end;margin:5px;"> |
|||
<DateRangePicker @bind-StartDate="m_startDate" @bind-EndDate="m_endDate" Ranges="m_ranges" ShowCustomRangeLabel="true" OnRangeSelect="@LoadTransactions"> |
|||
<PickerTemplate> |
|||
<div id="@context.Id" @onclick="context.Toggle" style="background: #fff; cursor: pointer; padding: 5px 10px; width: 250px; border: 1px solid #ccc;"> |
|||
<i class="tf-icons bx bx-calendar"></i> |
|||
<span>@context.FormattedRange @(string.IsNullOrEmpty(context.FormattedRange) ? "Choose dates..." : "")</span> |
|||
<i class="oi oi-chevron-bottom float-right"></i> |
|||
</div> |
|||
</PickerTemplate> |
|||
<ButtonsTemplate> |
|||
<button class="cancelBtn btn btn-sm btn-default" |
|||
@onclick="@context.ClickCancel" type="button"> |
|||
Cancel |
|||
</button> |
|||
<button class="cancelBtn btn btn-sm btn-default" |
|||
@onclick="@(e => ResetClick(e, context))" type="button"> |
|||
Reset |
|||
</button> |
|||
<button class="applyBtn btn btn-sm btn-primary" @onclick="@context.ClickApply" |
|||
disabled="@(context.TStartDate == null || context.TEndDate == null)" |
|||
type="button"> |
|||
Apply |
|||
</button> |
|||
</ButtonsTemplate> |
|||
</DateRangePicker> |
|||
</div> |
|||
@if (!m_lookUpMode) |
|||
{ |
|||
<SaleSummary StartRange="m_startDate.Value.LocalDateTime" EndRange="m_endDate.Value.LocalDateTime" |
|||
TotalRevenue="m_totalRevenue" TotalNbrTransactions="m_totalNbrRevenue" TotalCancelledRevenue="m_totalCancelledRevenue" |
|||
TotalNbrCancelledRevenue="m_totalNbrCancelled" RecentTrans="m_recent"/> |
|||
} |
|||
<RadzenDataGrid AllowPaging="true" PageSize="50" AllowSorting="true" Data="@m_salesItems" TItem="SaleItem" |
|||
GridLines="DataGridGridLines.Horizontal" RowClick="@(args => m_mainInterface.ShowReceipt(args.Data.Transno))"> |
|||
<Columns> |
|||
<RadzenDataGridColumn TItem="SaleItem" Property="Transno" Title="Transaction ID" /> |
|||
<RadzenDataGridColumn TItem="SaleItem" Property="Date" Title="Timestamp" /> |
|||
<RadzenDataGridColumn TItem="SaleItem" Property="Cashier" Title="Cashier" /> |
|||
<RadzenDataGridColumn TItem="SaleItem" Property="Customer" Title="Customer" /> |
|||
<RadzenDataGridColumn TItem="SaleItem" Property="Status" Title="Status" Width="10%" /> |
|||
<RadzenDataGridColumn TItem="SaleItem" Property="Total" Title="Total"> |
|||
<Template Context="detail"> |
|||
@( |
|||
m_calculator.FormatMoneyWithCurrency((double)detail.Total) |
|||
) |
|||
</Template> |
|||
</RadzenDataGridColumn> |
|||
<RadzenDataGridColumn TItem="SaleItem" Property="BranchId" Title="Branch" Resizable Reorderable /> |
|||
</Columns> |
|||
</RadzenDataGrid> |
|||
|
|||
@if (m_fetching) |
|||
{ |
|||
<div id="loading-div-background"> |
|||
<div id="loading-div" class="ui-corner-all"> |
|||
<div class="spinnermain-container"> |
|||
<SpinKitChasingDots /> |
|||
</div> |
|||
<h6 style="color:#fff;font-weight:normal;">Please wait fetching transaction details....</h6> |
|||
</div> |
|||
</div> |
|||
} |
@ -0,0 +1,102 @@ |
|||
using Biskilog_Accounting.Client.Pages.Product; |
|||
using Biskilog_Accounting.Shared.CustomModels; |
|||
using BlazorDateRangePicker; |
|||
using Microsoft.AspNetCore.Components.Web; |
|||
|
|||
namespace Biskilog_Accounting.Client.Pages.Transactions |
|||
{ |
|||
public partial class Sales |
|||
{ |
|||
private IEnumerable<SaleItem> m_salesItems { get; set; } = Enumerable.Empty<SaleItem>(); |
|||
private DateTimeOffset? m_startDate { get; set; } = DateTimeOffset.Now; |
|||
private DateTimeOffset? m_endDate { get; set; } = DateTimeOffset.Now; |
|||
private Dictionary<string, DateRange> m_ranges = new Dictionary<string, DateRange>(); |
|||
private double m_totalRevenue { get; set; } |
|||
private double m_totalCancelledRevenue { get; set; } |
|||
private int m_totalNbrRevenue { get; set; } |
|||
private int m_totalNbrCancelled { get; set; } |
|||
private bool m_lookUpMode { get; set; } |
|||
private bool m_fetching { get; set; } |
|||
private bool m_recent { get; set; } |
|||
|
|||
protected override void OnInitialized() |
|||
{ |
|||
PopulateRange(); |
|||
m_salesRepo.TransactionsChanged += TransactionsChanged; |
|||
m_searchControl.SearchValueChanged += SearchValueChanged; |
|||
m_salesRepo.FetchStart += FetchStart; |
|||
m_salesRepo.FetchComplete += FetchComplete; |
|||
|
|||
m_salesItems = m_salesRepo.GetRecentTransaction(); |
|||
SetParams(); |
|||
m_recent = true; |
|||
base.OnInitialized(); |
|||
} |
|||
|
|||
private void FetchComplete(object? sender, EventArgs e) |
|||
{ |
|||
m_fetching = false; |
|||
StateHasChanged(); |
|||
} |
|||
|
|||
private void FetchStart(object? sender, EventArgs e) |
|||
{ |
|||
m_fetching = true; |
|||
StateHasChanged(); |
|||
} |
|||
|
|||
void ResetClick(MouseEventArgs e, DateRangePicker picker) |
|||
{ |
|||
m_startDate = DateTimeOffset.UtcNow; |
|||
m_endDate = DateTimeOffset.UtcNow; |
|||
// Close the picker
|
|||
picker.Close(); |
|||
// Fire OnRangeSelectEvent
|
|||
picker.OnRangeSelect.InvokeAsync(new DateRange()); |
|||
} |
|||
private void PopulateRange() |
|||
{ |
|||
m_ranges.Clear(); |
|||
m_ranges.Add("Today", new DateRange() { Start = DateTime.Now, End = DateTime.Now.AddDays(1) }); |
|||
m_ranges.Add("Yesterday", new DateRange() { Start = DateTime.Now.AddDays(-1), End = DateTime.Now }); |
|||
m_ranges.Add("Last 7 Days", new DateRange() { Start = DateTime.Now.AddDays(-7), End = DateTime.Now }); |
|||
m_ranges.Add("Last 30 Days", new DateRange() { Start = DateTime.Now.AddDays(-30), End = DateTime.Now }); |
|||
} |
|||
private void TransactionsChanged(object? sender, EventArgs e) |
|||
{ |
|||
m_salesItems = m_salesRepo.GetTransactions(m_startDate.Value.Date, m_endDate.Value.Date); |
|||
SetParams(); |
|||
StateHasChanged(); |
|||
} |
|||
|
|||
private void SearchValueChanged(string a_searchKey) |
|||
{ |
|||
m_salesRepo.FetchReceipt(a_searchKey); |
|||
m_lookUpMode = !string.IsNullOrEmpty(a_searchKey); |
|||
} |
|||
|
|||
public void Dispose() |
|||
{ |
|||
m_salesRepo.TransactionsChanged -= TransactionsChanged; |
|||
m_searchControl.SearchValueChanged -= SearchValueChanged; |
|||
m_salesRepo.FetchStart -= FetchStart; |
|||
m_salesRepo.FetchComplete -= FetchComplete; |
|||
} |
|||
private void SetParams() |
|||
{ |
|||
m_totalRevenue = (double)m_salesItems.Where(c => c.Status == "SOLD").Sum(t => t.Total).Value; |
|||
m_totalNbrRevenue = m_salesItems.Where(c => c.Status == "SOLD").Count(); |
|||
m_totalNbrCancelled = m_salesItems.Where(c => c.Status != "SOLD").Count(); |
|||
m_totalCancelledRevenue = (double)m_salesItems.Where(c => c.Status != "SOLD").Sum(t => t.Total).Value; |
|||
m_recent = false; |
|||
} |
|||
private void LoadTransactions() |
|||
{ |
|||
m_searchControl.SearchValueChanged -= SearchValueChanged; |
|||
m_searchControl.Clear(); |
|||
m_lookUpMode = false; |
|||
m_salesRepo.FetchTransaction(m_startDate.Value.Date, m_endDate.Value.Date); |
|||
m_searchControl.SearchValueChanged += SearchValueChanged; |
|||
} |
|||
} |
|||
} |
@ -0,0 +1,98 @@ |
|||
using Biskilog_Accounting.Client.Pages.Transactions.Elements; |
|||
using Biskilog_Accounting.Shared.CustomModels; |
|||
using Biskilog_Accounting.Shared.Interfaces; |
|||
using Biskilog_Accounting.Shared.POSModels; |
|||
using Radzen; |
|||
using System.Text.Json; |
|||
|
|||
namespace Biskilog_Accounting.Client.Repos |
|||
{ |
|||
public class MainInterfaceService : IMainInterface, ICompanyInfo |
|||
{ |
|||
private readonly HttpClient m_http; |
|||
private readonly DialogService m_dialogService; |
|||
private DateTime m_currentTradeDate; |
|||
private DateTime m_previousTradeDate; |
|||
private IEnumerable<Tblbranch> m_branches; |
|||
private Tblcompanydetail m_info; |
|||
|
|||
public MainInterfaceService(DialogService a_dialogService, HttpClient http) |
|||
{ |
|||
m_dialogService = a_dialogService; |
|||
m_currentTradeDate = new DateTime(2023, 05, 01); |
|||
m_previousTradeDate = new DateTime(2023, 04, 01); |
|||
m_http = http; |
|||
|
|||
} |
|||
|
|||
async Task OpenReceiptDialog(string a_receiptId) |
|||
{ |
|||
await m_dialogService.OpenSideAsync<ReceiptDialog>("Receipt", |
|||
new Dictionary<string, object>() { { "ReceiptId", a_receiptId } }, |
|||
options: new SideDialogOptions |
|||
{ |
|||
CloseDialogOnOverlayClick = true, |
|||
Position = DialogPosition.Right, |
|||
ShowMask = true, |
|||
ShowTitle = false, |
|||
}); |
|||
} |
|||
public void ShowReceipt(string a_receiptId) |
|||
{ |
|||
OpenReceiptDialog(a_receiptId); |
|||
} |
|||
|
|||
public DateOnly CurrentTradeDate() |
|||
{ |
|||
return DateOnly.FromDateTime(m_currentTradeDate); |
|||
} |
|||
|
|||
public DateOnly PreviousTradeDate() |
|||
{ |
|||
return DateOnly.FromDateTime(m_previousTradeDate); |
|||
} |
|||
|
|||
public IEnumerable<Tblbranch> FetchBranches() |
|||
{ |
|||
return m_branches; |
|||
} |
|||
|
|||
public async Task<Tblcompanydetail> GetCompanyInfoAsync() |
|||
{ |
|||
var response = await m_http.GetAsync($"api/companyinfo/info"); |
|||
if (response.IsSuccessStatusCode) |
|||
{ |
|||
var jsonContent = await response.Content.ReadAsStringAsync(); |
|||
var options = new JsonSerializerOptions { PropertyNameCaseInsensitive = true }; |
|||
var recent = JsonSerializer.Deserialize<Tblcompanydetail>(jsonContent, options); |
|||
m_info = recent; |
|||
return recent; |
|||
} |
|||
return null; |
|||
} |
|||
|
|||
public async Task<IEnumerable<Tblbranch>> GetBranches() |
|||
{ |
|||
var response = await m_http.GetAsync($"api/companyinfo/branches"); |
|||
if (response.IsSuccessStatusCode) |
|||
{ |
|||
var jsonContent = await response.Content.ReadAsStringAsync(); |
|||
var options = new JsonSerializerOptions { PropertyNameCaseInsensitive = true }; |
|||
var recent = JsonSerializer.Deserialize<IEnumerable<Tblbranch>>(jsonContent, options); |
|||
m_branches = recent; |
|||
return recent; |
|||
} |
|||
return null; |
|||
} |
|||
|
|||
public string GetCompanyName() |
|||
{ |
|||
return m_info.CompanyName; |
|||
} |
|||
|
|||
public string GetBranchName(string a_branchId) |
|||
{ |
|||
return m_branches.First(b => b.BranchId == a_branchId).BranchName; |
|||
} |
|||
} |
|||
} |
@ -0,0 +1,143 @@ |
|||
using Biskilog_Accounting.Shared.CustomModels; |
|||
using Biskilog_Accounting.Shared.Interfaces; |
|||
using System.Text.Json; |
|||
using Biskilog_Accounting.Shared.POSModels; |
|||
using System.Text.RegularExpressions; |
|||
|
|||
namespace Biskilog_Accounting.Client.Repos |
|||
{ |
|||
public class ProductRepository : IProduct |
|||
{ |
|||
private IEnumerable<ProductItem> m_products; |
|||
private IEnumerable<Unitofmeasure> m_units; |
|||
private IEnumerable<Tblbrand> m_brands; |
|||
private IEnumerable<Tblcategory> m_categories; |
|||
private readonly HttpClient m_http; |
|||
|
|||
public event EventHandler ProductsChanged; |
|||
public event EventHandler UnitsChanged; |
|||
public event EventHandler BrandsChanged; |
|||
public event EventHandler CategoriesChanged; |
|||
|
|||
public ProductRepository(HttpClient a_http) |
|||
{ |
|||
m_products = new List<ProductItem>(); |
|||
m_units = new List<Unitofmeasure>(); |
|||
m_brands = new List<Tblbrand>(); |
|||
m_categories = new List<Tblcategory>(); |
|||
m_http = a_http; |
|||
} |
|||
public async Task FetchProducts() |
|||
{ |
|||
var response = await m_http.GetAsync($"api/products/fetch"); |
|||
if (response.IsSuccessStatusCode) |
|||
{ |
|||
var jsonContent = await response.Content.ReadAsStringAsync(); |
|||
var options = new JsonSerializerOptions { PropertyNameCaseInsensitive = true }; |
|||
var products = JsonSerializer.Deserialize<List<ProductItem>>(jsonContent, options); |
|||
m_products = products; |
|||
ProductsChanged?.Invoke(this, EventArgs.Empty); |
|||
} |
|||
} |
|||
|
|||
public ProductItem GetProductById(string a_id) |
|||
{ |
|||
if (m_products.Count() > 0) |
|||
{ |
|||
return m_products.First(i => i.Product.Pcode == a_id); |
|||
} |
|||
return null; |
|||
} |
|||
|
|||
public ProductItem GetProductByName(string name) |
|||
{ |
|||
throw new NotImplementedException(); |
|||
} |
|||
|
|||
public IEnumerable<ProductItem> GetProducts(string a_productKey) |
|||
{ |
|||
a_productKey = Regex.Replace(a_productKey, @"\s", "").ToLower(); |
|||
return m_products.Where(p => Regex.Replace(p.Product!.ProductName!, @"\s", "").ToLower().StartsWith(a_productKey) || |
|||
Regex.Replace(p.Product!.Pcode!, @"\s", "").ToLower().StartsWith(a_productKey) || |
|||
Regex.Replace(p.Product!.Pdesc!, @"\s", "").ToLower().StartsWith(a_productKey)); |
|||
} |
|||
|
|||
public void RefreshList() |
|||
{ |
|||
throw new NotImplementedException(); |
|||
} |
|||
|
|||
public IEnumerable<Unitofmeasure> GetUnitofmeasures() |
|||
{ |
|||
return m_units; |
|||
} |
|||
|
|||
public async Task FetchUnits() |
|||
{ |
|||
var response = await m_http.GetAsync($"api/products/units"); |
|||
if (response.IsSuccessStatusCode) |
|||
{ |
|||
var jsonContent = await response.Content.ReadAsStringAsync(); |
|||
var options = new JsonSerializerOptions { PropertyNameCaseInsensitive = true }; |
|||
var units = JsonSerializer.Deserialize<List<Unitofmeasure>>(jsonContent, options); |
|||
m_units = units; |
|||
UnitsChanged?.Invoke(this, EventArgs.Empty); |
|||
} |
|||
} |
|||
|
|||
public string GetUnitName(string a_unitCode) |
|||
{ |
|||
return m_units?.FirstOrDefault(u => u.UnitCode == a_unitCode)?.Unitname; |
|||
} |
|||
|
|||
public IEnumerable<Tblbrand> GetBrands(string a_brandKey = "") |
|||
{ |
|||
a_brandKey = Regex.Replace(a_brandKey, @"\s", "").ToLower(); |
|||
return m_brands.Where(b => Regex.Replace(b.Id, @"\s", "").ToLower().StartsWith(a_brandKey) || |
|||
Regex.Replace(b.Brand!, @"\s", "").ToLower().StartsWith(a_brandKey)); |
|||
} |
|||
|
|||
public IEnumerable<Tblcategory> GetCategories(string a_categoryKey = "") |
|||
{ |
|||
a_categoryKey = Regex.Replace(a_categoryKey, @"\s", "").ToLower(); |
|||
return m_categories.Where(c => Regex.Replace(c.Id, @"\s", "").ToLower().StartsWith(a_categoryKey) || |
|||
Regex.Replace(c.Category!, @"\s", "").ToLower().StartsWith(a_categoryKey)); |
|||
} |
|||
|
|||
public async Task FetchBrands() |
|||
{ |
|||
var response = await m_http.GetAsync($"api/products/brands"); |
|||
if (response.IsSuccessStatusCode) |
|||
{ |
|||
var jsonContent = await response.Content.ReadAsStringAsync(); |
|||
var options = new JsonSerializerOptions { PropertyNameCaseInsensitive = true }; |
|||
var brands = JsonSerializer.Deserialize<List<Tblbrand>>(jsonContent, options); |
|||
m_brands = brands; |
|||
BrandsChanged?.Invoke(this, EventArgs.Empty); |
|||
} |
|||
} |
|||
|
|||
public async Task FetchCategories() |
|||
{ |
|||
var response = await m_http.GetAsync($"api/products/categories"); |
|||
if (response.IsSuccessStatusCode) |
|||
{ |
|||
var jsonContent = await response.Content.ReadAsStringAsync(); |
|||
var options = new JsonSerializerOptions { PropertyNameCaseInsensitive = true }; |
|||
var categories = JsonSerializer.Deserialize<List<Tblcategory>>(jsonContent, options); |
|||
m_categories = categories; |
|||
CategoriesChanged?.Invoke(this, EventArgs.Empty); |
|||
} |
|||
} |
|||
|
|||
public IEnumerable<ProductItem> GetLowstockItems() |
|||
{ |
|||
throw new NotImplementedException(); |
|||
} |
|||
|
|||
public Task FetchLowStockProducts() |
|||
{ |
|||
throw new NotImplementedException(); |
|||
} |
|||
} |
|||
} |
@ -0,0 +1,98 @@ |
|||
using Biskilog_Accounting.Shared.CustomModels; |
|||
using Biskilog_Accounting.Shared.Interfaces; |
|||
using Biskilog_Accounting.Shared.POSModels; |
|||
using System.Text.Json; |
|||
|
|||
namespace Biskilog_Accounting.Client.Repos |
|||
{ |
|||
public class SalesRepository : ISalesInterface |
|||
{ |
|||
private IEnumerable<SaleItem> m_transactions; |
|||
private IEnumerable<SaleItem> m_recentTransactions; |
|||
private readonly HttpClient m_http; |
|||
|
|||
public event EventHandler TransactionsChanged; |
|||
public event EventHandler FetchComplete; |
|||
public event EventHandler FetchStart; |
|||
|
|||
public SalesRepository(HttpClient a_http) |
|||
{ |
|||
m_recentTransactions = m_transactions = new List<SaleItem>(); |
|||
m_http = a_http; |
|||
} |
|||
|
|||
public async Task FetchRecentTransaction(int a_limit) |
|||
{ |
|||
FetchStart?.Invoke(this, EventArgs.Empty); |
|||
var response = await m_http.GetAsync($"api/analytics/sales/recent/{a_limit}"); |
|||
if (response.IsSuccessStatusCode) |
|||
{ |
|||
var jsonContent = await response.Content.ReadAsStringAsync(); |
|||
var options = new JsonSerializerOptions { PropertyNameCaseInsensitive = true }; |
|||
var recent = JsonSerializer.Deserialize<List<SaleItem>>(jsonContent, options); |
|||
m_recentTransactions = recent; |
|||
} |
|||
FetchComplete?.Invoke(this, EventArgs.Empty); |
|||
} |
|||
|
|||
public async Task FetchTransaction(DateTime a_start, DateTime a_end) |
|||
{ |
|||
FetchStart?.Invoke(this, EventArgs.Empty); |
|||
string start = a_start.ToString("yyyy-MM-dd"); |
|||
string end = a_end.ToString("yyyy-MM-dd"); |
|||
var response = await m_http.GetAsync($"api/sales/transactions/{start}/{end}"); |
|||
if (response.IsSuccessStatusCode) |
|||
{ |
|||
var jsonContent = await response.Content.ReadAsStringAsync(); |
|||
var options = new JsonSerializerOptions { PropertyNameCaseInsensitive = true }; |
|||
var recent = JsonSerializer.Deserialize<List<SaleItem>>(jsonContent, options); |
|||
m_transactions = recent; |
|||
TransactionsChanged?.Invoke(this, new EventArgs()); |
|||
} |
|||
FetchComplete?.Invoke(this, EventArgs.Empty); |
|||
} |
|||
|
|||
public IEnumerable<SaleItem> GetTransactions(DateTime a_start, DateTime a_end) |
|||
{ |
|||
return m_transactions; |
|||
} |
|||
|
|||
public IEnumerable<SaleItem> GetRecentTransaction() |
|||
{ |
|||
return m_recentTransactions; |
|||
} |
|||
|
|||
public async Task FetchReceipt(string a_receiptId) |
|||
{ |
|||
FetchStart?.Invoke(this, EventArgs.Empty); |
|||
var response = await m_http.GetAsync($"api/sales/transactions/lookup/{a_receiptId}"); |
|||
if (response.IsSuccessStatusCode) |
|||
{ |
|||
var jsonContent = await response.Content.ReadAsStringAsync(); |
|||
var options = new JsonSerializerOptions { PropertyNameCaseInsensitive = true }; |
|||
var recent = JsonSerializer.Deserialize<List<SaleItem>>(jsonContent, options); |
|||
m_transactions = recent; |
|||
TransactionsChanged?.Invoke(this, new EventArgs()); |
|||
} |
|||
FetchComplete?.Invoke(this, EventArgs.Empty); |
|||
} |
|||
|
|||
public IEnumerable<SaleItem> GetReceipt(string a_receiptId) |
|||
{ |
|||
throw new NotImplementedException(); |
|||
} |
|||
|
|||
public async Task<IEnumerable<Tblcart>> GetReceiptDetail(string a_receiptId) |
|||
{ |
|||
var response = await m_http.GetAsync($"api/sales/receipt/lookup/{a_receiptId}"); |
|||
if (response.IsSuccessStatusCode) |
|||
{ |
|||
var jsonContent = await response.Content.ReadAsStringAsync(); |
|||
var options = new JsonSerializerOptions { PropertyNameCaseInsensitive = true }; |
|||
var recent = JsonSerializer.Deserialize<List<Tblcart>>(jsonContent, options); |
|||
return recent; |
|||
} |
|||
return null; |
|||
} |
|||
} |
|||
} |
After Width: | Height: | Size: 19 KiB |
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -0,0 +1,37 @@ |
|||
using Biskilog_Accounting.Shared.Interfaces; |
|||
using Biskilog_Accounting.Shared.POSModels; |
|||
using Microsoft.AspNetCore.Authorization; |
|||
using Microsoft.AspNetCore.Http; |
|||
using Microsoft.AspNetCore.Mvc; |
|||
|
|||
namespace Biskilog_Accounting.Server.Controllers |
|||
{ |
|||
[Route("api/[controller]")]
|
|||
[ApiController] |
|||
public class CompanyInfoController : ControllerBase |
|||
{ |
|||
private readonly ICompanyInfo m_companyInfo; |
|||
public CompanyInfoController(ICompanyInfo a_companyInfo) |
|||
{ |
|||
m_companyInfo = a_companyInfo; |
|||
} |
|||
/// <summary>
|
|||
/// Endpoint to return company information
|
|||
/// </summary>
|
|||
[Authorize] |
|||
[HttpGet, Route("info")] |
|||
public Task<Tblcompanydetail> GetCompanyInfo() |
|||
{ |
|||
return m_companyInfo.GetCompanyInfoAsync(); |
|||
} |
|||
/// <summary>
|
|||
/// Endpoint to return branch information in the company
|
|||
/// </summary>
|
|||
[Authorize] |
|||
[HttpGet, Route("branches")] |
|||
public Task<IEnumerable<Tblbranch>> Getbranches() |
|||
{ |
|||
return m_companyInfo.GetBranches(); |
|||
} |
|||
} |
|||
} |
@ -0,0 +1,55 @@ |
|||
using Biskilog_Accounting.Shared.CustomModels; |
|||
using Biskilog_Accounting.Shared.Interfaces; |
|||
using Biskilog_Accounting.Shared.POSModels; |
|||
using Microsoft.AspNetCore.Authorization; |
|||
using Microsoft.AspNetCore.Mvc; |
|||
|
|||
namespace Biskilog_Accounting.Server.Controllers |
|||
{ |
|||
[Route("api/[controller]")]
|
|||
[ApiController] |
|||
public class ProductsController : ControllerBase |
|||
{ |
|||
private readonly IProduct m_productService; |
|||
public ProductsController(IProduct a_productService) |
|||
{ |
|||
m_productService = a_productService; |
|||
} |
|||
/// <summary>
|
|||
/// Endpoint to return all units of measure for products
|
|||
/// </summary>
|
|||
[Authorize] |
|||
[HttpGet, Route("units")] |
|||
public IEnumerable<Unitofmeasure> GetUnits() |
|||
{ |
|||
return m_productService.GetUnitofmeasures(); |
|||
} |
|||
/// <summary>
|
|||
/// Endpoint to return all products
|
|||
/// </summary>
|
|||
[Authorize] |
|||
[HttpGet, Route("fetch")] |
|||
public IEnumerable<ProductItem> GetProducts() |
|||
{ |
|||
return m_productService.GetProducts(); |
|||
} |
|||
/// <summary>
|
|||
/// Endpoint to return all product categories
|
|||
/// </summary>
|
|||
[Authorize] |
|||
[HttpGet, Route("categories")] |
|||
public IEnumerable<Tblcategory> GetCategories() |
|||
{ |
|||
return m_productService.GetCategories(); |
|||
} |
|||
/// <summary>
|
|||
/// Endpoint to return all product brands
|
|||
/// </summary>
|
|||
[Authorize] |
|||
[HttpGet, Route("brands")] |
|||
public IEnumerable<Tblbrand> GetBrands() |
|||
{ |
|||
return m_productService.GetBrands(); |
|||
} |
|||
} |
|||
} |
@ -0,0 +1,49 @@ |
|||
using Biskilog_Accounting.Shared.CustomModels; |
|||
using Biskilog_Accounting.Shared.Interfaces; |
|||
using Biskilog_Accounting.Shared.POSModels; |
|||
using Microsoft.AspNetCore.Authorization; |
|||
using Microsoft.AspNetCore.Http; |
|||
using Microsoft.AspNetCore.Mvc; |
|||
|
|||
namespace Biskilog_Accounting.Server.Controllers |
|||
{ |
|||
[Route("api/[controller]")]
|
|||
[ApiController] |
|||
public class SalesController : ControllerBase |
|||
{ |
|||
private readonly ISalesInterface m_salesService; |
|||
public SalesController(ISalesInterface a_salesService) |
|||
{ |
|||
m_salesService = a_salesService; |
|||
} |
|||
/// <summary>
|
|||
/// Endpoint to return Sales within a specified period
|
|||
/// </summary>
|
|||
/// <param name="a_start"></param>
|
|||
/// <param name="a_end"></param>
|
|||
[Authorize] |
|||
[HttpGet, Route("transactions/{a_start}/{a_end}")] |
|||
public IEnumerable<SaleItem> GetSalesAsync(DateTime a_start, DateTime a_end) |
|||
{ |
|||
return m_salesService.GetTransactions(a_start, a_end); |
|||
} |
|||
/// <summary>
|
|||
/// Endpoint to return Sales using the specified transaction id
|
|||
/// </summary>
|
|||
[Authorize] |
|||
[HttpGet, Route("transactions/lookup/{a_receipt}")] |
|||
public IEnumerable<SaleItem> GetSaleAsync(string a_receipt) |
|||
{ |
|||
return m_salesService.GetReceipt(a_receipt); |
|||
} |
|||
/// <summary>
|
|||
/// Endpoint to return receipt details
|
|||
/// </summary>
|
|||
[Authorize] |
|||
[HttpGet, Route("receipt/lookup/{a_receipt}")] |
|||
public IEnumerable<Tblcart> GetReceiptAsync(string a_receipt) |
|||
{ |
|||
return m_salesService.GetReceiptDetail(a_receipt).Result.ToList(); |
|||
} |
|||
} |
|||
} |
@ -0,0 +1,53 @@ |
|||
using Biskilog_Accounting.Server.POSModels; |
|||
using Biskilog_Accounting.Shared.Interfaces; |
|||
using Biskilog_Accounting.Shared.POSModels; |
|||
|
|||
namespace Biskilog_Accounting.Server.Services |
|||
{ |
|||
public class CompanyService : ICompanyInfo |
|||
{ |
|||
private readonly BiskAcdbContext m_context; |
|||
private readonly ITokenService m_tokenService; |
|||
private readonly HttpContext m_httpContext; |
|||
|
|||
private Tblcompanydetail m_companyInfo { get; set; } |
|||
private IEnumerable<Tblbranch> m_companyBranches { get; set; } |
|||
public CompanyService(BiskAcdbContext a_context, ITokenService a_tokenService, IHttpContextAccessor a_httpContextAccessor) |
|||
{ |
|||
m_context = a_context; |
|||
m_tokenService = a_tokenService; |
|||
m_httpContext = a_httpContextAccessor?.HttpContext; |
|||
m_companyInfo = new Tblcompanydetail(); |
|||
m_companyBranches = new List<Tblbranch>(); |
|||
|
|||
GetCompanyInfoAsync(); |
|||
GetBranches(); |
|||
} |
|||
public IEnumerable<Tblbranch> FetchBranches() |
|||
{ |
|||
return m_companyBranches; |
|||
} |
|||
|
|||
public async Task<IEnumerable<Tblbranch>> GetBranches() |
|||
{ |
|||
m_companyBranches = m_context.Tblbranches; |
|||
return await Task.FromResult(m_companyBranches); |
|||
} |
|||
|
|||
public string GetBranchName(string a_branchId) |
|||
{ |
|||
return m_companyBranches.FirstOrDefault(b => b.BranchId == a_branchId).BranchName; |
|||
} |
|||
|
|||
public Task<Tblcompanydetail> GetCompanyInfoAsync() |
|||
{ |
|||
m_companyInfo = m_context.Tblcompanydetails.First(); |
|||
return Task.FromResult(m_companyInfo); |
|||
} |
|||
|
|||
public string GetCompanyName() |
|||
{ |
|||
return m_companyInfo.CompanyName; |
|||
} |
|||
} |
|||
} |
@ -0,0 +1,200 @@ |
|||
using Biskilog_Accounting.Server.POSModels; |
|||
using Biskilog_Accounting.Shared.CustomModels; |
|||
using Biskilog_Accounting.Shared.Enums; |
|||
using Biskilog_Accounting.Shared.Interfaces; |
|||
using Biskilog_Accounting.Shared.POSModels; |
|||
using Microsoft.EntityFrameworkCore; |
|||
using Microsoft.Net.Http.Headers; |
|||
using MySqlConnector; |
|||
using System.Data; |
|||
using System.Data.Common; |
|||
|
|||
namespace Biskilog_Accounting.Server.Services |
|||
{ |
|||
public class ProductRepo : IProduct |
|||
{ |
|||
private readonly BiskAcdbContext m_context; |
|||
private readonly ITokenService m_tokenService; |
|||
private readonly HttpContext m_httpContext; |
|||
|
|||
public event EventHandler ProductsChanged; |
|||
public event EventHandler UnitsChanged; |
|||
public event EventHandler BrandsChanged; |
|||
public event EventHandler CategoriesChanged; |
|||
|
|||
public ProductRepo(BiskAcdbContext a_context, ITokenService a_tokenService, IHttpContextAccessor a_httpContextAccessor) |
|||
{ |
|||
m_context = a_context; |
|||
m_tokenService = a_tokenService; |
|||
m_httpContext = a_httpContextAccessor?.HttpContext; |
|||
} |
|||
/// <summary>
|
|||
/// Gets all products from the server
|
|||
/// </summary>
|
|||
/// <returns></returns>
|
|||
public IEnumerable<ProductItem> GetProducts(string a_productKey = "") |
|||
{ |
|||
string token = m_httpContext.Request.Headers[HeaderNames.Authorization]!; |
|||
|
|||
if (AuthEnums.Valid == m_tokenService.ValidateToken(token)) |
|||
{ |
|||
IEnumerable<string> accessiblebranches = m_tokenService.BranchIds(token); |
|||
|
|||
using (var command = m_context.Database.GetDbConnection().CreateCommand()) |
|||
{ |
|||
command.CommandText = "CALL GetProducts(@p0)"; |
|||
command.Parameters.Add(new MySqlParameter("@p0", string.Join(", ", accessiblebranches.ToArray()))); |
|||
|
|||
m_context.Database.OpenConnection(); |
|||
|
|||
using (var reader = command.ExecuteReader()) |
|||
{ |
|||
while (reader.Read()) |
|||
{ |
|||
List<ProductUnits> pUnits = new List<ProductUnits>(); |
|||
|
|||
yield return new ProductItem |
|||
{ |
|||
Product = new Tblproduct |
|||
{ |
|||
Pcode = reader.GetString(0), |
|||
ProductName = reader.GetString(1), |
|||
Pdesc = reader.GetString(2), |
|||
BaseUnit = reader.GetString(3), |
|||
Costprice = reader.GetDecimal(4), |
|||
Status = reader.GetString(5), |
|||
Price = reader.GetDecimal(6), |
|||
BranchId = reader.GetString(7), |
|||
}, |
|||
BaseUnit = reader.GetString(3), |
|||
Stock = new Tblinventory |
|||
{ |
|||
Quantity = reader.GetInt32(8) |
|||
}, |
|||
Restocklevel = new Restocklevel |
|||
{ |
|||
WarnLevel = reader.GetInt32(9), |
|||
Unit = reader.GetString(10), |
|||
}, |
|||
Units = GetAltUnits(reader) |
|||
}; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
private List<ProductUnits> GetAltUnits(DbDataReader a_reader) |
|||
{ |
|||
List<ProductUnits> pUnits = new List<ProductUnits>(); |
|||
for (int i = 1; i < 5; i++) |
|||
{ |
|||
if (!a_reader.IsDBNull(a_reader.GetOrdinal($"AltUnit{i}"))) |
|||
{ |
|||
pUnits.Add(new ProductUnits |
|||
{ |
|||
UnitCode = a_reader.GetFieldValue<string>($"AltUnit{i}"), |
|||
QuantityUnit = a_reader.GetFieldValue<int>($"AltUnit{i}QTY"), |
|||
PriceUnit = a_reader.GetFieldValue<decimal>($"AltUnit{i}Price"), |
|||
DistinctiveCode = a_reader.GetFieldValue<string>($"AltUnit{i}distinctiveCode") |
|||
}); |
|||
} |
|||
else |
|||
{ |
|||
return pUnits; |
|||
} |
|||
} |
|||
return pUnits; |
|||
} |
|||
|
|||
public IEnumerable<Unitofmeasure> GetUnitofmeasures() |
|||
{ |
|||
string token = m_httpContext.Request.Headers[HeaderNames.Authorization]!; |
|||
|
|||
if (AuthEnums.Valid == m_tokenService.ValidateToken(token)) |
|||
{ |
|||
IEnumerable<string> accessiblebranches = m_tokenService.BranchIds(token); |
|||
|
|||
return m_context.Unitofmeasures.Where(b => accessiblebranches.Contains(b.BranchId)); |
|||
} |
|||
return new List<Unitofmeasure>(); |
|||
} |
|||
|
|||
|
|||
|
|||
public IEnumerable<Tblbrand> GetBrands(string a_brandKey = "") |
|||
{ |
|||
string token = m_httpContext.Request.Headers[HeaderNames.Authorization]!; |
|||
|
|||
if (AuthEnums.Valid == m_tokenService.ValidateToken(token)) |
|||
{ |
|||
IEnumerable<string> accessiblebranches = m_tokenService.BranchIds(token); |
|||
|
|||
return m_context.Tblbrands.Where(b => accessiblebranches.Contains(b.BranchId)); |
|||
} |
|||
return new List<Tblbrand>(); |
|||
} |
|||
|
|||
public IEnumerable<Tblcategory> GetCategories(string a_categoryKey = "") |
|||
{ |
|||
string token = m_httpContext.Request.Headers[HeaderNames.Authorization]!; |
|||
|
|||
if (AuthEnums.Valid == m_tokenService.ValidateToken(token)) |
|||
{ |
|||
IEnumerable<string> accessiblebranches = m_tokenService.BranchIds(token); |
|||
|
|||
return m_context.Tblcategories.Where(b => accessiblebranches.Contains(b.BranchId)); |
|||
} |
|||
return new List<Tblcategory>(); |
|||
} |
|||
|
|||
#region Only Need to implement in the client Side
|
|||
public Task FetchUnits() |
|||
{ |
|||
throw new NotImplementedException(); |
|||
} |
|||
public Task FetchProducts() |
|||
{ |
|||
throw new NotImplementedException(); |
|||
} |
|||
|
|||
public ProductItem GetProductById(string a_id) |
|||
{ |
|||
throw new NotImplementedException(); |
|||
} |
|||
|
|||
public ProductItem GetProductByName(string name) |
|||
{ |
|||
throw new NotImplementedException(); |
|||
} |
|||
|
|||
public void RefreshList() |
|||
{ |
|||
throw new NotImplementedException(); |
|||
} |
|||
|
|||
public string GetUnitName(string a_unitCode) |
|||
{ |
|||
throw new NotImplementedException(); |
|||
} |
|||
public Task FetchBrands() |
|||
{ |
|||
throw new NotImplementedException(); |
|||
} |
|||
|
|||
public Task FetchCategories() |
|||
{ |
|||
throw new NotImplementedException(); |
|||
} |
|||
|
|||
public IEnumerable<ProductItem> GetLowstockItems() |
|||
{ |
|||
throw new NotImplementedException(); |
|||
} |
|||
|
|||
public Task FetchLowStockProducts() |
|||
{ |
|||
throw new NotImplementedException(); |
|||
} |
|||
} |
|||
#endregion
|
|||
} |
@ -0,0 +1,169 @@ |
|||
using Biskilog_Accounting.Server.POSModels; |
|||
using Biskilog_Accounting.Shared.CustomModels; |
|||
using Biskilog_Accounting.Shared.Enums; |
|||
using Biskilog_Accounting.Shared.Interfaces; |
|||
using Biskilog_Accounting.Shared.POSModels; |
|||
using Microsoft.EntityFrameworkCore; |
|||
using Microsoft.Net.Http.Headers; |
|||
using MySqlConnector; |
|||
using System.Drawing.Drawing2D; |
|||
|
|||
namespace Biskilog_Accounting.Server.Services |
|||
{ |
|||
public class SalesService : ISalesInterface |
|||
{ |
|||
private readonly BiskAcdbContext m_context; |
|||
private readonly ITokenService m_tokenService; |
|||
private readonly HttpContext m_httpContext; |
|||
|
|||
public event EventHandler TransactionsChanged; |
|||
public event EventHandler FetchComplete; |
|||
public event EventHandler FetchStart; |
|||
|
|||
public SalesService(BiskAcdbContext a_context, ITokenService a_tokenService, IHttpContextAccessor a_httpContextAccessor) |
|||
{ |
|||
m_context = a_context; |
|||
m_tokenService = a_tokenService; |
|||
m_httpContext = a_httpContextAccessor?.HttpContext; |
|||
} |
|||
|
|||
public Task FetchRecentTransaction(int a_limit) |
|||
{ |
|||
throw new NotImplementedException(); |
|||
} |
|||
|
|||
public IEnumerable<SaleItem> GetRecentTransaction() |
|||
{ |
|||
throw new NotImplementedException(); |
|||
} |
|||
|
|||
public IEnumerable<SaleItem> GetTransactions(DateTime a_start, DateTime a_end) |
|||
{ |
|||
string token = m_httpContext.Request.Headers[HeaderNames.Authorization]!; |
|||
|
|||
if (AuthEnums.Valid == m_tokenService.ValidateToken(token)) |
|||
{ |
|||
IEnumerable<string> accessiblebranches = m_tokenService.BranchIds(token); |
|||
|
|||
using (var command = m_context.Database.GetDbConnection().CreateCommand()) |
|||
{ |
|||
command.CommandText = "CALL GetTransactionsByDate(@p0,@p1,@p2)"; |
|||
command.Parameters.Add(new MySqlParameter("@p0", a_start.ToString("yyyy-MM-dd"))); |
|||
command.Parameters.Add(new MySqlParameter("@p1", a_end.ToString("yyyy-MM-dd"))); |
|||
command.Parameters.Add(new MySqlParameter("@p2", string.Join(", ", accessiblebranches.ToArray()))); |
|||
|
|||
m_context.Database.OpenConnection(); |
|||
|
|||
using (var reader = command.ExecuteReader()) |
|||
{ |
|||
while (reader.Read()) |
|||
{ |
|||
yield return new SaleItem |
|||
{ |
|||
Transno = reader.GetString(0), |
|||
Total = (decimal)reader.GetDouble(1), |
|||
Date = reader.GetDateTime(2), |
|||
Cashier = reader.GetString(3), |
|||
BranchId = reader.GetString(4), |
|||
Customer = reader.GetString(5), |
|||
Status = reader.GetString(6), |
|||
}; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
public Task FetchTransaction(DateTime a_start, DateTime a_end) |
|||
{ |
|||
throw new NotImplementedException(); |
|||
} |
|||
|
|||
public Task FetchReceipt(string a_receiptId) |
|||
{ |
|||
throw new NotImplementedException(); |
|||
} |
|||
|
|||
public IEnumerable<SaleItem> GetReceipt(string a_receiptId) |
|||
{ |
|||
string token = m_httpContext.Request.Headers[HeaderNames.Authorization]!; |
|||
|
|||
if (AuthEnums.Valid == m_tokenService.ValidateToken(token)) |
|||
{ |
|||
IEnumerable<string> accessiblebranches = m_tokenService.BranchIds(token); |
|||
|
|||
using (var command = m_context.Database.GetDbConnection().CreateCommand()) |
|||
{ |
|||
command.CommandText = "CALL GetTransactionsById(@p0,@p1)"; |
|||
command.Parameters.Add(new MySqlParameter("@p0", a_receiptId)); |
|||
command.Parameters.Add(new MySqlParameter("@p1", string.Join(", ", accessiblebranches.ToArray()))); |
|||
|
|||
m_context.Database.OpenConnection(); |
|||
|
|||
using (var reader = command.ExecuteReader()) |
|||
{ |
|||
while (reader.Read()) |
|||
{ |
|||
yield return new SaleItem |
|||
{ |
|||
Transno = reader.GetString(0), |
|||
Total = (decimal)reader.GetDouble(1), |
|||
Date = reader.GetDateTime(2), |
|||
Cashier = reader.GetString(3), |
|||
BranchId = reader.GetString(4), |
|||
Customer = reader.GetString(5), |
|||
Status = reader.GetString(6), |
|||
}; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
public Task<IEnumerable<Tblcart>> GetReceiptDetail(string a_receiptId) |
|||
{ |
|||
List<Tblcart> details = new List<Tblcart>(); |
|||
string token = m_httpContext.Request.Headers[HeaderNames.Authorization]!; |
|||
|
|||
if (AuthEnums.Valid == m_tokenService.ValidateToken(token)) |
|||
{ |
|||
IEnumerable<string> accessiblebranches = m_tokenService.BranchIds(token); |
|||
|
|||
using (var command = m_context.Database.GetDbConnection().CreateCommand()) |
|||
{ |
|||
command.CommandText = "CALL GetReceiptDetails(@p0,@p1)"; |
|||
command.Parameters.Add(new MySqlParameter("@p0", a_receiptId)); |
|||
command.Parameters.Add(new MySqlParameter("@p1", string.Join(", ", accessiblebranches.ToArray()))); |
|||
|
|||
m_context.Database.OpenConnection(); |
|||
|
|||
using (var reader = command.ExecuteReader()) |
|||
{ |
|||
while (reader.Read()) |
|||
{ |
|||
details.Add(new Tblcart |
|||
{ |
|||
Transno = a_receiptId, |
|||
Id = reader.GetString(0), |
|||
Quantity = reader.GetInt32(1), |
|||
Date = reader.GetDateTime(2), |
|||
Price = reader.GetDecimal(3), |
|||
Cashier = reader.GetString(4), |
|||
Status = reader.GetString(5), |
|||
Total = (decimal)reader.GetDouble(6), |
|||
Unit = reader.GetString(7), |
|||
Costprice = reader.GetDecimal(8), |
|||
BranchId = reader.GetString(9), |
|||
CountId = reader.GetString(10), |
|||
Tendered = reader.GetDecimal(11), |
|||
Balance = reader.GetDecimal(12), |
|||
ValueAddTax = reader.GetDecimal(13) |
|||
}); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
return Task.FromResult(details.AsEnumerable()); |
|||
} |
|||
} |
|||
} |
@ -0,0 +1,26 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using System.Text; |
|||
using System.Threading.Tasks; |
|||
|
|||
namespace Biskilog_Accounting.Shared.CustomModels |
|||
{ |
|||
public class ProductUnits |
|||
{ |
|||
public string? Pcode { get; set; } |
|||
|
|||
public string? UnitCode { get; set; } |
|||
public string? UnitName { get; set; } |
|||
|
|||
public string? UnitBarcode { get; set; } |
|||
|
|||
public decimal? PriceUnit { get; set; } |
|||
|
|||
public int? QuantityUnit { get; set; } |
|||
|
|||
public string DistinctiveCode { get; set; } = null!; |
|||
|
|||
public string BranchId { get; set; } = null!; |
|||
} |
|||
} |
@ -0,0 +1,18 @@ |
|||
using Biskilog_Accounting.Shared.POSModels; |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using System.Text; |
|||
using System.Threading.Tasks; |
|||
|
|||
namespace Biskilog_Accounting.Shared.Interfaces |
|||
{ |
|||
public interface ICompanyInfo |
|||
{ |
|||
IEnumerable<Tblbranch> FetchBranches(); |
|||
Task<Tblcompanydetail> GetCompanyInfoAsync(); |
|||
Task<IEnumerable<Tblbranch>> GetBranches(); |
|||
string GetCompanyName(); |
|||
string GetBranchName(string a_branchId); |
|||
} |
|||
} |
@ -0,0 +1,15 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using System.Text; |
|||
using System.Threading.Tasks; |
|||
|
|||
namespace Biskilog_Accounting.Shared.Interfaces |
|||
{ |
|||
public interface IMainInterface |
|||
{ |
|||
void ShowReceipt(string a_receipt); |
|||
DateOnly CurrentTradeDate(); |
|||
DateOnly PreviousTradeDate(); |
|||
} |
|||
} |
@ -0,0 +1,32 @@ |
|||
using Biskilog_Accounting.Shared.CustomModels; |
|||
using Biskilog_Accounting.Shared.POSModels; |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using System.Text; |
|||
using System.Threading.Tasks; |
|||
|
|||
namespace Biskilog_Accounting.Shared.Interfaces |
|||
{ |
|||
public interface IProduct |
|||
{ |
|||
IEnumerable<Unitofmeasure> GetUnitofmeasures(); |
|||
IEnumerable<ProductItem> GetProducts(string a_productKey = ""); |
|||
IEnumerable<Tblbrand> GetBrands(string a_brandKey = ""); |
|||
IEnumerable<Tblcategory> GetCategories(string a_categoryKey = ""); |
|||
IEnumerable<ProductItem> GetLowstockItems(); |
|||
Task FetchProducts(); |
|||
Task FetchLowStockProducts(); |
|||
Task FetchUnits(); |
|||
Task FetchBrands(); |
|||
Task FetchCategories(); |
|||
void RefreshList(); |
|||
ProductItem GetProductById(string a_id); |
|||
ProductItem GetProductByName(string name); |
|||
string GetUnitName(string a_unitCode); |
|||
event EventHandler ProductsChanged; |
|||
event EventHandler UnitsChanged; |
|||
event EventHandler BrandsChanged; |
|||
event EventHandler CategoriesChanged; |
|||
} |
|||
} |
@ -0,0 +1,24 @@ |
|||
using Biskilog_Accounting.Shared.CustomModels; |
|||
using Biskilog_Accounting.Shared.POSModels; |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using System.Text; |
|||
using System.Threading.Tasks; |
|||
|
|||
namespace Biskilog_Accounting.Shared.Interfaces |
|||
{ |
|||
public interface ISalesInterface |
|||
{ |
|||
Task FetchRecentTransaction(int a_limit); |
|||
Task FetchTransaction(DateTime a_start, DateTime a_end); |
|||
IEnumerable<SaleItem> GetTransactions(DateTime a_start, DateTime a_end); |
|||
IEnumerable<SaleItem> GetRecentTransaction(); |
|||
Task FetchReceipt(string a_receiptId); |
|||
IEnumerable<SaleItem> GetReceipt(string a_receiptId); |
|||
Task<IEnumerable<Tblcart>> GetReceiptDetail(string a_receiptId); |
|||
event EventHandler TransactionsChanged; |
|||
event EventHandler FetchComplete; |
|||
event EventHandler FetchStart; |
|||
} |
|||
} |
@ -0,0 +1,16 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using System.Text; |
|||
using System.Threading.Tasks; |
|||
|
|||
namespace Biskilog_Accounting.Shared.Interfaces |
|||
{ |
|||
public interface ISearchService |
|||
{ |
|||
public event Action<string> SearchValueChanged; |
|||
public event Action ClearTextBox; |
|||
void PerformSearch(string a_searchKey); |
|||
void Clear(); |
|||
} |
|||
} |
@ -0,0 +1,33 @@ |
|||
using Biskilog_Accounting.Shared.Interfaces; |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using System.Text; |
|||
using System.Threading.Tasks; |
|||
|
|||
namespace Biskilog_Accounting.Shared.ServiceRepo |
|||
{ |
|||
public class SearchService : ISearchService |
|||
{ |
|||
public event Action<string> SearchValueChanged; |
|||
public event Action ClearTextBox; |
|||
|
|||
// Method that raises the event
|
|||
protected virtual void OnSearchValueChanged(string a_searchKey) |
|||
{ |
|||
SearchValueChanged?.Invoke(a_searchKey); |
|||
} |
|||
|
|||
// Method that triggers the event
|
|||
public void PerformSearch(string a_searchKey) |
|||
{ |
|||
OnSearchValueChanged(a_searchKey); |
|||
} |
|||
|
|||
public void Clear() |
|||
{ |
|||
ClearTextBox?.Invoke(); |
|||
} |
|||
} |
|||
|
|||
} |
Loading…
Reference in new issue