Benjamin Arhen
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