CompanyInventoryList sorting and tagging
This commit is contained in:
parent
8cd924e817
commit
1afbf20b15
56 changed files with 643 additions and 1028 deletions
|
@ -23,37 +23,74 @@
|
||||||
<div class="list-group mt-2">
|
<div class="list-group mt-2">
|
||||||
<div class="list-group-item d-print-none">
|
<div class="list-group-item d-print-none">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-sm-4 action-link-element" @onclick="@(() => SortProducts(ProductSort.Desc))"><i class="bi-sort-alpha-down"></i> Navn <i class="bi-sort-alpha-up-alt"></i></div>
|
@*
|
||||||
<div class="col-sm-3 action-link-element" @onclick="@(() => SortProducts(ProductSort.Sku))"><i class="bi-sort-alpha-down"></i> Varenr <i class="bi-sort-alpha-up-alt"></i></div>
|
<div class="col-sm-4 action-link-element" onclick="@(() => SortProducts(ProductSort.Description))"><i class="bi-sort-alpha-down"></i> Navn <i class="bi-sort-alpha-up-alt"></i></div>
|
||||||
<div class="col-sm-2 text-center action-link-element" @onclick="@(() => SortProducts(ProductSort.Qty))"><i class="bi-sort-numeric-down"></i> Antal <i class="bi-sort-numeric-up-alt"></i></div>
|
<div class="col-sm-3 action-link-element" onclick="@(() => SortProducts(ProductSort.Sku))"><i class="bi-sort-alpha-down"></i> Varenr <i class="bi-sort-alpha-up-alt"></i></div>
|
||||||
<div class="col-sm-2"></div>
|
*@
|
||||||
<div class="col-sm-1"></div>
|
<div class="col-sm-7 text-end">
|
||||||
|
<div class="form-check form-check-inline">
|
||||||
|
<input class="form-check-input" type="checkbox" id="sortOrder" checked @onclick="@SetSortOrder"/>
|
||||||
|
<label class="form-check-label" for="sortOrder"><i class="@(Descending ? "bi-sort-up" : "bi-sort-down-alt") "></i></label>
|
||||||
|
</div>
|
||||||
|
<div class="form-check form-check-inline">
|
||||||
|
<input class="form-check-input" type="radio" name="sortCol" id="description" value="description"
|
||||||
|
onclick="@(() => SortProducts(ProductSort.Description))">
|
||||||
|
<label class="form-check-label" for="description">Navn</label>
|
||||||
|
</div>
|
||||||
|
<div class="form-check form-check-inline">
|
||||||
|
<input class="form-check-input" type="radio" name="sortCol" id="itemNumber" value="itemNumber"
|
||||||
|
onclick="@(() => SortProducts(ProductSort.Sku))">
|
||||||
|
<label class="form-check-label" for="itemNumber">Vare Nr.</label>
|
||||||
|
</div>
|
||||||
|
<div class="form-check form-check-inline">
|
||||||
|
<input class="form-check-input" type="radio" name="sortCol" id="lastInvoiceDate" value="itemDate"
|
||||||
|
onclick="@(() => SortProducts(ProductSort.LastInvoiceDate))" checked>
|
||||||
|
<label class="form-check-label" for="lastInvoiceDate">Sidst leveret</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-5">
|
||||||
|
<SearchPhraseComponent OnChanged="OnSearchChanged"/>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@foreach (var product in Inventory)
|
@foreach (var product in FilteredList)
|
||||||
{
|
{
|
||||||
<div class="list-group-item">
|
<div class="list-group-item">
|
||||||
<div class="row align-items-center">
|
<div class="row align-items-center">
|
||||||
|
<div class="col-sm-2">
|
||||||
|
<div class="position-relative">
|
||||||
|
@product.LastInvoiceDate
|
||||||
|
@if (product.AgedProduct() && !product.Discontinued)
|
||||||
|
{
|
||||||
|
<span class="position-absolute top-0 start-100 translate-middle badge rounded-pill bg-danger">
|
||||||
|
Længe siden
|
||||||
|
<span class="visually-hidden">Længe siden</span>
|
||||||
|
</span>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div class="col-sm-4">
|
<div class="col-sm-4">
|
||||||
<div class="position-relative">
|
<div class="position-relative">
|
||||||
@product.Description
|
@product.Description
|
||||||
@if (product.Discontinued)
|
@if (product.Discontinued)
|
||||||
{
|
{
|
||||||
<span class="position-absolute top-0 start-100 translate-middle badge rounded-pill bg-danger">Udgået</span>
|
<span class="position-absolute top-0 start-100 translate-middle badge rounded-pill bg-danger">
|
||||||
<span class="visually-hidden">Produktet er udgået</span>
|
Udgået
|
||||||
|
<span class="visually-hidden">Produktet er udgået</span>
|
||||||
|
</span>
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-sm-3">
|
<div class="col-sm-2 text-sm-start">
|
||||||
@product.Sku
|
@product.Sku
|
||||||
</div>
|
</div>
|
||||||
<div class="col-sm-2 text-center">
|
<div class="col-sm-1 text-center">
|
||||||
@product.Quantity
|
@product.Quantity
|
||||||
</div>
|
</div>
|
||||||
<div class="col-sm-2 d-print-none">
|
<div class="col-sm-2 d-print-none">
|
||||||
<button type="button" class="btn btn-info d-block" @onclick="@(() => CallShowReorderModal(product.Sku))"><i class="bi-cart"></i> Genbestil</button>
|
<button type="button" class="btn btn-info d-block" @onclick="@(() => CallShowReorderModal(product.Sku))"><i class="bi-cart"></i> Genbestil</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-sm-1 d-print-none" @onclick="@(() => ProductCheck(product.Sku))">
|
<div class="col-sm-1 d-print-none" @onclick="@(() => SetProductCheckmark(product.Sku))">
|
||||||
<input type="checkbox" class="btn-check" id="btn-@product.Sku.Replace(",", "")" autocomplete="off"/>
|
<input type="checkbox" class="btn-check" id="btn-@product.Sku.Replace(",", "")" autocomplete="off"/>
|
||||||
@if (product.Check)
|
@if (product.Check)
|
||||||
{
|
{
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
using Blazored.LocalStorage;
|
using Blazored.LocalStorage;
|
||||||
using Microsoft.AspNetCore.Components;
|
using Microsoft.AspNetCore.Components;
|
||||||
using Wonky.Client.Enums;
|
using Wonky.Client.Enums;
|
||||||
|
using Wonky.Client.Helpers;
|
||||||
using Wonky.Client.Models;
|
using Wonky.Client.Models;
|
||||||
using Wonky.Entity.Views;
|
using Wonky.Entity.Views;
|
||||||
|
|
||||||
|
@ -24,71 +25,68 @@ namespace Wonky.Client.Components;
|
||||||
|
|
||||||
public partial class CustomerInventoryListComponent
|
public partial class CustomerInventoryListComponent
|
||||||
{
|
{
|
||||||
|
// ##############################################3333############
|
||||||
[Inject] public ILocalStorageService Storage { get; set; }
|
[Inject] public ILocalStorageService Storage { get; set; }
|
||||||
// Parameters
|
[Inject] public ILogger<CustomerInventoryListComponent> Logger { get; set; }
|
||||||
|
|
||||||
|
// ##############################################3333############
|
||||||
[Parameter] public List<ProductInventoryItemView> Inventory { get; set; } = new();
|
[Parameter] public List<ProductInventoryItemView> Inventory { get; set; } = new();
|
||||||
[Parameter] public string CompanyId { get; set; } = "";
|
[Parameter] public string CompanyId { get; set; } = "";
|
||||||
[Parameter] public EventCallback<string> OnReorderSelected { get; set; }
|
[Parameter] public EventCallback<string> OnReorderSelected { get; set; }
|
||||||
|
|
||||||
|
// ##############################################3333############
|
||||||
// private variables
|
// private variables
|
||||||
private bool Descending { get; set; }
|
private bool Descending { get; set; } = true;
|
||||||
|
private string SearchTerm { get; set; } = "";
|
||||||
|
private List<ProductInventoryItemView> FilteredList { get; set; }
|
||||||
|
private ProductSort SortColumn { get; set; } = ProductSort.LastInvoiceDate;
|
||||||
|
|
||||||
protected override void OnParametersSet()
|
protected override void OnInitialized()
|
||||||
{
|
{
|
||||||
if(Inventory.Any())
|
// sort base list
|
||||||
Inventory = Inventory.OrderBy(x => x.Description).ToList();
|
Inventory = Utils.SortInventory(Inventory, SortColumn, Descending);
|
||||||
|
// initialize FilteredList
|
||||||
|
FilterItems(SearchTerm);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void SetSortOrder()
|
||||||
|
{
|
||||||
|
Descending = !Descending;
|
||||||
|
FilteredList = Utils.SortInventory(FilteredList, SortColumn, Descending);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void OnSearchChanged(string searchTerm)
|
||||||
|
{
|
||||||
|
// use search input to filter list
|
||||||
|
FilterItems(searchTerm);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void FilterItems(string filter)
|
||||||
|
{
|
||||||
|
SearchTerm = filter;
|
||||||
|
FilteredList = string.IsNullOrWhiteSpace(filter)
|
||||||
|
? Inventory
|
||||||
|
: Inventory.Where(i => i.Description.ToLower().Contains(filter.ToLower())).ToList();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private void SortProducts(ProductSort column)
|
private void SortProducts(ProductSort column)
|
||||||
{
|
{
|
||||||
Descending = !Descending;
|
FilteredList = Utils.SortInventory(FilteredList, column, Descending);
|
||||||
switch (column)
|
|
||||||
{
|
|
||||||
case ProductSort.Desc:
|
|
||||||
if (Descending)
|
|
||||||
{
|
|
||||||
Inventory = Inventory.OrderByDescending(x => x.Description).ToList();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
Inventory = Inventory.OrderBy(x => x.Description).ToList();
|
|
||||||
break;
|
|
||||||
case ProductSort.Sku:
|
|
||||||
if (Descending)
|
|
||||||
{
|
|
||||||
Inventory = Inventory.OrderByDescending(x => x.Sku).ToList();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
Inventory = Inventory.OrderBy(x => x.Sku).ToList();
|
|
||||||
break;
|
|
||||||
case ProductSort.Qty:
|
|
||||||
if (Descending)
|
|
||||||
{
|
|
||||||
Inventory = Inventory.OrderByDescending(x => x.Quantity).ToList();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
Inventory = Inventory.OrderBy(x => x.Quantity).ToList();
|
|
||||||
break;
|
|
||||||
case ProductSort.None:
|
|
||||||
Inventory = Inventory.OrderBy(x => x.Description).ToList();
|
|
||||||
break;
|
|
||||||
case ProductSort.Abbr:
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
Inventory = Inventory.OrderBy(x => x.Description).ToList();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private async Task CallShowReorderModal(string sku)
|
private async Task CallShowReorderModal(string sku)
|
||||||
{
|
{
|
||||||
await ProductCheck(sku);
|
await SetProductCheckmark(sku);
|
||||||
await OnReorderSelected.InvokeAsync(sku);
|
await OnReorderSelected.InvokeAsync(sku);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private async Task ProductCheck(string sku)
|
private async Task SetProductCheckmark(string sku)
|
||||||
{
|
{
|
||||||
var x = Inventory.First(x => x.Sku == sku);
|
var x = Inventory.First(x => x.Sku == sku);
|
||||||
x.Check = !x.Check;
|
x.Check = !x.Check;
|
||||||
|
|
|
@ -22,24 +22,50 @@
|
||||||
<div class="list-group mt-2">
|
<div class="list-group mt-2">
|
||||||
<div class="list-group-item">
|
<div class="list-group-item">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-sm-4" style="cursor: pointer;" @onclick="@(() => SortProducts(ProductSort.Desc))"><i class="bi-sort-alpha-down"></i> Navn <i class="bi-sort-alpha-up-alt"></i></div>
|
@*
|
||||||
|
<div class="col-sm-4" style="cursor: pointer;" @onclick="@(() => SortProducts(ProductSort.Description))"><i class="bi-sort-alpha-down"></i> Navn <i class="bi-sort-alpha-up-alt"></i></div>
|
||||||
<div class="col-sm-3" style="cursor: pointer;" @onclick="@(() => SortProducts(ProductSort.Sku))"><i class="bi-sort-alpha-down"></i> Varenr <i class="bi-sort-alpha-up-alt"></i></div>
|
<div class="col-sm-3" style="cursor: pointer;" @onclick="@(() => SortProducts(ProductSort.Sku))"><i class="bi-sort-alpha-down"></i> Varenr <i class="bi-sort-alpha-up-alt"></i></div>
|
||||||
<div class="col-sm-2 text-center" style="cursor: pointer;" @onclick="@(() => SortProducts(ProductSort.Qty))"><i class="bi-sort-numeric-down"></i> Antal <i class="bi-sort-numeric-up-alt"></i></div>
|
*@
|
||||||
<div class="col-sm-2"></div>
|
<div class="col-sm-7 text-end">
|
||||||
<div class="col-sm-1"></div>
|
<div class="form-check form-check-inline">
|
||||||
|
<input class="form-check-input" type="checkbox" id="sortOrder" checked @onclick="@SetSortOrder"/>
|
||||||
|
<label class="form-check-label" for="sortOrder"><i class="@(Descending ? "bi-sort-up" : "bi-sort-down") "></i></label>
|
||||||
|
</div>
|
||||||
|
<div class="form-check form-check-inline">
|
||||||
|
<input class="form-check-input" type="radio" name="sortCol" id="description" value="description"
|
||||||
|
onclick="@(() => SortProducts(ProductSort.Description))">
|
||||||
|
<label class="form-check-label" for="description">Navn</label>
|
||||||
|
</div>
|
||||||
|
<div class="form-check form-check-inline">
|
||||||
|
<input class="form-check-input" type="radio" name="sortCol" id="itemNumber" value="itemNumber"
|
||||||
|
onclick="@(() => SortProducts(ProductSort.Sku))">
|
||||||
|
<label class="form-check-label" for="itemNumber">Vare Nr.</label>
|
||||||
|
</div>
|
||||||
|
<div class="form-check form-check-inline">
|
||||||
|
<input class="form-check-input" type="radio" name="sortCol" id="lastInvoiceDate" value="itemDate"
|
||||||
|
onclick="@(() => SortProducts(ProductSort.LastInvoiceDate))" checked>
|
||||||
|
<label class="form-check-label" for="lastInvoiceDate">Sidst leveret</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-5">
|
||||||
|
<SearchPhraseComponent OnChanged="OnSearchChanged"/>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@foreach (var product in Inventory)
|
@foreach (var product in Inventory)
|
||||||
{
|
{
|
||||||
<div class="list-group-item">
|
<div class="list-group-item">
|
||||||
<div class="row align-items-center">
|
<div class="row align-items-center">
|
||||||
|
<div class="col-sm-2">
|
||||||
|
@product.LastInvoiceDate
|
||||||
|
</div>
|
||||||
<div class="col-sm-4">
|
<div class="col-sm-4">
|
||||||
@product.Description
|
@product.Description
|
||||||
</div>
|
</div>
|
||||||
<div class="col-sm-3">
|
<div class="col-sm-2">
|
||||||
@product.Sku
|
@product.Sku
|
||||||
</div>
|
</div>
|
||||||
<div class="col-sm-2 text-center">
|
<div class="col-sm-1 text-center">
|
||||||
@product.Quantity
|
@product.Quantity
|
||||||
</div>
|
</div>
|
||||||
<div class="col-sm-2">
|
<div class="col-sm-2">
|
||||||
|
|
|
@ -13,9 +13,11 @@
|
||||||
// along with this program. If not, see [https://www.gnu.org/licenses/agpl-3.0.en.html]
|
// along with this program. If not, see [https://www.gnu.org/licenses/agpl-3.0.en.html]
|
||||||
//
|
//
|
||||||
|
|
||||||
|
using System.Security.Policy;
|
||||||
using Blazored.LocalStorage;
|
using Blazored.LocalStorage;
|
||||||
using Microsoft.AspNetCore.Components;
|
using Microsoft.AspNetCore.Components;
|
||||||
using Wonky.Client.Enums;
|
using Wonky.Client.Enums;
|
||||||
|
using Wonky.Client.Helpers;
|
||||||
using Wonky.Client.Models;
|
using Wonky.Client.Models;
|
||||||
using Wonky.Entity.Views;
|
using Wonky.Entity.Views;
|
||||||
#pragma warning disable CS8618
|
#pragma warning disable CS8618
|
||||||
|
@ -27,57 +29,48 @@ public partial class CustomerProductCheckListComponent
|
||||||
[Parameter] public string CompanyId { get; set; } = "";
|
[Parameter] public string CompanyId { get; set; } = "";
|
||||||
[Inject] public ILocalStorageService Storage { get; set; }
|
[Inject] public ILocalStorageService Storage { get; set; }
|
||||||
// private variables
|
// private variables
|
||||||
private bool Descending { get; set; }
|
private bool Descending { get; set; } = true;
|
||||||
|
private string SearchTerm { get; set; } = "";
|
||||||
|
private List<ProductInventoryItemView> FilteredList { get; set; } = new();
|
||||||
|
|
||||||
protected override void OnParametersSet()
|
protected override void OnParametersSet()
|
||||||
{
|
{
|
||||||
if(Inventory.Any())
|
Inventory = Utils.SortInventory(Inventory, ProductSort.LastInvoiceDate, Descending);
|
||||||
Inventory = Inventory.OrderBy(x => x.Description).ToList();
|
FilterItems(SearchTerm);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void SetSortOrder()
|
||||||
|
{
|
||||||
|
Descending = !Descending;
|
||||||
|
FilteredList = Utils.SortInventory(FilteredList, ProductSort.LastInvoiceDate, Descending);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void OnSearchChanged(string searchTerm)
|
||||||
|
{
|
||||||
|
FilterItems(searchTerm);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void FilterItems(string filter)
|
||||||
|
{
|
||||||
|
SearchTerm = filter;
|
||||||
|
FilteredList = string.IsNullOrWhiteSpace(filter)
|
||||||
|
? Inventory
|
||||||
|
: Inventory.Where(i => i.Description.ToLower().Contains(filter.ToLower())).ToList();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
private void SortProducts(ProductSort column)
|
private void SortProducts(ProductSort column)
|
||||||
{
|
{
|
||||||
Descending = !Descending;
|
FilteredList = Utils.SortInventory(Inventory, column, Descending);
|
||||||
switch (column)
|
|
||||||
{
|
|
||||||
case ProductSort.Desc:
|
|
||||||
if (Descending)
|
|
||||||
{
|
|
||||||
Inventory = Inventory.OrderByDescending(x => x.Description).ToList();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
Inventory = Inventory.OrderBy(x => x.Description).ToList();
|
|
||||||
break;
|
|
||||||
case ProductSort.Sku:
|
|
||||||
if (Descending)
|
|
||||||
{
|
|
||||||
Inventory = Inventory.OrderByDescending(x => x.Sku).ToList();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
Inventory = Inventory.OrderBy(x => x.Sku).ToList();
|
|
||||||
break;
|
|
||||||
case ProductSort.Qty:
|
|
||||||
if (Descending)
|
|
||||||
{
|
|
||||||
Inventory = Inventory.OrderByDescending(x => x.Quantity).ToList();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
Inventory = Inventory.OrderBy(x => x.Quantity).ToList();
|
|
||||||
break;
|
|
||||||
case ProductSort.None:
|
|
||||||
break;
|
|
||||||
case ProductSort.Abbr:
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
Inventory = Inventory.OrderByDescending(x => x.Quantity).ToList();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task ProductCheck(string sku)
|
|
||||||
|
private void ProductCheck(string sku)
|
||||||
{
|
{
|
||||||
var x = Inventory.First(x => x.Sku == sku);
|
var x = Inventory.First(x => x.Sku == sku);
|
||||||
x.Check = !x.Check;
|
x.Check = !x.Check;
|
||||||
await Storage.SetItemAsync($"{CompanyId}-products", Inventory);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,60 +0,0 @@
|
||||||
@* Copyright (C) 2022 FCS Frede's Computer Services.
|
|
||||||
// This program is free software: you can redistribute it and/or modify
|
|
||||||
// it under the terms of the GNU Affero General Public License as
|
|
||||||
// published by the Free Software Foundation, either version 3 of the
|
|
||||||
// License, or (at your option) any later version.
|
|
||||||
//
|
|
||||||
// This program is distributed in the hope that it will be useful,
|
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
// GNU Affero General Public License for more details.
|
|
||||||
//
|
|
||||||
// You should have received a copy of the GNU Affero General Public License
|
|
||||||
// along with this program. If not, see [https://www.gnu.org/licenses/agpl-3.0.en.html]
|
|
||||||
*@
|
|
||||||
|
|
||||||
@using Wonky.Client.Components
|
|
||||||
|
|
||||||
<h3>Pakning / Forsendelse</h3>
|
|
||||||
<table class="table">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th>Symbol</th>
|
|
||||||
<th>Betydning</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
<tr>
|
|
||||||
<td class="align-middle">
|
|
||||||
<div class="color-code">
|
|
||||||
<DisplayStateComponent StateClass="the-good"/>
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
<td class="align-middle">Ubehandlet</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td class="align-middle">
|
|
||||||
<div class="color-code">
|
|
||||||
<DisplayStateComponent StateClass="the-bad"/>
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
<td class="align-middle">Varer er plukket</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td class="align-middle">
|
|
||||||
<div class="color-code">
|
|
||||||
<DisplayStateComponent StateClass="the-ugly"/>
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
<td class="align-middle">Varer er pakket</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td class="align-middle">
|
|
||||||
<div class="color-code">
|
|
||||||
<DisplayStateComponent StateClass="the-dead"/>
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
<td class="align-middle">Varer er afsendt</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
|
@ -36,6 +36,7 @@
|
||||||
<td><i class="bi-printer" style="font-size:1.3rem"></i></td>
|
<td><i class="bi-printer" style="font-size:1.3rem"></i></td>
|
||||||
<td>Udskrevet</td>
|
<td>Udskrevet</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
@*
|
||||||
<tr>
|
<tr>
|
||||||
<td><i class="bi-file-earmark-check" style="font-size:1.3rem"></i></td>
|
<td><i class="bi-file-earmark-check" style="font-size:1.3rem"></i></td>
|
||||||
<td>Plukket</td>
|
<td>Plukket</td>
|
||||||
|
@ -48,5 +49,6 @@
|
||||||
<td><i class="bi-truck" style="font-size:1.3rem"></i></td>
|
<td><i class="bi-truck" style="font-size:1.3rem"></i></td>
|
||||||
<td>Leveret</td>
|
<td>Leveret</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
*@
|
||||||
</thead>
|
</thead>
|
||||||
</table>
|
</table>
|
||||||
|
|
|
@ -70,7 +70,7 @@
|
||||||
</div>
|
</div>
|
||||||
<OfficeCustomerInvoiceListOverlay Company="@SelectedCompany" InvoiceList="@InvoiceList" @ref="InvoiceListOverlay" />
|
<OfficeCustomerInvoiceListOverlay Company="@SelectedCompany" InvoiceList="@InvoiceList" @ref="InvoiceListOverlay" />
|
||||||
<OfficeCustomerActivityListOverlay Company="SelectedCompany" ActivityList="ActivityList" @ref="ActivityListOverlay" />
|
<OfficeCustomerActivityListOverlay Company="SelectedCompany" ActivityList="ActivityList" @ref="ActivityListOverlay" />
|
||||||
<OfficeCustomerProductListOverlay Company="SelectedCompany" Inventory="ProductList" @ref="ProductListOverlay" />
|
<OfficeCustomerInventoryListOverlay Company="SelectedCompany" Inventory="ProductList" @ref="InventoryListOverlay" />
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
@ -48,7 +48,7 @@ public partial class OfficeCountryCustomerListComponent
|
||||||
// overlays
|
// overlays
|
||||||
private OfficeCustomerInvoiceListOverlay InvoiceListOverlay { get; set; } = new();
|
private OfficeCustomerInvoiceListOverlay InvoiceListOverlay { get; set; } = new();
|
||||||
private OfficeCustomerActivityListOverlay ActivityListOverlay { get; set; } = new();
|
private OfficeCustomerActivityListOverlay ActivityListOverlay { get; set; } = new();
|
||||||
private OfficeCustomerProductListOverlay ProductListOverlay { get; set; } = new();
|
private OfficeCustomerInventoryListOverlay InventoryListOverlay { get; set; } = new();
|
||||||
|
|
||||||
// ******************************************************
|
// ******************************************************
|
||||||
// variables
|
// variables
|
||||||
|
@ -108,7 +108,7 @@ public partial class OfficeCountryCustomerListComponent
|
||||||
SelectedCompany.HistorySync = newSyncDate;
|
SelectedCompany.HistorySync = newSyncDate;
|
||||||
}
|
}
|
||||||
ProductList = await HistoryRepo.GetInventory(SelectedCompany.CountryCode, SelectedCompany.CompanyId);
|
ProductList = await HistoryRepo.GetInventory(SelectedCompany.CountryCode, SelectedCompany.CompanyId);
|
||||||
ProductListOverlay.Show();
|
InventoryListOverlay.Show();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ShowOrder(string companyId)
|
private void ShowOrder(string companyId)
|
||||||
|
|
|
@ -24,11 +24,32 @@
|
||||||
<div class="list-group mt-2">
|
<div class="list-group mt-2">
|
||||||
<div class="list-group-item">
|
<div class="list-group-item">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-sm-4" style="cursor: pointer;" @onclick="@(() => SortProducts(ProductSort.Desc))"><i class="bi-sort-alpha-down"></i> Navn <i class="bi-sort-alpha-up-alt"></i></div>
|
@* <div class="col-sm-4" style="cursor: pointer;" @onclick="@(() => SortProducts(ProductSort.Description))"><i class="bi-sort-alpha-down"></i> Navn <i class="bi-sort-alpha-up-alt"></i></div> *@
|
||||||
<div class="col-sm-3" style="cursor: pointer;" @onclick="@(() => SortProducts(ProductSort.Sku))"><i class="bi-sort-alpha-down"></i> Varenr <i class="bi-sort-alpha-up-alt"></i></div>
|
@* <div class="col-sm-3" style="cursor: pointer;" @onclick="@(() => SortProducts(ProductSort.Sku))"><i class="bi-sort-alpha-down"></i> Varenr <i class="bi-sort-alpha-up-alt"></i></div> *@
|
||||||
<div class="col-sm-2 text-center" style="cursor: pointer;" @onclick="@(() => SortProducts(ProductSort.Qty))"><i class="bi-sort-numeric-down"></i> Antal <i class="bi-sort-numeric-up-alt"></i></div>
|
<div class="col-sm-7 text-end">
|
||||||
<div class="col-sm-2"></div>
|
<div class="form-check form-check-inline">
|
||||||
<div class="col-sm-1"></div>
|
<input class="form-check-input" type="checkbox" id="sortOrder" checked @onclick="@SetSortOrder"/>
|
||||||
|
<label class="form-check-label" for="sortOrder"><i class="@(Descending ? "bi-sort-up" : "bi-sort-down") "></i></label>
|
||||||
|
</div>
|
||||||
|
<div class="form-check form-check-inline">
|
||||||
|
<input class="form-check-input" type="radio" name="sortCol" id="description" value="description"
|
||||||
|
onclick="@(() => SortProducts(ProductSort.Description))">
|
||||||
|
<label class="form-check-label" for="description">Navn</label>
|
||||||
|
</div>
|
||||||
|
<div class="form-check form-check-inline">
|
||||||
|
<input class="form-check-input" type="radio" name="sortCol" id="itemNumber" value="itemNumber"
|
||||||
|
onclick="@(() => SortProducts(ProductSort.Sku))">
|
||||||
|
<label class="form-check-label" for="itemNumber">Vare Nr.</label>
|
||||||
|
</div>
|
||||||
|
<div class="form-check form-check-inline">
|
||||||
|
<input class="form-check-input" type="radio" name="sortCol" id="lastInvoiceDate" value="itemDate"
|
||||||
|
onclick="@(() => SortProducts(ProductSort.LastInvoiceDate))" checked>
|
||||||
|
<label class="form-check-label" for="lastInvoiceDate">Sidst leveret</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-5">
|
||||||
|
<SearchPhraseComponent OnChanged="OnSearchChanged" />
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@foreach (var product in Inventory)
|
@foreach (var product in Inventory)
|
|
@ -15,72 +15,70 @@
|
||||||
|
|
||||||
using Blazored.LocalStorage;
|
using Blazored.LocalStorage;
|
||||||
using Microsoft.AspNetCore.Components;
|
using Microsoft.AspNetCore.Components;
|
||||||
|
using Microsoft.VisualBasic.CompilerServices;
|
||||||
using Wonky.Client.Enums;
|
using Wonky.Client.Enums;
|
||||||
using Wonky.Client.Models;
|
using Wonky.Client.Models;
|
||||||
using Wonky.Entity.Views;
|
using Wonky.Entity.Views;
|
||||||
|
using Utils = Wonky.Client.Helpers.Utils;
|
||||||
|
|
||||||
namespace Wonky.Client.Components;
|
namespace Wonky.Client.Components;
|
||||||
#pragma warning disable CS8618
|
#pragma warning disable CS8618
|
||||||
|
|
||||||
public partial class OfficeInventoryListComponent
|
public partial class OfficeCustomerInventoryListComponent
|
||||||
{
|
{
|
||||||
// *************************************************************
|
// *************************************************************
|
||||||
// Injections
|
// Injections
|
||||||
[Inject] public ILocalStorageService Storage { get; set; }
|
[Inject] public ILocalStorageService Storage { get; set; }
|
||||||
|
|
||||||
// *************************************************************
|
// *************************************************************
|
||||||
// Parameters
|
// Parameters
|
||||||
[Parameter] public List<ProductInventoryItemView> Inventory { get; set; } = new();
|
[Parameter] public List<ProductInventoryItemView> Inventory { get; set; } = new();
|
||||||
[Parameter] public string CompanyId { get; set; } = "";
|
[Parameter] public string CompanyId { get; set; } = "";
|
||||||
[Parameter] public EventCallback<string> OnReorderSelected { get; set; }
|
[Parameter] public EventCallback<string> OnReorderSelected { get; set; }
|
||||||
|
|
||||||
// *************************************************************
|
// *************************************************************
|
||||||
// private variables
|
// private variables
|
||||||
private bool Descending { get; set; }
|
private bool Descending { get; set; } = true;
|
||||||
|
private string SearchTerm { get; set; } = "";
|
||||||
|
private List<ProductInventoryItemView> FilteredList { get; set; } = new();
|
||||||
|
private ProductSort SortColumn { get; set; } = ProductSort.LastInvoiceDate;
|
||||||
|
|
||||||
|
|
||||||
protected override void OnParametersSet()
|
protected override void OnParametersSet()
|
||||||
{
|
{
|
||||||
if(Inventory.Any())
|
Inventory = Utils.SortInventory(Inventory, SortColumn, Descending);
|
||||||
Inventory = Inventory.OrderBy(x => x.Description).ToList();
|
FilterItems(SearchTerm);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void SetSortOrder()
|
||||||
|
{
|
||||||
|
Descending = !Descending;
|
||||||
|
FilteredList = Utils.SortInventory(FilteredList, SortColumn, Descending);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void OnSearchChanged(string searchTerm)
|
||||||
|
{
|
||||||
|
FilterItems(searchTerm);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void FilterItems(string filter)
|
||||||
|
{
|
||||||
|
SearchTerm = filter;
|
||||||
|
FilteredList = string.IsNullOrWhiteSpace(filter)
|
||||||
|
? Inventory
|
||||||
|
: Inventory.Where(i => i.Description.ToLower().Contains(filter.ToLower())).ToList();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
private void SortProducts(ProductSort column)
|
private void SortProducts(ProductSort column)
|
||||||
{
|
{
|
||||||
Descending = !Descending;
|
FilteredList = Utils.SortInventory(FilteredList, column, Descending);
|
||||||
switch (column)
|
|
||||||
{
|
|
||||||
case ProductSort.Desc:
|
|
||||||
if (Descending)
|
|
||||||
{
|
|
||||||
Inventory = Inventory.OrderByDescending(x => x.Description).ToList();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
Inventory = Inventory.OrderBy(x => x.Description).ToList();
|
|
||||||
break;
|
|
||||||
case ProductSort.Sku:
|
|
||||||
if (Descending)
|
|
||||||
{
|
|
||||||
Inventory = Inventory.OrderByDescending(x => x.Sku).ToList();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
Inventory = Inventory.OrderBy(x => x.Sku).ToList();
|
|
||||||
break;
|
|
||||||
case ProductSort.Qty:
|
|
||||||
if (Descending)
|
|
||||||
{
|
|
||||||
Inventory = Inventory.OrderByDescending(x => x.Quantity).ToList();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
Inventory = Inventory.OrderBy(x => x.Quantity).ToList();
|
|
||||||
break;
|
|
||||||
case ProductSort.None:
|
|
||||||
break;
|
|
||||||
case ProductSort.Abbr:
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
Inventory = Inventory.OrderByDescending(x => x.Quantity).ToList();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private async Task CallShowReorderModal(string sku)
|
private async Task CallShowReorderModal(string sku)
|
||||||
{
|
{
|
||||||
// await ProductCheck(sku);
|
// await ProductCheck(sku);
|
|
@ -13,20 +13,9 @@
|
||||||
// along with this program. If not, see [https://www.gnu.org/licenses/agpl-3.0.en.html]
|
// along with this program. If not, see [https://www.gnu.org/licenses/agpl-3.0.en.html]
|
||||||
*@
|
*@
|
||||||
|
|
||||||
<h3>Lager</h3>
|
<div class="input-group">
|
||||||
<table class="table">
|
<input id="search-input" type="text" class="form-control" placeholder="Søg ..." aria-described-by="search-addon"
|
||||||
<thead>
|
@bind-value="SearchTerm" @bind-value:event="oninput" onkeyup="@OnSearchChanged" />
|
||||||
<tr>
|
<span class="input-group-text" id="search-addon"><i class="oi oi-delete" @onclick="@ClearSearch"></i></span>
|
||||||
<th>Symbol</th>
|
</div>
|
||||||
<th>Betydning</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
<i class="bi-box" style="font-size:1.3rem"></i>
|
|
||||||
</td>
|
|
||||||
<td>Pakning / Forsendelse</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* Copyright (C) 2022 FCS Frede's Computer Services.
|
// Copyright (C) 2022 FCS Frede's Computer Services.
|
||||||
// This program is free software: you can redistribute it and/or modify
|
// This program is free software: you can redistribute it and/or modify
|
||||||
// it under the terms of the GNU Affero General Public License as
|
// it under the terms of the GNU Affero General Public License as
|
||||||
// published by the Free Software Foundation, either version 3 of the
|
// published by the Free Software Foundation, either version 3 of the
|
||||||
|
@ -11,10 +11,27 @@
|
||||||
//
|
//
|
||||||
// You should have received a copy of the GNU Affero General Public License
|
// You should have received a copy of the GNU Affero General Public License
|
||||||
// along with this program. If not, see [https://www.gnu.org/licenses/agpl-3.0.en.html]
|
// along with this program. If not, see [https://www.gnu.org/licenses/agpl-3.0.en.html]
|
||||||
*/
|
//
|
||||||
.pictogram {
|
|
||||||
max-width: 30px;
|
using System.Timers;
|
||||||
}
|
using Microsoft.AspNetCore.Components;
|
||||||
.color-code {
|
using Timer = System.Timers.Timer;
|
||||||
max-width: 30px;
|
|
||||||
|
namespace Wonky.Client.Components;
|
||||||
|
|
||||||
|
public partial class SearchPhraseComponent
|
||||||
|
{
|
||||||
|
private string SearchTerm { get; set; } = "";
|
||||||
|
[Parameter] public EventCallback<string> OnChanged { get; set; }
|
||||||
|
|
||||||
|
private void ClearSearch()
|
||||||
|
{
|
||||||
|
SearchTerm = "";
|
||||||
|
OnChanged.InvokeAsync("");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnSearchChanged()
|
||||||
|
{
|
||||||
|
OnChanged.InvokeAsync(SearchTerm);
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -1,102 +0,0 @@
|
||||||
@* Copyright (C) 2022 FCS Frede's Computer Services.
|
|
||||||
// This program is free software: you can redistribute it and/or modify
|
|
||||||
// it under the terms of the GNU Affero General Public License as
|
|
||||||
// published by the Free Software Foundation, either version 3 of the
|
|
||||||
// License, or (at your option) any later version.
|
|
||||||
//
|
|
||||||
// This program is distributed in the hope that it will be useful,
|
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
// GNU Affero General Public License for more details.
|
|
||||||
//
|
|
||||||
// You should have received a copy of the GNU Affero General Public License
|
|
||||||
// along with this program. If not, see [https://www.gnu.org/licenses/agpl-3.0.en.html]
|
|
||||||
*@
|
|
||||||
|
|
||||||
|
|
||||||
@using Wonky.Client.Models
|
|
||||||
@using Wonky.Client.Enums
|
|
||||||
|
|
||||||
@if (OrderList != null)
|
|
||||||
{
|
|
||||||
<div class="row mb-3">
|
|
||||||
<div class="col-sm-4">
|
|
||||||
<div class="btn-group" role="group" aria-label="Ordre status">
|
|
||||||
<input type="radio" class="btn-check" name="btn-order" id="btn-order1" @onchange="() => GetWithStatus(ProcessStatus.None)" autocomplete="off" checked="checked"/>
|
|
||||||
<label class="btn btn-success" for="btn-order1">Ubehandlet</label>
|
|
||||||
|
|
||||||
<input type="radio" class="btn-check" name="btn-order" id="btn-order2" @onchange="() => GetWithStatus(ProcessStatus.Picked)" autocomplete="off"/>
|
|
||||||
<label class="btn btn-warning" for="btn-order2">Plukket</label>
|
|
||||||
|
|
||||||
<input type="radio" class="btn-check" name="btn-order" id="btn-order3" @onchange="() => GetWithStatus(ProcessStatus.Packed)" autocomplete="off"/>
|
|
||||||
<label class="btn btn-danger" for="btn-order3">Pakket</label>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="col-sm-4 text-end">
|
|
||||||
<label class="btn btn-outline-dark position-relative">
|
|
||||||
@Header
|
|
||||||
<span class="position-absolute top-0 start-100 translate-middle badge rounded-pill bg-info">@Orders.Count</span>
|
|
||||||
<span class="visually-hidden">ordrer i listen</span>
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
<div class="col-sm-4 text-end">
|
|
||||||
@if (ReadyToShip && Orders.Any())
|
|
||||||
{
|
|
||||||
<button type="button" class="btn btn-primary text-sm-center" @onclick="@SetShipStatus">Sæt alle afsendt</button>
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="list-group list-group-flush">
|
|
||||||
<div class="list-group-item">
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-sm-4">
|
|
||||||
<h4>Modtager</h4>
|
|
||||||
</div>
|
|
||||||
<div class="col-sm-3">
|
|
||||||
<h5>Post By</h5>
|
|
||||||
</div>
|
|
||||||
<div class="col-sm-2">
|
|
||||||
<h5>Dato</h5>
|
|
||||||
</div>
|
|
||||||
<div class="col-sm-3 text-end">
|
|
||||||
<h5><i class="bi-lightning-fill"></i> Status</h5>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
@foreach (var order in Orders)
|
|
||||||
{
|
|
||||||
<div class="list-group-item list-group-item-action" style="cursor: hand;">
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-sm-4">
|
|
||||||
@order.Company.Name
|
|
||||||
</div>
|
|
||||||
<div class="col-sm-3">
|
|
||||||
@order.Company.ZipCode @order.Company.City
|
|
||||||
</div>
|
|
||||||
<div class="col-sm-2">
|
|
||||||
@order.OrderDate
|
|
||||||
</div>
|
|
||||||
<div class="col-sm-3 d-flex">
|
|
||||||
@if (order.Express)
|
|
||||||
{
|
|
||||||
<i class="bi-lightning-fill text-warning"></i>
|
|
||||||
}
|
|
||||||
@switch (order.ProcessStatusEnum.ToLower())
|
|
||||||
{
|
|
||||||
case "none":
|
|
||||||
<button class="btn btn-outline-danger me-4" @onclick="@(() => QuickPak(order.OrderId))">QuickPak</button>
|
|
||||||
<a class="btn btn-warning" href="warehouse/orders/process/@order.OrderId">Pluk varer</a>
|
|
||||||
break;
|
|
||||||
case "picked":
|
|
||||||
<a class="btn btn-warning" href="warehouse/orders/process/@order.OrderId">Pak varer</a>
|
|
||||||
break;
|
|
||||||
case "packed":
|
|
||||||
<a class="btn btn-warning" href="warehouse/orders/process/@order.OrderId">Afhent varer</a>
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
}
|
|
|
@ -1,56 +0,0 @@
|
||||||
// Copyright (C) 2022 FCS Frede's Computer Services.
|
|
||||||
// This program is free software: you can redistribute it and/or modify
|
|
||||||
// it under the terms of the GNU Affero General Public License as
|
|
||||||
// published by the Free Software Foundation, either version 3 of the
|
|
||||||
// License, or (at your option) any later version.
|
|
||||||
//
|
|
||||||
// This program is distributed in the hope that it will be useful,
|
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
// GNU Affero General Public License for more details.
|
|
||||||
//
|
|
||||||
// You should have received a copy of the GNU Affero General Public License
|
|
||||||
// along with this program. If not, see [https://www.gnu.org/licenses/agpl-3.0.en.html]
|
|
||||||
//
|
|
||||||
|
|
||||||
using Microsoft.AspNetCore.Components;
|
|
||||||
using Wonky.Client.Enums;
|
|
||||||
using Wonky.Client.Models;
|
|
||||||
using Wonky.Entity.Views;
|
|
||||||
|
|
||||||
namespace Wonky.Client.Components;
|
|
||||||
|
|
||||||
public partial class WarehouseListComponent
|
|
||||||
{
|
|
||||||
[Parameter] public string Header { get; set; } = "";
|
|
||||||
[Parameter] public List<WarehouseOrderView> OrderList { get; set; } = new();
|
|
||||||
[Parameter] public bool ReadyToShip { get; set; }
|
|
||||||
[Parameter] public EventCallback<ProcessStatus> OnGetStatus { get; set; }
|
|
||||||
[Parameter] public EventCallback OnSetShipped { get; set; }
|
|
||||||
[Parameter] public EventCallback<string> OnQPak { get; set; }
|
|
||||||
|
|
||||||
private List<WarehouseOrderView> Orders { get; set; } = new();
|
|
||||||
|
|
||||||
protected override async Task OnParametersSetAsync()
|
|
||||||
{
|
|
||||||
while (OrderList == null)
|
|
||||||
await Task.Delay(500);
|
|
||||||
|
|
||||||
Orders = OrderList;
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task SetShipStatus()
|
|
||||||
{
|
|
||||||
await OnSetShipped.InvokeAsync();
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task GetWithStatus(ProcessStatus status)
|
|
||||||
{
|
|
||||||
await OnGetStatus.InvokeAsync(status);
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task QuickPak(string orderId)
|
|
||||||
{
|
|
||||||
await OnQPak.InvokeAsync(orderId);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -18,9 +18,7 @@ namespace Wonky.Client.Enums;
|
||||||
|
|
||||||
public enum ProductSort
|
public enum ProductSort
|
||||||
{
|
{
|
||||||
None,
|
Description,
|
||||||
Desc,
|
|
||||||
Sku,
|
Sku,
|
||||||
Qty,
|
LastInvoiceDate
|
||||||
Abbr
|
|
||||||
}
|
}
|
|
@ -27,11 +27,37 @@ namespace Wonky.Client.Helpers;
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static class Utils
|
public static class Utils
|
||||||
{
|
{
|
||||||
|
public static List<ProductInventoryItemView> SortInventory(IEnumerable<ProductInventoryItemView> inventory,
|
||||||
|
ProductSort column, bool descending)
|
||||||
|
{
|
||||||
|
return column switch
|
||||||
|
{
|
||||||
|
ProductSort.Description => descending
|
||||||
|
? inventory.OrderByDescending(x => x.Description).ToList()
|
||||||
|
: inventory.OrderBy(x => x.Description).ToList(),
|
||||||
|
ProductSort.Sku => descending
|
||||||
|
? inventory.OrderByDescending(x => x.Sku).ToList()
|
||||||
|
: inventory.OrderBy(x => x.Sku).ToList(),
|
||||||
|
ProductSort.LastInvoiceDate => descending
|
||||||
|
? inventory.OrderByDescending(x => x.LastInvoiceDate).ToList()
|
||||||
|
: inventory.OrderBy(x => x.LastInvoiceDate).ToList(),
|
||||||
|
_ => inventory.OrderByDescending(x => x.LastInvoiceDate).ToList()
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public static List<ProductVariant> GenerateVariantListDto(IEnumerable<DocView> items)
|
public static List<ProductVariant> GenerateVariantListDto(IEnumerable<DocView> items)
|
||||||
{
|
{
|
||||||
return items.Select(item => new ProductVariant { VariantId = item.VariantId, S5A = item.S5A, S9A = item.S9A }).ToList();
|
return items.Select(item => new ProductVariant
|
||||||
|
{
|
||||||
|
VariantId = item.VariantId,
|
||||||
|
S5A = item.S5A,
|
||||||
|
S9A = item.S9A
|
||||||
|
})
|
||||||
|
.ToList();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public static List<DocView> GenerateRevListView(IEnumerable<WorkplaceProduct> products)
|
public static List<DocView> GenerateRevListView(IEnumerable<WorkplaceProduct> products)
|
||||||
{
|
{
|
||||||
var result = new List<DocView>();
|
var result = new List<DocView>();
|
||||||
|
@ -64,9 +90,11 @@ public static class Utils
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
result.Add(newDoc);
|
result.Add(newDoc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return result.OrderBy(x => x.VariantName).ToList();
|
return result.OrderBy(x => x.VariantName).ToList();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -104,9 +132,11 @@ public static class Utils
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
result.Add(newDoc);
|
result.Add(newDoc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return result.OrderBy(x => x.VariantName).ToList();
|
return result.OrderBy(x => x.VariantName).ToList();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -115,11 +145,11 @@ public static class Utils
|
||||||
{
|
{
|
||||||
var addresses = recipients
|
var addresses = recipients
|
||||||
.Replace(" ", ",")
|
.Replace(" ", ",")
|
||||||
.Replace(",,",",")
|
.Replace(",,", ",")
|
||||||
.Split(",");
|
.Split(",");
|
||||||
|
|
||||||
return (from address
|
return (from address
|
||||||
in addresses
|
in addresses
|
||||||
where IsValidEmail(address)
|
where IsValidEmail(address)
|
||||||
select new EmailContact
|
select new EmailContact
|
||||||
{
|
{
|
||||||
|
@ -132,14 +162,14 @@ public static class Utils
|
||||||
{
|
{
|
||||||
return new List<UserRoleAssignment>()
|
return new List<UserRoleAssignment>()
|
||||||
{
|
{
|
||||||
new (){ Name = "Admin", Assigned = model.Admin},
|
new() { Name = "Admin", Assigned = model.Admin },
|
||||||
new (){ Name = "Advisor", Assigned = model.Advisor},
|
new() { Name = "Advisor", Assigned = model.Advisor },
|
||||||
new (){ Name = "EDoc", Assigned = model.EDoc},
|
new() { Name = "EDoc", Assigned = model.EDoc },
|
||||||
new (){ Name = "EShop", Assigned = model.EShop},
|
new() { Name = "EShop", Assigned = model.EShop },
|
||||||
new (){ Name = "Management", Assigned = model.Management},
|
new() { Name = "Management", Assigned = model.Management },
|
||||||
new (){ Name = "Office", Assigned = model.Office},
|
new() { Name = "Office", Assigned = model.Office },
|
||||||
new (){ Name = "Supervisor", Assigned = model.Supervisor},
|
new() { Name = "Supervisor", Assigned = model.Supervisor },
|
||||||
new (){ Name = "Warehouse", Assigned = model.Warehouse}
|
new() { Name = "Warehouse", Assigned = model.Warehouse }
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -177,6 +207,7 @@ public static class Utils
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return x;
|
return x;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -69,7 +69,8 @@ public class HttpInterceptorService
|
||||||
var absolutePath = e.Request.RequestUri.AbsolutePath;
|
var absolutePath = e.Request.RequestUri.AbsolutePath;
|
||||||
if (!absolutePath.Contains("token"))
|
if (!absolutePath.Contains("token"))
|
||||||
{
|
{
|
||||||
// call TryRefreshToken
|
// we are using the tryRefreshToken
|
||||||
|
// the service returns the current access token or a new token using refreshToken
|
||||||
var token = await _refreshTokenService.TryRefreshToken();
|
var token = await _refreshTokenService.TryRefreshToken();
|
||||||
if (!string.IsNullOrEmpty(token))
|
if (!string.IsNullOrEmpty(token))
|
||||||
{
|
{
|
||||||
|
|
|
@ -34,6 +34,7 @@ public class CrmCustomerHistoryRepository : ICrmCustomerHistoryRepository
|
||||||
private readonly HttpClient _client;
|
private readonly HttpClient _client;
|
||||||
private readonly ApiConfig _api;
|
private readonly ApiConfig _api;
|
||||||
|
|
||||||
|
|
||||||
public CrmCustomerHistoryRepository(
|
public CrmCustomerHistoryRepository(
|
||||||
HttpClient client, ILogger<CrmCustomerHistoryRepository> logger,
|
HttpClient client, ILogger<CrmCustomerHistoryRepository> logger,
|
||||||
NavigationManager navigation, IOptions<ApiConfig> configuration)
|
NavigationManager navigation, IOptions<ApiConfig> configuration)
|
||||||
|
@ -44,92 +45,80 @@ public class CrmCustomerHistoryRepository : ICrmCustomerHistoryRepository
|
||||||
_api = configuration.Value;
|
_api = configuration.Value;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Fetch Invoice LIst
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="companyId"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
public async Task<InvoiceListView> FetchInvoiceList(string companyId)
|
public async Task<InvoiceListView> FetchInvoiceList(string companyId)
|
||||||
{
|
{
|
||||||
var response = await _client.GetAsync($"{_api.CrmCustomers}/{companyId}/invoices");
|
var response = await _client.GetAsync($"{_api.CrmCustomers}/{companyId}/invoices");
|
||||||
var content = await response.Content.ReadAsStringAsync();
|
var content = await response.Content.ReadAsStringAsync();
|
||||||
return response.IsSuccessStatusCode
|
if (!response.IsSuccessStatusCode || string.IsNullOrWhiteSpace(content))
|
||||||
? JsonSerializer.Deserialize<InvoiceListView>(content, _options)
|
{
|
||||||
: new InvoiceListView();
|
return new InvoiceListView();
|
||||||
|
}
|
||||||
|
return JsonSerializer.Deserialize<InvoiceListView>(content, _options) ?? new InvoiceListView();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Fetch given invoice for given customer
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="companyId"></param>
|
|
||||||
/// <param name="invoiceId"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
public async Task<InvoiceView> FetchInvoice(string companyId, string invoiceId)
|
public async Task<InvoiceView> FetchInvoice(string companyId, string invoiceId)
|
||||||
{
|
{
|
||||||
return await _client
|
var content = await _client
|
||||||
.GetFromJsonAsync<InvoiceView>($"{_api.CrmCustomers}/{companyId}/invoices/{invoiceId}", _options);
|
.GetFromJsonAsync<InvoiceView>($"{_api.CrmCustomers}/{companyId}/invoices/{invoiceId}", _options);
|
||||||
|
return content ?? new InvoiceView();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Fetch inventory from given customer
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="companyId"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
public async Task<List<ProductInventoryItemView>> FetchInventory(string companyId)
|
public async Task<List<ProductInventoryItemView>> FetchInventory(string companyId)
|
||||||
{
|
{
|
||||||
var response = await _client.GetAsync($"{_api.CrmCustomers}/{companyId}/{_api.CrmInventoryExt}");
|
var response = await _client.GetAsync($"{_api.CrmCustomers}/{companyId}/{_api.CrmInventoryExt}");
|
||||||
if (!response.IsSuccessStatusCode)
|
|
||||||
return new List<ProductInventoryItemView>();
|
|
||||||
var content = await response.Content.ReadAsStringAsync();
|
var content = await response.Content.ReadAsStringAsync();
|
||||||
return string.IsNullOrWhiteSpace(content)
|
if (!response.IsSuccessStatusCode || string.IsNullOrWhiteSpace(content))
|
||||||
? new List<ProductInventoryItemView>()
|
return new List<ProductInventoryItemView>();
|
||||||
: JsonSerializer.Deserialize<List<ProductInventoryItemView>>(content, _options);
|
return JsonSerializer.Deserialize<List<ProductInventoryItemView>>(content, _options) ?? new List<ProductInventoryItemView>();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Fetch History for given customer
|
public async Task<List<ProductHistoryView>> GetProductInvoiceLines(string companyId)
|
||||||
/// </summary>
|
|
||||||
/// <param name="companyId"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
public async Task<List<ProductHistoryView>> FetchHistory(string companyId)
|
|
||||||
{
|
{
|
||||||
var response = await _client.GetAsync($"{_api.CrmCustomers}/{companyId}/{_api.CrmProductExt}");
|
var response = await _client.GetAsync($"{_api.CrmCustomers}/{companyId}/{_api.CrmProductExt}");
|
||||||
if (!response.IsSuccessStatusCode)
|
|
||||||
return new List<ProductHistoryView>();
|
|
||||||
var content = await response.Content.ReadAsStringAsync();
|
var content = await response.Content.ReadAsStringAsync();
|
||||||
return string.IsNullOrWhiteSpace(content)
|
if (!response.IsSuccessStatusCode || string.IsNullOrWhiteSpace(content))
|
||||||
? new List<ProductHistoryView>()
|
{
|
||||||
: JsonSerializer.Deserialize<List<ProductHistoryView>>(content, _options);
|
return new List<ProductHistoryView>();
|
||||||
|
}
|
||||||
|
return JsonSerializer.Deserialize<List<ProductHistoryView>>(content, _options) ?? new List<ProductHistoryView>();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Fetch history for given customer and a given product
|
public async Task<List<ProductHistoryView>> GetProductInvoiceLines(string companyId, int months)
|
||||||
/// </summary>
|
{
|
||||||
/// <param name="companyId"></param>
|
var response = await _client.GetAsync($"{_api.CrmCustomers}/{companyId}/{_api.CrmProductExt}/statistic?months={months}");
|
||||||
/// <param name="sku"></param>
|
var content = await response.Content.ReadAsStringAsync();
|
||||||
/// <returns></returns>
|
if (!response.IsSuccessStatusCode || string.IsNullOrWhiteSpace(content))
|
||||||
public async Task<List<ProductHistoryView>> FetchHistory(string companyId, string sku)
|
{
|
||||||
|
return new List<ProductHistoryView>();
|
||||||
|
}
|
||||||
|
return JsonSerializer.Deserialize<List<ProductHistoryView>>(content, _options) ?? new List<ProductHistoryView>();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public async Task<List<ProductHistoryView>> GetProductInvoiceLines(string companyId, string sku)
|
||||||
{
|
{
|
||||||
var response = await _client.GetAsync($"{_api.CrmCustomers}/{companyId}/{_api.CrmProductExt}/{sku}");
|
var response = await _client.GetAsync($"{_api.CrmCustomers}/{companyId}/{_api.CrmProductExt}/{sku}");
|
||||||
if (!response.IsSuccessStatusCode)
|
|
||||||
return new List<ProductHistoryView>();
|
|
||||||
var content = await response.Content.ReadAsStringAsync();
|
var content = await response.Content.ReadAsStringAsync();
|
||||||
return string.IsNullOrWhiteSpace(content)
|
if (!response.IsSuccessStatusCode || string.IsNullOrWhiteSpace(content))
|
||||||
? new List<ProductHistoryView>()
|
{
|
||||||
: JsonSerializer.Deserialize<List<ProductHistoryView>>(content, _options);
|
return new List<ProductHistoryView>();
|
||||||
|
}
|
||||||
|
return JsonSerializer.Deserialize<List<ProductHistoryView>>(content, _options) ?? new List<ProductHistoryView>();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// RPC call to initiate remote server sync for given customer
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="companyId"></param>
|
|
||||||
/// <param name="syncDate"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
public async Task<string> InvoiceErpToCrmRpc(string companyId, string syncDate)
|
public async Task<string> InvoiceErpToCrmRpc(string companyId, string syncDate)
|
||||||
{
|
{
|
||||||
var x = await _client.GetAsync($"{_api.SyncRpc}/companies/{companyId}/invoices/{syncDate}");
|
var x = await _client.GetAsync($"{_api.SyncRpc}/companies/{companyId}/invoices/{syncDate}");
|
||||||
if (!x.IsSuccessStatusCode)
|
if (!x.IsSuccessStatusCode)
|
||||||
|
{
|
||||||
return string.Empty;
|
return string.Empty;
|
||||||
|
}
|
||||||
return await x.Content.ReadAsStringAsync();
|
return await x.Content.ReadAsStringAsync();
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -49,7 +49,15 @@ public interface ICrmCustomerHistoryRepository
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="companyId"></param>
|
/// <param name="companyId"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
Task<List<ProductHistoryView>> FetchHistory(string companyId);
|
Task<List<ProductHistoryView>> GetProductInvoiceLines(string companyId);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Fetch history for customer for the past months. A hard limit on 24 months is enforced by the backed
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="companyId"></param>
|
||||||
|
/// <param name="months"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
Task<List<ProductHistoryView>> GetProductInvoiceLines(string companyId, int months);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Fetch history for given customer and a given product
|
/// Fetch history for given customer and a given product
|
||||||
|
@ -57,7 +65,7 @@ public interface ICrmCustomerHistoryRepository
|
||||||
/// <param name="companyId"></param>
|
/// <param name="companyId"></param>
|
||||||
/// <param name="sku"></param>
|
/// <param name="sku"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
Task<List<ProductHistoryView>> FetchHistory(string companyId, string sku);
|
Task<List<ProductHistoryView>> GetProductInvoiceLines(string companyId, string sku);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// RPC call to initiate remote server sync for given customer
|
/// RPC call to initiate remote server sync for given customer
|
||||||
|
|
|
@ -150,11 +150,22 @@ public class AuthenticationService : IAuthenticationService
|
||||||
((AuthStateProvider)_authStateProvider).NotifyUserLogout();
|
((AuthStateProvider)_authStateProvider).NotifyUserLogout();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public async Task<string> AccessToken()
|
||||||
|
{
|
||||||
|
return await _infoService.GetAccessToken();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public async Task<UserManagerEditView> UserInfo(bool write = false)
|
public async Task<UserManagerEditView> UserInfo(bool write = false)
|
||||||
{
|
{
|
||||||
|
// use http to fetch userInfo for authenticated user
|
||||||
var response = await _client.GetAsync(_apiConfig.Value.UserInfoAuth).ConfigureAwait(true);
|
var response = await _client.GetAsync(_apiConfig.Value.UserInfoAuth).ConfigureAwait(true);
|
||||||
|
|
||||||
var content = await response.Content.ReadAsStringAsync();
|
var content = await response.Content.ReadAsStringAsync();
|
||||||
|
if (!response.IsSuccessStatusCode || string.IsNullOrWhiteSpace(content))
|
||||||
|
{
|
||||||
|
return new UserManagerEditView();
|
||||||
|
}
|
||||||
var userInfo = JsonSerializer.Deserialize<UserManagerEditView>(content, _options) ?? new UserManagerEditView();
|
var userInfo = JsonSerializer.Deserialize<UserManagerEditView>(content, _options) ?? new UserManagerEditView();
|
||||||
if (write)
|
if (write)
|
||||||
{
|
{
|
||||||
|
|
|
@ -23,6 +23,7 @@ public interface IAuthenticationService
|
||||||
{
|
{
|
||||||
Task<AuthResponseView> Login(CredentialDto credentials);
|
Task<AuthResponseView> Login(CredentialDto credentials);
|
||||||
Task Logout();
|
Task Logout();
|
||||||
|
Task<string> AccessToken();
|
||||||
Task<string> RefreshToken();
|
Task<string> RefreshToken();
|
||||||
Task<UserManagerEditView> UserInfo(bool write = false);
|
Task<UserManagerEditView> UserInfo(bool write = false);
|
||||||
}
|
}
|
|
@ -40,13 +40,12 @@ public class RefreshTokenService
|
||||||
|
|
||||||
var expClaim = user.FindFirst(c => c.Type.Contains("exp"))?.Value;
|
var expClaim = user.FindFirst(c => c.Type.Contains("exp"))?.Value;
|
||||||
|
|
||||||
//var expTime = DateTimeOffset.FromUnixTimeSeconds(Convert.ToInt64(expClaim));
|
|
||||||
var expTime = DateTimeOffset.FromUnixTimeSeconds(Convert.ToInt64(expClaim));
|
var expTime = DateTimeOffset.FromUnixTimeSeconds(Convert.ToInt64(expClaim));
|
||||||
|
|
||||||
var diff = expTime - DateTime.UtcNow;
|
var diff = expTime - DateTime.UtcNow;
|
||||||
return diff.TotalMinutes <= 2
|
return diff.TotalMinutes <= 10
|
||||||
? await _authService.RefreshToken() //.ConfigureAwait(true)
|
? await _authService.RefreshToken()
|
||||||
: string.Empty;
|
: await _authService.AccessToken();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -47,7 +47,7 @@ public partial class CustomerInventoryReorderOverlay
|
||||||
if (string.IsNullOrWhiteSpace(SalesItem.Sku))
|
if (string.IsNullOrWhiteSpace(SalesItem.Sku))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
History = await HistoryRepo.FetchHistory(CompanyId, SalesItem.Sku);
|
History = await HistoryRepo.GetProductInvoiceLines(CompanyId, SalesItem.Sku);
|
||||||
if (!History.Any())
|
if (!History.Any())
|
||||||
await Task.Delay(1000);
|
await Task.Delay(1000);
|
||||||
SelectedItem.Item = SalesItem;
|
SelectedItem.Item = SalesItem;
|
||||||
|
|
|
@ -24,10 +24,15 @@ namespace Wonky.Client.OverlayCustomer;
|
||||||
|
|
||||||
public partial class CustomerInvoiceViewOverlay : IDisposable
|
public partial class CustomerInvoiceViewOverlay : IDisposable
|
||||||
{
|
{
|
||||||
[Parameter] public string CompanyId { get; set; } = "";
|
// ##############################################################
|
||||||
[Parameter] public string InvoiceId { get; set; } = "";
|
|
||||||
[Inject] public HttpInterceptorService Interceptor { get; set; }
|
[Inject] public HttpInterceptorService Interceptor { get; set; }
|
||||||
[Inject] public ICrmCustomerHistoryRepository HistoryRepo { get; set; }
|
[Inject] public ICrmCustomerHistoryRepository HistoryRepo { get; set; }
|
||||||
|
|
||||||
|
// ##############################################################
|
||||||
|
[Parameter] public string CompanyId { get; set; } = "";
|
||||||
|
[Parameter] public string InvoiceId { get; set; } = "";
|
||||||
|
|
||||||
|
// ##############################################################
|
||||||
private string _modalDisplay = "";
|
private string _modalDisplay = "";
|
||||||
private bool _showBackdrop;
|
private bool _showBackdrop;
|
||||||
private InvoiceView Invoice { get; set; } = new();
|
private InvoiceView Invoice { get; set; } = new();
|
||||||
|
|
|
@ -31,28 +31,32 @@ public partial class ProductSelectionOverlay
|
||||||
private List<DocView> FilteredList { get; set; } = new();
|
private List<DocView> FilteredList { get; set; } = new();
|
||||||
private string SearchTerm { get; set; } = "";
|
private string SearchTerm { get; set; } = "";
|
||||||
|
|
||||||
|
|
||||||
protected override void OnInitialized()
|
protected override void OnInitialized()
|
||||||
{
|
{
|
||||||
FilterItems(SearchTerm);
|
FilterItems(SearchTerm);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private async Task SelectItem(DocView item)
|
||||||
|
{
|
||||||
|
item.Added = !item.Added;
|
||||||
|
await OnSelectItem.InvokeAsync(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
private void ClearSearch()
|
private void ClearSearch()
|
||||||
{
|
{
|
||||||
SearchTerm = "";
|
SearchTerm = "";
|
||||||
FilterItems(SearchTerm);
|
FilterItems(SearchTerm);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private void OnSearchChanged()
|
private void OnSearchChanged()
|
||||||
{
|
{
|
||||||
FilterItems(SearchTerm);
|
FilterItems(SearchTerm);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task SelectItem(DocView item)
|
|
||||||
{
|
|
||||||
item.Added = !item.Added;
|
|
||||||
await OnSelectItem.InvokeAsync(item);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private void FilterItems(string filter)
|
private void FilterItems(string filter)
|
||||||
{
|
{
|
||||||
|
|
|
@ -22,9 +22,11 @@ namespace Wonky.Client.OverlayOffice;
|
||||||
|
|
||||||
public partial class OfficeCustomerActivityListOverlay
|
public partial class OfficeCustomerActivityListOverlay
|
||||||
{
|
{
|
||||||
|
// ##############################################################
|
||||||
[Parameter] public CompanyDto Company { get; set; } = new();
|
[Parameter] public CompanyDto Company { get; set; } = new();
|
||||||
[Parameter] public List<ReportItemView> ActivityList { get; set; } = new();
|
[Parameter] public List<ReportItemView> ActivityList { get; set; } = new();
|
||||||
|
|
||||||
|
// ##############################################################
|
||||||
private string _modalDisplay = "";
|
private string _modalDisplay = "";
|
||||||
private bool _showBackdrop;
|
private bool _showBackdrop;
|
||||||
|
|
||||||
|
|
|
@ -21,7 +21,10 @@ namespace Wonky.Client.OverlayOffice;
|
||||||
|
|
||||||
public partial class OfficeCustomerActivityViewOverlay
|
public partial class OfficeCustomerActivityViewOverlay
|
||||||
{
|
{
|
||||||
|
// ##############################################################
|
||||||
[Parameter] public ReportItemView Activity { get; set; } = new();
|
[Parameter] public ReportItemView Activity { get; set; } = new();
|
||||||
|
|
||||||
|
// ##############################################################
|
||||||
private string _modalDisplay = "";
|
private string _modalDisplay = "";
|
||||||
private bool _showBackdrop;
|
private bool _showBackdrop;
|
||||||
|
|
||||||
|
|
|
@ -30,11 +30,36 @@
|
||||||
<div class="list-group mt-2">
|
<div class="list-group mt-2">
|
||||||
<div class="list-group-item bg-dark text-white">
|
<div class="list-group-item bg-dark text-white">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-sm-4" style="cursor: pointer;" @onclick="@(() => SortProducts(ProductSort.Desc))"><i class="bi-sort-alpha-down"></i> Navn <i class="bi-sort-alpha-up-alt"></i></div>
|
@*
|
||||||
|
<div class="col-sm-4" style="cursor: pointer;" @onclick="@(() => SortProducts(ProductSort.Description))"><i class="bi-sort-alpha-down"></i> Navn <i class="bi-sort-alpha-up-alt"></i></div>
|
||||||
<div class="col-sm-3" style="cursor: pointer;" @onclick="@(() => SortProducts(ProductSort.Sku))"><i class="bi-sort-alpha-down"></i> Varenr <i class="bi-sort-alpha-up-alt"></i></div>
|
<div class="col-sm-3" style="cursor: pointer;" @onclick="@(() => SortProducts(ProductSort.Sku))"><i class="bi-sort-alpha-down"></i> Varenr <i class="bi-sort-alpha-up-alt"></i></div>
|
||||||
<div class="col-sm-2 text-center" style="cursor: pointer;" @onclick="@(() => SortProducts(ProductSort.Qty))"><i class="bi-sort-numeric-down"></i> Antal <i class="bi-sort-numeric-up-alt"></i></div>
|
*@
|
||||||
<div class="col-sm-2"></div>
|
<div class="col-sm-7 text-end">
|
||||||
<div class="col-sm-1"></div>
|
<div class="form-check form-check-inline">
|
||||||
|
<input class="form-check-input" type="checkbox" id="sortOrder" checked @onclick="@SetSortOrder"/>
|
||||||
|
<label class="form-check-label" for="sortOrder">
|
||||||
|
<i class="@(Descending ? "bi-sort-up" : "bi-sort-down-alt")"></i>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div class="form-check form-check-inline">
|
||||||
|
<input class="form-check-input" type="radio" name="sortCol" id="description" value="description"
|
||||||
|
onclick="@(() => SortProducts(ProductSort.Description))">
|
||||||
|
<label class="form-check-label" for="description">Navn</label>
|
||||||
|
</div>
|
||||||
|
<div class="form-check form-check-inline">
|
||||||
|
<input class="form-check-input" type="radio" name="sortCol" id="itemNumber" value="itemNumber"
|
||||||
|
onclick="@(() => SortProducts(ProductSort.Sku))">
|
||||||
|
<label class="form-check-label" for="itemNumber">Vare Nr.</label>
|
||||||
|
</div>
|
||||||
|
<div class="form-check form-check-inline">
|
||||||
|
<input class="form-check-input" type="radio" name="sortCol" id="lastInvoiceDate" value="itemDate"
|
||||||
|
onclick="@(() => SortProducts(ProductSort.LastInvoiceDate))" checked>
|
||||||
|
<label class="form-check-label" for="lastInvoiceDate">Sidst leveret</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-5">
|
||||||
|
<SearchPhraseComponent OnChanged="OnSearchChanged"/>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@foreach (var product in Inventory)
|
@foreach (var product in Inventory)
|
|
@ -16,6 +16,7 @@
|
||||||
|
|
||||||
using Microsoft.AspNetCore.Components;
|
using Microsoft.AspNetCore.Components;
|
||||||
using Wonky.Client.Enums;
|
using Wonky.Client.Enums;
|
||||||
|
using Wonky.Client.Helpers;
|
||||||
using Wonky.Client.HttpInterceptors;
|
using Wonky.Client.HttpInterceptors;
|
||||||
using Wonky.Client.HttpRepository;
|
using Wonky.Client.HttpRepository;
|
||||||
using Wonky.Client.Models;
|
using Wonky.Client.Models;
|
||||||
|
@ -26,81 +27,75 @@ using Wonky.Entity.Views;
|
||||||
|
|
||||||
namespace Wonky.Client.OverlayOffice;
|
namespace Wonky.Client.OverlayOffice;
|
||||||
|
|
||||||
public partial class OfficeCustomerProductListOverlay : IDisposable
|
public partial class OfficeCustomerInventoryListOverlay : IDisposable
|
||||||
{
|
{
|
||||||
|
// ##############################################################
|
||||||
[Inject] public HttpInterceptorService Interceptor { get; set; }
|
[Inject] public HttpInterceptorService Interceptor { get; set; }
|
||||||
[Inject] public ICountryCatalogRepository CatalogRepo { get; set; }
|
[Inject] public ICountryCatalogRepository CatalogRepo { get; set; }
|
||||||
[Inject] public ILogger<OfficeCustomerProductListOverlay> Logger { get; set; }
|
[Inject] public ILogger<OfficeCustomerInventoryListOverlay> Logger { get; set; }
|
||||||
|
|
||||||
|
// ##############################################################
|
||||||
|
[Parameter] public CompanyDto Company { get; set; } = new();
|
||||||
|
[Parameter] public List<ProductInventoryItemView> Inventory { get; set; } = new();
|
||||||
|
|
||||||
|
// ##############################################################
|
||||||
private string _modalDisplay = "";
|
private string _modalDisplay = "";
|
||||||
private bool _showBackdrop;
|
private bool _showBackdrop;
|
||||||
private DraftItem DraftItem { get; set; } = new();
|
private DraftItem DraftItem { get; set; } = new();
|
||||||
private SalesItemView SalesItem { get; set; } = new();
|
private SalesItemView SalesItem { get; set; } = new();
|
||||||
private OfficeCustomerInventoryReorderOverlay ReorderOverlay { get; set; } = new();
|
private OfficeCustomerInventoryReorderOverlay ReorderOverlay { get; set; } = new();
|
||||||
private bool Descending { get; set; }
|
private bool Descending { get; set; } = true;
|
||||||
|
private string SearchTerm { get; set; } = "";
|
||||||
|
private List<ProductInventoryItemView> FilteredList { get; set; } = new();
|
||||||
|
private ProductSort SortColumn { get; set; } = ProductSort.LastInvoiceDate;
|
||||||
|
|
||||||
[Parameter] public CompanyDto Company { get; set; } = new();
|
|
||||||
[Parameter] public List<ProductInventoryItemView> Inventory { get; set; } = new();
|
|
||||||
|
|
||||||
protected override void OnParametersSet()
|
|
||||||
{
|
|
||||||
if(Inventory.Any())
|
|
||||||
Inventory = Inventory.OrderBy(x => x.Description).ToList();
|
|
||||||
}
|
|
||||||
protected override void OnInitialized()
|
protected override void OnInitialized()
|
||||||
{
|
{
|
||||||
Interceptor.RegisterEvent();
|
Interceptor.RegisterEvent();
|
||||||
Interceptor.RegisterBeforeSendEvent();
|
Interceptor.RegisterBeforeSendEvent();
|
||||||
|
Inventory = Utils.SortInventory(Inventory, SortColumn, Descending);
|
||||||
|
FilterItems(SearchTerm);
|
||||||
StateHasChanged();
|
StateHasChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void OnSearchChanged(string searchTerm)
|
||||||
|
{
|
||||||
|
FilterItems(searchTerm);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void SortProducts(ProductSort column)
|
||||||
|
{
|
||||||
|
Descending = !Descending;
|
||||||
|
FilteredList = Utils.SortInventory(FilteredList, column, Descending);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void SetSortOrder()
|
||||||
|
{
|
||||||
|
Descending = !Descending;
|
||||||
|
FilteredList = Utils.SortInventory(FilteredList, SortColumn, Descending);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void FilterItems(string filter)
|
||||||
|
{
|
||||||
|
SearchTerm = filter;
|
||||||
|
FilteredList = string.IsNullOrWhiteSpace(filter)
|
||||||
|
? Inventory
|
||||||
|
: Inventory.Where(i => i.Description.ToLower().Contains(filter.ToLower())).ToList();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
private async Task ShowSkuReorder(string sku)
|
private async Task ShowSkuReorder(string sku)
|
||||||
{
|
{
|
||||||
SalesItem = await CatalogRepo.GetSalesItemSku(Company.CountryCode.ToLower(), sku);
|
SalesItem = await CatalogRepo.GetSalesItemSku(Company.CountryCode.ToLower(), sku);
|
||||||
ReorderOverlay.Show();
|
ReorderOverlay.Show();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SortProducts(ProductSort column)
|
|
||||||
{
|
|
||||||
Descending = !Descending;
|
|
||||||
switch (column)
|
|
||||||
{
|
|
||||||
case ProductSort.Desc:
|
|
||||||
if (Descending)
|
|
||||||
{
|
|
||||||
Inventory = Inventory.OrderByDescending(x => x.Description).ToList();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
Inventory = Inventory.OrderBy(x => x.Description).ToList();
|
|
||||||
break;
|
|
||||||
case ProductSort.Sku:
|
|
||||||
if (Descending)
|
|
||||||
{
|
|
||||||
Inventory = Inventory.OrderByDescending(x => x.Sku).ToList();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
Inventory = Inventory.OrderBy(x => x.Sku).ToList();
|
|
||||||
break;
|
|
||||||
case ProductSort.Qty:
|
|
||||||
if (Descending)
|
|
||||||
{
|
|
||||||
Inventory = Inventory.OrderByDescending(x => x.Quantity).ToList();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
Inventory = Inventory.OrderBy(x => x.Quantity).ToList();
|
|
||||||
break;
|
|
||||||
case ProductSort.None:
|
|
||||||
break;
|
|
||||||
case ProductSort.Abbr:
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
Inventory = Inventory.OrderByDescending(x => x.Quantity).ToList();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public void Show()
|
public void Show()
|
||||||
{
|
{
|
||||||
_modalDisplay = "block;";
|
_modalDisplay = "block;";
|
||||||
|
@ -108,6 +103,7 @@ public partial class OfficeCustomerProductListOverlay : IDisposable
|
||||||
StateHasChanged();
|
StateHasChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private void Hide()
|
private void Hide()
|
||||||
{
|
{
|
||||||
_modalDisplay = "none;";
|
_modalDisplay = "none;";
|
||||||
|
@ -115,9 +111,9 @@ public partial class OfficeCustomerProductListOverlay : IDisposable
|
||||||
StateHasChanged();
|
StateHasChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
Interceptor.DisposeEvent();
|
Interceptor.DisposeEvent();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -26,10 +26,15 @@ namespace Wonky.Client.OverlayOffice;
|
||||||
|
|
||||||
public partial class OfficeCustomerInventoryReorderOverlay
|
public partial class OfficeCustomerInventoryReorderOverlay
|
||||||
{
|
{
|
||||||
|
// ##############################################################
|
||||||
[Parameter] public CompanyDto Company { get; set; }
|
[Parameter] public CompanyDto Company { get; set; }
|
||||||
[Parameter] public SalesItemView SalesItem { get; set; } = new();
|
[Parameter] public SalesItemView SalesItem { get; set; } = new();
|
||||||
[Inject] public ICountryCustomerHistoryRepository HistoryRepo { get; set; }
|
[Inject] public ICountryCustomerHistoryRepository HistoryRepo { get; set; }
|
||||||
|
|
||||||
|
// ##############################################################
|
||||||
[Parameter] public EventCallback<DraftItem> OrderItemCallback { get; set; }
|
[Parameter] public EventCallback<DraftItem> OrderItemCallback { get; set; }
|
||||||
|
|
||||||
|
// ##############################################################
|
||||||
private List<ProductHistoryView> History { get; set; } = new();
|
private List<ProductHistoryView> History { get; set; } = new();
|
||||||
private DraftItem SelectedItem { get; set; } = new();
|
private DraftItem SelectedItem { get; set; } = new();
|
||||||
private string ProductName { get; set; } = "";
|
private string ProductName { get; set; } = "";
|
||||||
|
|
|
@ -24,12 +24,16 @@ namespace Wonky.Client.OverlayOffice;
|
||||||
|
|
||||||
public partial class OfficeCustomerInvoiceViewOverlay : IDisposable
|
public partial class OfficeCustomerInvoiceViewOverlay : IDisposable
|
||||||
{
|
{
|
||||||
|
// ##############################################################
|
||||||
[Parameter] public string CompanyId { get; set; } = "";
|
[Parameter] public string CompanyId { get; set; } = "";
|
||||||
[Parameter] public string InvoiceId { get; set; } = "";
|
[Parameter] public string InvoiceId { get; set; } = "";
|
||||||
[Parameter] public string CountryCode { get; set; } = "";
|
[Parameter] public string CountryCode { get; set; } = "";
|
||||||
|
|
||||||
|
// ##############################################################
|
||||||
[Inject] public HttpInterceptorService Interceptor { get; set; }
|
[Inject] public HttpInterceptorService Interceptor { get; set; }
|
||||||
[Inject] public ICountryCustomerHistoryRepository HistoryRepo { get; set; }
|
[Inject] public ICountryCustomerHistoryRepository HistoryRepo { get; set; }
|
||||||
|
|
||||||
|
// ##############################################################
|
||||||
private string _modalDisplay = "";
|
private string _modalDisplay = "";
|
||||||
private bool _showBackdrop;
|
private bool _showBackdrop;
|
||||||
private InvoiceView Invoice { get; set; } = new();
|
private InvoiceView Invoice { get; set; } = new();
|
||||||
|
|
|
@ -23,7 +23,7 @@
|
||||||
<button type="button" class="btn-close" @onclick="@Hide" data-bs-dismiss="modal" aria-label="Luk"></button>
|
<button type="button" class="btn-close" @onclick="@Hide" data-bs-dismiss="modal" aria-label="Luk"></button>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-body">
|
<div class="modal-body">
|
||||||
<OfficeInventoryListComponent OnReorderSelected="OnReorderCallback" CompanyId="@Company.CompanyId" Inventory="@Inventory"/>
|
<OfficeCustomerInventoryListComponent OnReorderSelected="OnReorderCallback" CompanyId="@Company.CompanyId" Inventory="@Inventory"/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -33,4 +33,4 @@
|
||||||
<div class="modal-backdrop fade show"></div>
|
<div class="modal-backdrop fade show"></div>
|
||||||
}
|
}
|
||||||
|
|
||||||
<OfficeOrderInventoryReorderOverlay Company="@Company" SalesItem="SalesItem" OnSelected="OnSelected" @ref="ReorderOverlay" />
|
<OfficeCustomerOrderInventoryReorderOverlay Company="@Company" SalesItem="SalesItem" OnSelected="OnSelected" @ref="ReorderOverlay" />
|
|
@ -24,23 +24,26 @@ using Wonky.Entity.Views;
|
||||||
|
|
||||||
namespace Wonky.Client.OverlayOffice;
|
namespace Wonky.Client.OverlayOffice;
|
||||||
|
|
||||||
public partial class OfficeOrderInventoryListOverlay : IDisposable
|
public partial class OfficeCustomerOrderInventoryListOverlay : IDisposable
|
||||||
{
|
{
|
||||||
|
// ##############################################################
|
||||||
[Inject] public HttpInterceptorService Interceptor { get; set; }
|
[Inject] public HttpInterceptorService Interceptor { get; set; }
|
||||||
[Inject] public ICountryCatalogRepository CatalogRepo { get; set; }
|
[Inject] public ICountryCatalogRepository CatalogRepo { get; set; }
|
||||||
[Inject] public ILogger<OfficeOrderInventoryListOverlay> Logger { get; set; }
|
[Inject] public ILogger<OfficeCustomerOrderInventoryListOverlay> Logger { get; set; }
|
||||||
|
|
||||||
|
// ##############################################################
|
||||||
[Parameter] public CompanyDto Company { get; set; } = new();
|
[Parameter] public CompanyDto Company { get; set; } = new();
|
||||||
[Parameter] public List<ProductInventoryItemView> Inventory { get; set; } = new();
|
[Parameter] public List<ProductInventoryItemView> Inventory { get; set; } = new();
|
||||||
[Parameter] public EventCallback<DraftItem> OnSelected { get; set; }
|
[Parameter] public EventCallback<DraftItem> OnSelected { get; set; }
|
||||||
|
|
||||||
|
// ##############################################################
|
||||||
private string _modalDisplay = "";
|
private string _modalDisplay = "";
|
||||||
private bool _showBackdrop;
|
private bool _showBackdrop;
|
||||||
// private List<ProductInventoryView> ProductList { get; set; } = new();
|
// private List<ProductInventoryView> ProductList { get; set; } = new();
|
||||||
private DraftItem DraftItem { get; set; } = new();
|
private DraftItem DraftItem { get; set; } = new();
|
||||||
private SalesItemView SalesItem { get; set; } = new();
|
private SalesItemView SalesItem { get; set; } = new();
|
||||||
|
|
||||||
private OfficeOrderInventoryReorderOverlay ReorderOverlay { get; set; } = new();
|
private OfficeCustomerOrderInventoryReorderOverlay ReorderOverlay { get; set; } = new();
|
||||||
|
|
||||||
protected override void OnParametersSet()
|
protected override void OnParametersSet()
|
||||||
{
|
{
|
|
@ -24,12 +24,17 @@ using Wonky.Entity.Views;
|
||||||
|
|
||||||
namespace Wonky.Client.OverlayOffice;
|
namespace Wonky.Client.OverlayOffice;
|
||||||
|
|
||||||
public partial class OfficeOrderInventoryReorderOverlay
|
public partial class OfficeCustomerOrderInventoryReorderOverlay
|
||||||
{
|
{
|
||||||
|
// ##############################################################
|
||||||
[Inject] public ICountryCustomerHistoryRepository HistoryRepo { get; set; }
|
[Inject] public ICountryCustomerHistoryRepository HistoryRepo { get; set; }
|
||||||
|
|
||||||
|
// ##############################################################
|
||||||
[Parameter] public CompanyDto Company { get; set; } = new();
|
[Parameter] public CompanyDto Company { get; set; } = new();
|
||||||
[Parameter] public SalesItemView SalesItem { get; set; } = new();
|
[Parameter] public SalesItemView SalesItem { get; set; } = new();
|
||||||
[Parameter] public EventCallback<DraftItem> OnSelected { get; set; }
|
[Parameter] public EventCallback<DraftItem> OnSelected { get; set; }
|
||||||
|
|
||||||
|
// ##############################################################
|
||||||
private List<ProductHistoryView>? ProductHistory { get; set; } = new();
|
private List<ProductHistoryView>? ProductHistory { get; set; } = new();
|
||||||
private DraftItem SelectedItem { get; set; } = new();
|
private DraftItem SelectedItem { get; set; } = new();
|
||||||
private string ProductName { get; set; } = "";
|
private string ProductName { get; set; } = "";
|
|
@ -29,17 +29,17 @@ namespace Wonky.Client.OverlayOrderCreate;
|
||||||
|
|
||||||
public partial class CatalogPagedOverlay : IDisposable
|
public partial class CatalogPagedOverlay : IDisposable
|
||||||
{
|
{
|
||||||
// injections
|
// ##############################################################
|
||||||
[Inject] public ICountryCatalogRepository CatalogRepo { get; set; }
|
[Inject] public ICountryCatalogRepository CatalogRepo { get; set; }
|
||||||
[Inject] public HttpInterceptorService Interceptor { get; set; }
|
[Inject] public HttpInterceptorService Interceptor { get; set; }
|
||||||
[Inject] public UserPreferenceService PreferenceService { get; set; }
|
[Inject] public UserPreferenceService PreferenceService { get; set; }
|
||||||
[Inject] public ILogger<CatalogPagedOverlay> Logger { get; set; }
|
[Inject] public ILogger<CatalogPagedOverlay> Logger { get; set; }
|
||||||
|
|
||||||
// parameters
|
// ##############################################################
|
||||||
[Parameter] public string CountryCode { get; set; } = "";
|
[Parameter] public string CountryCode { get; set; } = "";
|
||||||
[Parameter] public EventCallback<SelectedSku> OnSelected { get; set; }
|
[Parameter] public EventCallback<SelectedSku> OnSelected { get; set; }
|
||||||
|
|
||||||
// variables
|
// ##############################################################
|
||||||
private string _modalDisplay = "";
|
private string _modalDisplay = "";
|
||||||
private bool _showBackdrop;
|
private bool _showBackdrop;
|
||||||
private List<SalesItemView> Items { get; set; } = new();
|
private List<SalesItemView> Items { get; set; } = new();
|
||||||
|
|
|
@ -21,13 +21,16 @@ namespace Wonky.Client.OverlayOrderCreate;
|
||||||
|
|
||||||
public partial class ProductCheckConfirmationOverlay
|
public partial class ProductCheckConfirmationOverlay
|
||||||
{
|
{
|
||||||
private string _modalDisplay = "";
|
// ##############################################################
|
||||||
private bool _showBackdrop;
|
|
||||||
[Parameter] public string BodyMessage { get; set; } = "";
|
[Parameter] public string BodyMessage { get; set; } = "";
|
||||||
[Parameter] public string CompanyId { get; set; } = "";
|
[Parameter] public string CompanyId { get; set; } = "";
|
||||||
[Parameter] public List<ProductInventoryItemView> Products { get; set; } = new();
|
[Parameter] public List<ProductInventoryItemView> Products { get; set; } = new();
|
||||||
[Parameter] public EventCallback OnOkClicked { get; set; }
|
[Parameter] public EventCallback OnOkClicked { get; set; }
|
||||||
|
|
||||||
|
// ##############################################################
|
||||||
|
private string _modalDisplay = "";
|
||||||
|
private bool _showBackdrop;
|
||||||
|
|
||||||
public void Show()
|
public void Show()
|
||||||
{
|
{
|
||||||
_modalDisplay = "block;";
|
_modalDisplay = "block;";
|
||||||
|
|
|
@ -24,10 +24,14 @@ namespace Wonky.Client.OverlayOrderCreate;
|
||||||
|
|
||||||
public partial class ProductHistoryOverlay
|
public partial class ProductHistoryOverlay
|
||||||
{
|
{
|
||||||
// [Parameter] public EventCallback<decimal> OnSelected { get; set; }
|
// ##############################################################
|
||||||
|
[Inject] public ICrmCustomerHistoryRepository HistoryRepo { get; set; }
|
||||||
|
|
||||||
|
// ##############################################################
|
||||||
[Parameter] public string CompanyId { get; set; } = "";
|
[Parameter] public string CompanyId { get; set; } = "";
|
||||||
[Parameter] public string ItemSku { get; set; } = "";
|
[Parameter] public string ItemSku { get; set; } = "";
|
||||||
[Inject] public ICrmCustomerHistoryRepository HistoryRepo { get; set; }
|
|
||||||
|
// ##############################################################
|
||||||
private List<ProductHistoryView>? History { get; set; }
|
private List<ProductHistoryView>? History { get; set; }
|
||||||
private string ProductName { get; set; } = "";
|
private string ProductName { get; set; } = "";
|
||||||
private string _modalDisplay = "";
|
private string _modalDisplay = "";
|
||||||
|
@ -35,18 +39,13 @@ public partial class ProductHistoryOverlay
|
||||||
|
|
||||||
protected override async Task OnParametersSetAsync()
|
protected override async Task OnParametersSetAsync()
|
||||||
{
|
{
|
||||||
History = await HistoryRepo.FetchHistory(CompanyId, ItemSku);
|
History = await HistoryRepo.GetProductInvoiceLines(CompanyId, ItemSku);
|
||||||
if (History.Any())
|
if (History.Any())
|
||||||
{
|
{
|
||||||
ProductName = History[0].Description;
|
ProductName = History[0].Description;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// private void SelectPrice(decimal price)
|
|
||||||
// {
|
|
||||||
// OnSelected.InvokeAsync(price);
|
|
||||||
// Hide();
|
|
||||||
// }
|
|
||||||
|
|
||||||
public void Show()
|
public void Show()
|
||||||
{
|
{
|
||||||
|
@ -55,6 +54,7 @@ public partial class ProductHistoryOverlay
|
||||||
StateHasChanged();
|
StateHasChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private void Hide()
|
private void Hide()
|
||||||
{
|
{
|
||||||
_modalDisplay = "none;";
|
_modalDisplay = "none;";
|
||||||
|
|
|
@ -24,10 +24,15 @@ namespace Wonky.Client.OverlayOrderCreate;
|
||||||
|
|
||||||
public partial class ProductPriceHistoryOverlay
|
public partial class ProductPriceHistoryOverlay
|
||||||
{
|
{
|
||||||
|
// ##############################################################
|
||||||
|
[Inject] public ICrmCustomerHistoryRepository HistoryRepo { get; set; }
|
||||||
|
|
||||||
|
// ##############################################################
|
||||||
[Parameter] public EventCallback<decimal> OnSelected { get; set; }
|
[Parameter] public EventCallback<decimal> OnSelected { get; set; }
|
||||||
[Parameter] public string CompanyId { get; set; } = "";
|
[Parameter] public string CompanyId { get; set; } = "";
|
||||||
[Parameter] public string Sku { get; set; } = "";
|
[Parameter] public string Sku { get; set; } = "";
|
||||||
[Inject] public ICrmCustomerHistoryRepository HistoryRepo { get; set; }
|
|
||||||
|
// ##############################################################
|
||||||
private List<ProductHistoryView>? ProductHistory { get; set; }
|
private List<ProductHistoryView>? ProductHistory { get; set; }
|
||||||
private string ProductName { get; set; } = "";
|
private string ProductName { get; set; } = "";
|
||||||
private string _modalDisplay = "";
|
private string _modalDisplay = "";
|
||||||
|
@ -38,19 +43,21 @@ public partial class ProductPriceHistoryOverlay
|
||||||
if (string.IsNullOrWhiteSpace(Sku))
|
if (string.IsNullOrWhiteSpace(Sku))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
ProductHistory = await HistoryRepo.FetchHistory(CompanyId, Sku);
|
ProductHistory = await HistoryRepo.GetProductInvoiceLines(CompanyId, Sku);
|
||||||
if (ProductHistory.Any())
|
if (ProductHistory.Any())
|
||||||
{
|
{
|
||||||
ProductName = ProductHistory[0].Description;
|
ProductName = ProductHistory[0].Description;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private void SelectPrice(decimal price)
|
private void SelectPrice(decimal price)
|
||||||
{
|
{
|
||||||
OnSelected.InvokeAsync(price);
|
OnSelected.InvokeAsync(price);
|
||||||
Hide();
|
Hide();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void Show()
|
public void Show()
|
||||||
{
|
{
|
||||||
_modalDisplay = "block;";
|
_modalDisplay = "block;";
|
||||||
|
@ -58,6 +65,7 @@ public partial class ProductPriceHistoryOverlay
|
||||||
StateHasChanged();
|
StateHasChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private void Hide()
|
private void Hide()
|
||||||
{
|
{
|
||||||
_modalDisplay = "none;";
|
_modalDisplay = "none;";
|
||||||
|
|
|
@ -22,7 +22,7 @@
|
||||||
<PageTitle>Produkt oversigt for @Company.Name</PageTitle>
|
<PageTitle>Produkt oversigt for @Company.Name</PageTitle>
|
||||||
<div class="row ps-3 pt-2 pb-1 rounded-2 bg-dark text-white">
|
<div class="row ps-3 pt-2 pb-1 rounded-2 bg-dark text-white">
|
||||||
<div class="col-sm-6">
|
<div class="col-sm-6">
|
||||||
<h4 class="pt-1">Produkt oversigt @Company.Name</h4>
|
<h4 class="pt-1">Produkt køb @Company.Name</h4>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-sm-3 align-content-end d-print-none">
|
<div class="col-sm-3 align-content-end d-print-none">
|
||||||
<a class="btn btn-primary d-block" href="/advisor/customers/@CompanyId"><i class="bi-chevron-left"></i> Stamkort</a>
|
<a class="btn btn-primary d-block" href="/advisor/customers/@CompanyId"><i class="bi-chevron-left"></i> Stamkort</a>
|
||||||
|
@ -33,10 +33,9 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<CustomerInventoryListComponent OnReorderSelected="OnReorderCallback" CompanyId="@CompanyId" Inventory="@Inventory"/>
|
<CustomerInventoryListComponent OnReorderSelected="OnReorderCallback" CompanyId="@CompanyId" Inventory="@Inventory"/>
|
||||||
|
<CustomerInventoryReorderOverlay OnSelected="@OnSelectedItem" CompanyId="@CompanyId" SalesItem="@SalesItem" @ref="ReorderOverlay"/>
|
||||||
|
|
||||||
@if (Working)
|
@if (Working)
|
||||||
{
|
{
|
||||||
<WorkingThreeDots/>
|
<WorkingThreeDots/>
|
||||||
}
|
}
|
||||||
|
|
||||||
<CustomerInventoryReorderOverlay OnSelected="@OnSelectedItem" CompanyId="@CompanyId" SalesItem="@SalesItem" @ref="ReorderOverlay"/>
|
|
||||||
|
|
|
@ -19,6 +19,8 @@ using System.Xml;
|
||||||
using Blazored.LocalStorage;
|
using Blazored.LocalStorage;
|
||||||
using Blazored.Toast.Services;
|
using Blazored.Toast.Services;
|
||||||
using Microsoft.AspNetCore.Components;
|
using Microsoft.AspNetCore.Components;
|
||||||
|
using Wonky.Client.Enums;
|
||||||
|
using Wonky.Client.Helpers;
|
||||||
using Wonky.Client.HttpInterceptors;
|
using Wonky.Client.HttpInterceptors;
|
||||||
using Wonky.Client.HttpRepository;
|
using Wonky.Client.HttpRepository;
|
||||||
using Wonky.Client.Models;
|
using Wonky.Client.Models;
|
||||||
|
@ -66,6 +68,7 @@ public partial class AdvisorCustomerInventoryListPage : IDisposable
|
||||||
Working = false;
|
Working = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private async Task OnReorderCallback(string sku)
|
private async Task OnReorderCallback(string sku)
|
||||||
{
|
{
|
||||||
// fetch item from http repo
|
// fetch item from http repo
|
||||||
|
|
|
@ -311,12 +311,9 @@
|
||||||
<button type="button" class="btn btn-outline-dark" @onclick="@ToggleVisibility">@ToggleButtonText</button>
|
<button type="button" class="btn btn-outline-dark" @onclick="@ToggleVisibility">@ToggleButtonText</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-sm-4 d-grid">
|
<div class="col-sm-4 d-grid">
|
||||||
@if (AppInfo!.Value!.Rc)
|
@if (UserInfo.CountryCode is "DK")
|
||||||
{
|
{
|
||||||
@if (UserInfo.CountryCode is "DK")
|
<a class="btn btn-info" href="@($"/advisor/customers/{CompanyId}/workplaces")">Kemi Dokumentation</a>
|
||||||
{
|
|
||||||
<a class="btn btn-info" href="@($"/advisor/customers/{CompanyId}/workplaces")">Kemi Dokumentation</a>
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -33,12 +33,11 @@
|
||||||
<div class="col-sm-12 col-md-6">
|
<div class="col-sm-12 col-md-6">
|
||||||
<InfoColorCustomerComponent/>
|
<InfoColorCustomerComponent/>
|
||||||
</div>
|
</div>
|
||||||
|
@*
|
||||||
<div class="col-sm-12 col-md-6">
|
<div class="col-sm-12 col-md-6">
|
||||||
<InfoColorPackageComponent/>
|
<InfoColorPackageComponent/>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-sm-12 col-md-6">
|
*@
|
||||||
<InfoCommonComponent />
|
|
||||||
</div>
|
|
||||||
<div class="col-sm-12 col-md-6">
|
<div class="col-sm-12 col-md-6">
|
||||||
<InfoProcessStateComponent />
|
<InfoProcessStateComponent />
|
||||||
</div>
|
</div>
|
||||||
|
@ -48,12 +47,17 @@
|
||||||
<div class="col-sm-12 col-md-6">
|
<div class="col-sm-12 col-md-6">
|
||||||
<InfoQuoteToolbarComponent/>
|
<InfoQuoteToolbarComponent/>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="col-sm-12 col-md-6">
|
||||||
|
<InfoCommonComponent />
|
||||||
|
</div>
|
||||||
<div class="col-sm-12 col-md-6">
|
<div class="col-sm-12 col-md-6">
|
||||||
<InfoOfficeComponent />
|
<InfoOfficeComponent />
|
||||||
</div>
|
</div>
|
||||||
|
@*
|
||||||
<div class="col-sm-12 col-md-6">
|
<div class="col-sm-12 col-md-6">
|
||||||
<InfoWarehouseComponent />
|
<InfoWarehouseComponent />
|
||||||
</div>
|
</div>
|
||||||
|
*@
|
||||||
<div class="col-sm-12 col-md-6">
|
<div class="col-sm-12 col-md-6">
|
||||||
<InfoBrowserComponent />
|
<InfoBrowserComponent />
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -245,4 +245,4 @@
|
||||||
<CatalogPagedOverlay @ref="CatalogOverlay" CountryCode="@CountryCode" OnSelected="PriceListCallback"/>
|
<CatalogPagedOverlay @ref="CatalogOverlay" CountryCode="@CountryCode" OnSelected="PriceListCallback"/>
|
||||||
<OfficeCustomerInvoiceListOverlay @ref="InvoiceListOverlay" Company="Company" InvoiceList="CompanyInvoices"/>
|
<OfficeCustomerInvoiceListOverlay @ref="InvoiceListOverlay" Company="Company" InvoiceList="CompanyInvoices"/>
|
||||||
<OfficeCustomerActivityListOverlay @ref="ActivityListOverlay" Company="Company" ActivityList="CompanyActivities"/>
|
<OfficeCustomerActivityListOverlay @ref="ActivityListOverlay" Company="Company" ActivityList="CompanyActivities"/>
|
||||||
<OfficeOrderInventoryListOverlay @ref="InventoryListOverlay" Company="Company" Inventory="CompanyInventory" OnSelected="InventoryCallback"/>
|
<OfficeCustomerOrderInventoryListOverlay @ref="InventoryListOverlay" Company="Company" Inventory="CompanyInventory" OnSelected="InventoryCallback"/>
|
|
@ -80,7 +80,7 @@ public partial class OfficeOrderCreatePage : IDisposable
|
||||||
private CatalogPagedOverlay CatalogOverlay { get; set; } = new();
|
private CatalogPagedOverlay CatalogOverlay { get; set; } = new();
|
||||||
private OfficeCustomerInvoiceListOverlay InvoiceListOverlay { get; set; } = new();
|
private OfficeCustomerInvoiceListOverlay InvoiceListOverlay { get; set; } = new();
|
||||||
private OfficeCustomerActivityListOverlay ActivityListOverlay { get; set; } = new();
|
private OfficeCustomerActivityListOverlay ActivityListOverlay { get; set; } = new();
|
||||||
private OfficeOrderInventoryListOverlay InventoryListOverlay { get; set; } = new();
|
private OfficeCustomerOrderInventoryListOverlay InventoryListOverlay { get; set; } = new();
|
||||||
|
|
||||||
// #############################################################
|
// #############################################################
|
||||||
// lists
|
// lists
|
||||||
|
|
|
@ -37,6 +37,7 @@ public partial class SupervisorDocumentNewPage : IDisposable
|
||||||
[Inject] public ILogger<SupervisorDocumentNewPage> Logger { get; set; }
|
[Inject] public ILogger<SupervisorDocumentNewPage> Logger { get; set; }
|
||||||
[Inject] public IToastService Toaster { get; set; }
|
[Inject] public IToastService Toaster { get; set; }
|
||||||
[Inject] public NavigationManager Navigator { get; set; }
|
[Inject] public NavigationManager Navigator { get; set; }
|
||||||
|
[Inject] public ISystemSendMailService SendMail { get; set; }
|
||||||
|
|
||||||
|
|
||||||
// ############################################################
|
// ############################################################
|
||||||
|
@ -102,6 +103,25 @@ public partial class SupervisorDocumentNewPage : IDisposable
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Toaster.ShowSuccess("Ok");
|
Toaster.ShowSuccess("Ok");
|
||||||
|
var sendTo = new List<EmailContact>
|
||||||
|
{
|
||||||
|
new () { Email = "paul@innotec.dk", Name = "Paul Vendelbo" },
|
||||||
|
new () { Email = "eddie@innotec.dk", Name = "Eddie Broch" }
|
||||||
|
};
|
||||||
|
var msg = new EmailMessage
|
||||||
|
{
|
||||||
|
Body = Document.Content,
|
||||||
|
Subject = Document.Description,
|
||||||
|
To = sendTo,
|
||||||
|
IsBodyHtml = false
|
||||||
|
};
|
||||||
|
Toaster.ShowInfo("Sender email ...");
|
||||||
|
var result = await SendMail.SendMail("system", msg);
|
||||||
|
if (result.IsSuccess)
|
||||||
|
{
|
||||||
|
Toaster.ClearAll();
|
||||||
|
Toaster.ShowInfo("Email sendt.");
|
||||||
|
}
|
||||||
Navigator.NavigateTo($"/supervisor/advisors/{AdvisorId}/documents");
|
Navigator.NavigateTo($"/supervisor/advisors/{AdvisorId}/documents");
|
||||||
}
|
}
|
||||||
Toaster.ClearAll();
|
Toaster.ClearAll();
|
||||||
|
|
|
@ -82,7 +82,7 @@
|
||||||
<div class="card-footer">
|
<div class="card-footer">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col text-start">
|
<div class="col text-start">
|
||||||
<button type="button" class="btn btn-warning" nclick="@RemoveDocument"><i class="bi-trash"></i> Slet</button>
|
<button type="button" class="btn btn-warning" @onclick="@RemoveDocument"><i class="bi-trash"></i> Slet</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="col text-end">
|
<div class="col text-end">
|
||||||
<button type="submit" class="btn btn-primary"><i class="bi-cloud-upload"></i> Gem</button>
|
<button type="submit" class="btn btn-primary"><i class="bi-cloud-upload"></i> Gem</button>
|
||||||
|
|
|
@ -1,36 +0,0 @@
|
||||||
@* Copyright (C) 2022 FCS Frede's Computer Services.
|
|
||||||
// This program is free software: you can redistribute it and/or modify
|
|
||||||
// it under the terms of the GNU Affero General Public License as
|
|
||||||
// published by the Free Software Foundation, either version 3 of the
|
|
||||||
// License, or (at your option) any later version.
|
|
||||||
//
|
|
||||||
// This program is distributed in the hope that it will be useful,
|
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
// GNU Affero General Public License for more details.
|
|
||||||
//
|
|
||||||
// You should have received a copy of the GNU Affero General Public License
|
|
||||||
// along with this program. If not, see [https://www.gnu.org/licenses/agpl-3.0.en.html]
|
|
||||||
*@
|
|
||||||
|
|
||||||
|
|
||||||
@using Wonky.Client.Components
|
|
||||||
@using Microsoft.AspNetCore.Authorization
|
|
||||||
@attribute [Authorize(Roles = "Admin,Office,Warehouse")]
|
|
||||||
|
|
||||||
@page "/warehouse/orders/{Status}"
|
|
||||||
|
|
||||||
<div class="row">
|
|
||||||
<div class="col">
|
|
||||||
<h2>Forsendelser</h2>
|
|
||||||
</div>
|
|
||||||
<div class="col">
|
|
||||||
<div class="busy-signal" style="display:@(Working ? "block" : "none")">
|
|
||||||
<div class="spinner-grow text-info" role="status">
|
|
||||||
<span class="visually-hidden">Loading...</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<WarehouseListComponent Header="@Header" OrderList="@OrderList" ReadyToShip="@ReadyToShip"
|
|
||||||
OnGetStatus="GetStatusCallback" OnSetShipped="@SetShippedCallback" OnQPak="QPakCallback" />
|
|
|
@ -1,133 +0,0 @@
|
||||||
// Copyright (C) 2022 FCS Frede's Computer Services.
|
|
||||||
// This program is free software: you can redistribute it and/or modify
|
|
||||||
// it under the terms of the GNU Affero General Public License as
|
|
||||||
// published by the Free Software Foundation, either version 3 of the
|
|
||||||
// License, or (at your option) any later version.
|
|
||||||
//
|
|
||||||
// This program is distributed in the hope that it will be useful,
|
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
// GNU Affero General Public License for more details.
|
|
||||||
//
|
|
||||||
// You should have received a copy of the GNU Affero General Public License
|
|
||||||
// along with this program. If not, see [https://www.gnu.org/licenses/agpl-3.0.en.html]
|
|
||||||
//
|
|
||||||
|
|
||||||
|
|
||||||
using Microsoft.AspNetCore.Components;
|
|
||||||
using Wonky.Client.Enums;
|
|
||||||
using Wonky.Client.Helpers;
|
|
||||||
using Wonky.Client.HttpInterceptors;
|
|
||||||
using Wonky.Client.HttpRepository;
|
|
||||||
using Wonky.Client.Models;
|
|
||||||
using Wonky.Entity.DTO;
|
|
||||||
using Wonky.Entity.Views;
|
|
||||||
#pragma warning disable CS8618
|
|
||||||
|
|
||||||
namespace Wonky.Client.Pages;
|
|
||||||
|
|
||||||
public partial class WarehouseOrderListPage : IDisposable
|
|
||||||
{
|
|
||||||
// #############################################################
|
|
||||||
[Inject] public HttpInterceptorService Interceptor { get; set; }
|
|
||||||
[Inject] public IOrderProcessRepository OrderProcessRepo { get; set; }
|
|
||||||
[Inject] public NavigationManager Navigator { get; set; }
|
|
||||||
|
|
||||||
// #############################################################
|
|
||||||
[Parameter] public string Status { get; set; } = "none";
|
|
||||||
|
|
||||||
// #############################################################
|
|
||||||
private List<WarehouseOrderView> OrderList { get; set; } = new();
|
|
||||||
private bool Working { get; set; } = true;
|
|
||||||
private string Header { get; set; } = "Ubehandlet";
|
|
||||||
private bool ReadyToShip { get; set; }
|
|
||||||
|
|
||||||
|
|
||||||
protected override async Task OnParametersSetAsync()
|
|
||||||
{
|
|
||||||
Interceptor.RegisterEvent();
|
|
||||||
Interceptor.RegisterBeforeSendEvent();
|
|
||||||
OrderList = await FetchOrders(Status);
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task GetStatusCallback(ProcessStatus status)
|
|
||||||
{
|
|
||||||
Working = true;
|
|
||||||
OrderList = new List<WarehouseOrderView>();
|
|
||||||
switch (status)
|
|
||||||
{
|
|
||||||
case ProcessStatus.None or ProcessStatus.Printed:
|
|
||||||
Header = "Ubehandlede ordrer";
|
|
||||||
ReadyToShip = false;
|
|
||||||
break;
|
|
||||||
case ProcessStatus.Picked:
|
|
||||||
Header = "Plukkede ordrer";
|
|
||||||
ReadyToShip = false;
|
|
||||||
break;
|
|
||||||
case ProcessStatus.Packed:
|
|
||||||
Header = "Pakkede ordrer";
|
|
||||||
ReadyToShip = true;
|
|
||||||
break;
|
|
||||||
case ProcessStatus.Shipped:
|
|
||||||
break;
|
|
||||||
case ProcessStatus.All:
|
|
||||||
break;
|
|
||||||
case ProcessStatus.Express:
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
throw new ArgumentOutOfRangeException(nameof(status), status, null);
|
|
||||||
}
|
|
||||||
Status = Utils.EnumToString(status).ToLower();
|
|
||||||
OrderList = await FetchOrders(Status);
|
|
||||||
Working = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// QPak - quick mark an order as shipped
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="orderId"></param>
|
|
||||||
private async Task QPakCallback(string orderId)
|
|
||||||
{
|
|
||||||
Working = true;
|
|
||||||
var order = OrderList.First(x => x.OrderId == orderId);
|
|
||||||
order.ProcessStatusEnum = "packed";
|
|
||||||
var process = new OrderProcessState
|
|
||||||
{
|
|
||||||
OrderId = order.OrderId,
|
|
||||||
ProcessStatusEnum = "packed"
|
|
||||||
};
|
|
||||||
await OrderProcessRepo.UpdateWarehouseOrderStatus(process);
|
|
||||||
OrderList.Remove(order);
|
|
||||||
Working = false;
|
|
||||||
}
|
|
||||||
/// <summary>
|
|
||||||
/// Set status shipped where status is packed
|
|
||||||
/// </summary>
|
|
||||||
private async Task SetShippedCallback()
|
|
||||||
{
|
|
||||||
Working = true;
|
|
||||||
foreach (var order in OrderList.Where(order => order.ProcessStatusEnum.ToLower() == "packed"))
|
|
||||||
{
|
|
||||||
order.ProcessStatusEnum = "shipped";
|
|
||||||
var process = new OrderProcessState
|
|
||||||
{
|
|
||||||
OrderId = order.OrderId,
|
|
||||||
ProcessStatusEnum = "shipped"
|
|
||||||
};
|
|
||||||
await OrderProcessRepo.UpdateWarehouseOrderStatus(process);
|
|
||||||
}
|
|
||||||
Working = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task<List<WarehouseOrderView>> FetchOrders(string status)
|
|
||||||
{
|
|
||||||
Working = true;
|
|
||||||
var orderList = await OrderProcessRepo.GetWarehouseOrderListByStatus(status.ToLower());
|
|
||||||
if(orderList.Any(x => x.Express))
|
|
||||||
orderList = orderList.OrderByDescending(x => x.Express).ToList();
|
|
||||||
Working = false;
|
|
||||||
return orderList;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Dispose() => Interceptor.DisposeEvent();
|
|
||||||
}
|
|
|
@ -1,129 +0,0 @@
|
||||||
@* Copyright (C) 2022 FCS Frede's Computer Services.
|
|
||||||
// This program is free software: you can redistribute it and/or modify
|
|
||||||
// it under the terms of the GNU Affero General Public License as
|
|
||||||
// published by the Free Software Foundation, either version 3 of the
|
|
||||||
// License, or (at your option) any later version.
|
|
||||||
//
|
|
||||||
// This program is distributed in the hope that it will be useful,
|
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
// GNU Affero General Public License for more details.
|
|
||||||
//
|
|
||||||
// You should have received a copy of the GNU Affero General Public License
|
|
||||||
// along with this program. If not, see [https://www.gnu.org/licenses/agpl-3.0.en.html]
|
|
||||||
*@
|
|
||||||
|
|
||||||
|
|
||||||
@using Microsoft.AspNetCore.Authorization
|
|
||||||
@using Wonky.Client.Components
|
|
||||||
@attribute [Authorize(Roles = "Admin,Office,Warehouse")]
|
|
||||||
|
|
||||||
@page "/warehouse/orders/process/{OrderId}"
|
|
||||||
|
|
||||||
@if (!string.IsNullOrWhiteSpace(Order.OrderDate))
|
|
||||||
{
|
|
||||||
<table class="table">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th colspan="4">
|
|
||||||
@if (Order.Express)
|
|
||||||
{
|
|
||||||
<h2 class="text-center fw-bold">HASTE ORDRE</h2>
|
|
||||||
}
|
|
||||||
<h2 class="text-center">@Order.Company.Name</h2>
|
|
||||||
</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
<tr>
|
|
||||||
<th scope="row">Konto</th>
|
|
||||||
<td>@Order.Company.Account</td>
|
|
||||||
<th scope="row">Telefon</th>
|
|
||||||
<td>@Order.Company.Phone</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th scope="row">Kunde</th>
|
|
||||||
<td>@Order.Company.Name</td>
|
|
||||||
<th scope="row">Lev.Navn</th>
|
|
||||||
<td>@Order.DlvName</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th scope="row">Adresse</th>
|
|
||||||
<td>@Order.Company.Address1</td>
|
|
||||||
<th scope="row">Lev.Adresse</th>
|
|
||||||
<td>@Order.DlvAddress1</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th scope="row">Adresse</th>
|
|
||||||
<td>@Order.Company.Address2</td>
|
|
||||||
<th scope="row">Lev.Adresse</th>
|
|
||||||
<td>@Order.DlvAddress2</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th scope="row">Postnr By</th>
|
|
||||||
<td>@Order.Company.ZipCode @Order.Company.City</td>
|
|
||||||
<th scope="row">Lev.Postnr By</th>
|
|
||||||
<td>@Order.DlvZipCity</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
<table class="table table-striped">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th scope="col">Placering</th>
|
|
||||||
<th scope="col">Antal</th>
|
|
||||||
<th scope="col">Varenr</th>
|
|
||||||
<th scope="col">Beskrivelse</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
@foreach (var line in Order.Lines)
|
|
||||||
{
|
|
||||||
<tr>
|
|
||||||
<td class="fw-bold">@line.Location</td>
|
|
||||||
<td>@line.Quantity</td>
|
|
||||||
<td>@line.Sku</td>
|
|
||||||
<td>
|
|
||||||
<div class="form-check">
|
|
||||||
<input class="form-check-input" type="checkbox" id="@line.LineNumber"/>
|
|
||||||
<label class="form-check-label" for="@line.LineNumber">@line.Description</label>
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
}
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
@if (!string.IsNullOrWhiteSpace(Order.OfficeNote))
|
|
||||||
{
|
|
||||||
<div class="alert bg-light border-dark border-2">
|
|
||||||
<h3 class="text-center">@Order.OfficeNote</h3>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-md-3">
|
|
||||||
<a class="btn btn-outline-success text-nowrap" href="/warehouse/orders/none">Ubehandlet</a>
|
|
||||||
</div>
|
|
||||||
<div class="col-md-3">
|
|
||||||
</div>
|
|
||||||
<div class="col-md-4">
|
|
||||||
@if (Order.ProcessStatusEnum.ToLower() is "none" or "printed")
|
|
||||||
{
|
|
||||||
<button class="btn btn-lg btn-warning text-nowrap" type="button" @onclick="@SetProcessStatusPicked" disabled="@Working">Sæt status plukket</button>
|
|
||||||
}
|
|
||||||
@if (Order.ProcessStatusEnum.ToLower() == "picked")
|
|
||||||
{
|
|
||||||
<button class="btn btn-lg btn-danger text-nowrap" type="button" @onclick="@SetProcessStatusPacked" disabled="@Working">Sæt status pakket</button>
|
|
||||||
}
|
|
||||||
@if (Order.ProcessStatusEnum.ToLower() == "packed")
|
|
||||||
{
|
|
||||||
<button class="btn btn-lg btn-primary text-nowrap" type="button" @onclick="@SetProcessStatusShipped" disabled="@Working">Sæt status afsendt</button>
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@if (Working)
|
|
||||||
{
|
|
||||||
<WorkingThreeDots/>
|
|
||||||
}
|
|
|
@ -1,103 +0,0 @@
|
||||||
// Copyright (C) 2022 FCS Frede's Computer Services.
|
|
||||||
// This program is free software: you can redistribute it and/or modify
|
|
||||||
// it under the terms of the GNU Affero General Public License as
|
|
||||||
// published by the Free Software Foundation, either version 3 of the
|
|
||||||
// License, or (at your option) any later version.
|
|
||||||
//
|
|
||||||
// This program is distributed in the hope that it will be useful,
|
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
// GNU Affero General Public License for more details.
|
|
||||||
//
|
|
||||||
// You should have received a copy of the GNU Affero General Public License
|
|
||||||
// along with this program. If not, see [https://www.gnu.org/licenses/agpl-3.0.en.html]
|
|
||||||
//
|
|
||||||
|
|
||||||
|
|
||||||
using System.Text.Json;
|
|
||||||
using Blazored.Toast.Services;
|
|
||||||
using Microsoft.AspNetCore.Components;
|
|
||||||
using Wonky.Client.HttpInterceptors;
|
|
||||||
using Wonky.Client.HttpRepository;
|
|
||||||
using Wonky.Entity.DTO;
|
|
||||||
using Wonky.Entity.Views;
|
|
||||||
#pragma warning disable CS8618
|
|
||||||
|
|
||||||
namespace Wonky.Client.Pages;
|
|
||||||
|
|
||||||
public partial class WarehouseOrderViewPage : IDisposable
|
|
||||||
{
|
|
||||||
// #############################################################
|
|
||||||
[Inject] public HttpInterceptorService Interceptor { get; set; }
|
|
||||||
[Inject] public IOrderProcessRepository OrderProcessRepo { get; set; }
|
|
||||||
[Inject] public NavigationManager Navigator { get; set; }
|
|
||||||
[Inject] public IToastService Toast { get; set; }
|
|
||||||
[Inject] public ILogger<WarehouseOrderViewPage> Logger { get; set; }
|
|
||||||
|
|
||||||
// #############################################################
|
|
||||||
[Parameter] public string OrderId { get; set; } = "";
|
|
||||||
|
|
||||||
// #############################################################
|
|
||||||
private WarehouseOrderView Order { get; set; } = new();
|
|
||||||
private bool Working { get; set; } = true;
|
|
||||||
|
|
||||||
|
|
||||||
protected override async Task OnParametersSetAsync()
|
|
||||||
{
|
|
||||||
Interceptor.RegisterEvent();
|
|
||||||
Interceptor.RegisterBeforeSendEvent();
|
|
||||||
if (!string.IsNullOrWhiteSpace(OrderId))
|
|
||||||
Order = await OrderProcessRepo.GetWarehouseOrder(OrderId);
|
|
||||||
|
|
||||||
Logger.LogDebug("Warehouse OrderView =>\n{}", JsonSerializer.Serialize(Order));
|
|
||||||
Working = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task SetProcessStatusPicked()
|
|
||||||
{
|
|
||||||
if (Working)
|
|
||||||
return;
|
|
||||||
|
|
||||||
Working = true;
|
|
||||||
var process = new OrderProcessState
|
|
||||||
{
|
|
||||||
OrderId = Order.OrderId,
|
|
||||||
ProcessStatusEnum = "picked"
|
|
||||||
};
|
|
||||||
await OrderProcessRepo.UpdateWarehouseOrderStatus(process);
|
|
||||||
Navigator.NavigateTo("/warehouse/orders/none");
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task SetProcessStatusPacked()
|
|
||||||
{
|
|
||||||
if (Working)
|
|
||||||
return;
|
|
||||||
Working = true;
|
|
||||||
var process = new OrderProcessState
|
|
||||||
{
|
|
||||||
OrderId = Order.OrderId,
|
|
||||||
ProcessStatusEnum = "packed"
|
|
||||||
};
|
|
||||||
await OrderProcessRepo.UpdateWarehouseOrderStatus(process);
|
|
||||||
Navigator.NavigateTo("/warehouse/orders/picked");
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task SetProcessStatusShipped()
|
|
||||||
{
|
|
||||||
if (Working)
|
|
||||||
return;
|
|
||||||
Working = true;
|
|
||||||
var process = new OrderProcessState
|
|
||||||
{
|
|
||||||
OrderId = Order.OrderId,
|
|
||||||
ProcessStatusEnum = "shipped"
|
|
||||||
};
|
|
||||||
await OrderProcessRepo.UpdateWarehouseOrderStatus(process);
|
|
||||||
Navigator.NavigateTo("/warehouse/orders/none");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Dispose()
|
|
||||||
{
|
|
||||||
Interceptor.DisposeEvent();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -15,6 +15,7 @@
|
||||||
|
|
||||||
using System.Net.Http.Headers;
|
using System.Net.Http.Headers;
|
||||||
using System.Security.Claims;
|
using System.Security.Claims;
|
||||||
|
using System.Text.Json;
|
||||||
using Blazored.LocalStorage;
|
using Blazored.LocalStorage;
|
||||||
using Microsoft.AspNetCore.Components.Authorization;
|
using Microsoft.AspNetCore.Components.Authorization;
|
||||||
using Wonky.Client.Local.Services;
|
using Wonky.Client.Local.Services;
|
||||||
|
@ -26,15 +27,16 @@ namespace Wonky.Client.Shared;
|
||||||
public class AuthStateProvider : AuthenticationStateProvider
|
public class AuthStateProvider : AuthenticationStateProvider
|
||||||
{
|
{
|
||||||
private readonly HttpClient _client;
|
private readonly HttpClient _client;
|
||||||
// private readonly ILocalStorageService _storage;
|
|
||||||
private readonly AuthenticationState _anonymous;
|
private readonly AuthenticationState _anonymous;
|
||||||
private readonly IUserInfoService _infoService;
|
private readonly IUserInfoService _infoService;
|
||||||
|
|
||||||
|
private readonly ILogger<AuthStateProvider> _logger;
|
||||||
|
|
||||||
public AuthStateProvider(HttpClient client, IUserInfoService infoService)
|
public AuthStateProvider(HttpClient client, IUserInfoService infoService, ILogger<AuthStateProvider> logger)
|
||||||
{
|
{
|
||||||
_client = client;
|
_client = client;
|
||||||
_infoService = infoService;
|
_infoService = infoService;
|
||||||
|
_logger = logger;
|
||||||
_anonymous = new AuthenticationState(new ClaimsPrincipal(new ClaimsIdentity()));
|
_anonymous = new AuthenticationState(new ClaimsPrincipal(new ClaimsIdentity()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -42,19 +44,26 @@ public class AuthStateProvider : AuthenticationStateProvider
|
||||||
public override async Task<AuthenticationState> GetAuthenticationStateAsync()
|
public override async Task<AuthenticationState> GetAuthenticationStateAsync()
|
||||||
{
|
{
|
||||||
var token = await _infoService.GetAccessToken();
|
var token = await _infoService.GetAccessToken();
|
||||||
|
_logger.LogDebug("accessToken {}", token);
|
||||||
if (string.IsNullOrEmpty(token))
|
if (string.IsNullOrEmpty(token))
|
||||||
{
|
{
|
||||||
return _anonymous;
|
return _anonymous;
|
||||||
}
|
}
|
||||||
|
|
||||||
var userInfo = await _infoService.GetUserInfo();
|
var userInfo = await _infoService.GetUserInfo();
|
||||||
if (string.IsNullOrWhiteSpace(userInfo.UserId))
|
_logger.LogDebug("userInfo {}", JsonSerializer.Serialize(userInfo));
|
||||||
|
|
||||||
|
if (userInfo == null || string.IsNullOrWhiteSpace(userInfo.FirstName))
|
||||||
{
|
{
|
||||||
|
NotifyUserLogout();
|
||||||
return _anonymous;
|
return _anonymous;
|
||||||
}
|
}
|
||||||
|
_logger.LogDebug("userInfo.FirstName {}", userInfo.FirstName);
|
||||||
_client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("bearer", token);
|
_client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("bearer", token);
|
||||||
|
|
||||||
var exp = await _infoService.GetExpiration();
|
var exp = await _infoService.GetExpiration();
|
||||||
|
_logger.LogDebug("expiration {}", exp);
|
||||||
|
|
||||||
var claims = new List<Claim>
|
var claims = new List<Claim>
|
||||||
{
|
{
|
||||||
new(ClaimTypes.Name, $"{userInfo.FirstName} {userInfo.LastName}"),
|
new(ClaimTypes.Name, $"{userInfo.FirstName} {userInfo.LastName}"),
|
||||||
|
@ -65,14 +74,15 @@ public class AuthStateProvider : AuthenticationStateProvider
|
||||||
};
|
};
|
||||||
claims.AddRange(
|
claims.AddRange(
|
||||||
from role in userInfo.AssignedRoles
|
from role in userInfo.AssignedRoles
|
||||||
where role.Assigned select new Claim(ClaimTypes.Role, role.Name)
|
where role.Assigned
|
||||||
);
|
select new Claim(ClaimTypes.Role, role.Name)
|
||||||
claims.Add( new Claim(ClaimTypes.Role, userInfo.CountryCode));
|
);
|
||||||
|
|
||||||
// return the authState for the user
|
// return the authState for the user
|
||||||
return new AuthenticationState(
|
return new AuthenticationState(
|
||||||
new ClaimsPrincipal(
|
new ClaimsPrincipal(
|
||||||
new ClaimsIdentity(claims, "token")));
|
new ClaimsIdentity(claims, "token"))
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -80,12 +90,18 @@ public class AuthStateProvider : AuthenticationStateProvider
|
||||||
{
|
{
|
||||||
if (string.IsNullOrEmpty(token))
|
if (string.IsNullOrEmpty(token))
|
||||||
{
|
{
|
||||||
|
NotifyUserLogout();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
_client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("bearer", token);
|
_client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("bearer", token);
|
||||||
|
|
||||||
var userInfo = await _infoService.GetUserInfo();
|
var userInfo = await _infoService.GetUserInfo();
|
||||||
|
if (string.IsNullOrWhiteSpace(userInfo.UserId))
|
||||||
|
{
|
||||||
|
NotifyUserLogout();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
var exp = await _infoService.GetExpiration();
|
var exp = await _infoService.GetExpiration();
|
||||||
|
|
||||||
var claims = new List<Claim>
|
var claims = new List<Claim>
|
||||||
|
@ -98,12 +114,16 @@ public class AuthStateProvider : AuthenticationStateProvider
|
||||||
};
|
};
|
||||||
claims.AddRange(
|
claims.AddRange(
|
||||||
from role in userInfo.AssignedRoles
|
from role in userInfo.AssignedRoles
|
||||||
where role.Assigned select new Claim(ClaimTypes.Role, role.Name));
|
where role.Assigned
|
||||||
|
select new Claim(ClaimTypes.Role, role.Name)
|
||||||
|
);
|
||||||
|
|
||||||
var authState = Task.FromResult(
|
var authState = Task.FromResult(
|
||||||
new AuthenticationState(
|
new AuthenticationState(
|
||||||
new ClaimsPrincipal(
|
new ClaimsPrincipal(
|
||||||
new ClaimsIdentity(claims, "token"))));
|
new ClaimsIdentity(claims, "token"))
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
NotifyAuthenticationStateChanged(authState);
|
NotifyAuthenticationStateChanged(authState);
|
||||||
}
|
}
|
||||||
|
|
|
@ -66,11 +66,13 @@
|
||||||
<i class="bi-building pe-2" style="font-size:1.3em;" aria-hidden="true"></i> Kunder SE
|
<i class="bi-building pe-2" style="font-size:1.3em;" aria-hidden="true"></i> Kunder SE
|
||||||
</NavLink>
|
</NavLink>
|
||||||
</div>
|
</div>
|
||||||
|
@*
|
||||||
<div class="nav-item px-3">
|
<div class="nav-item px-3">
|
||||||
<NavLink class="nav-link ps-2" href="/warehouse/orders/none">
|
<NavLink class="nav-link ps-2" href="/warehouse/orders/none">
|
||||||
<i class="bi-box pe-2" style="font-size:1.3em;" aria-hidden="true"></i> Forsendelse
|
<i class="bi-box pe-2" style="font-size:1.3em;" aria-hidden="true"></i> Forsendelse
|
||||||
</NavLink>
|
</NavLink>
|
||||||
</div>
|
</div>
|
||||||
|
*@
|
||||||
</AuthorizeView>
|
</AuthorizeView>
|
||||||
|
|
||||||
<AuthorizeView Roles="Advisor">
|
<AuthorizeView Roles="Advisor">
|
||||||
|
|
|
@ -1,15 +1,15 @@
|
||||||
{
|
{
|
||||||
"appInfo": {
|
"appInfo": {
|
||||||
"name": "Wonky Online",
|
"name": "Wonky Online",
|
||||||
"version": "153.0",
|
"version": "157.1",
|
||||||
"rc": true,
|
"rc": true,
|
||||||
"sandBox": false,
|
"sandBox": false,
|
||||||
"image": "grumpy-coder.png"
|
"image": "grumpy-coder.png"
|
||||||
},
|
},
|
||||||
"Logging": {
|
"Logging": {
|
||||||
"LogLevel": {
|
"LogLevel": {
|
||||||
"Default": "Information",
|
"Default": "Debug",
|
||||||
"System": "Information",
|
"System": "Debug",
|
||||||
"Microsoft": "Information"
|
"Microsoft": "Information"
|
||||||
},
|
},
|
||||||
"Debug": {
|
"Debug": {
|
||||||
|
@ -19,7 +19,7 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"apiConfig": {
|
"apiConfig": {
|
||||||
"baseUrl": "https://zeta.innotec.dk",
|
"baseUrl": "https://dev.innotec.dk",
|
||||||
"catalog": "api/v2/catalog/country",
|
"catalog": "api/v2/catalog/country",
|
||||||
"crmCustomers": "api/v2/crm/companies",
|
"crmCustomers": "api/v2/crm/companies",
|
||||||
"crmInventoryExt": "history/inventory",
|
"crmInventoryExt": "history/inventory",
|
||||||
|
|
|
@ -16,6 +16,14 @@ body {
|
||||||
.workDate {
|
.workDate {
|
||||||
font-variant: small-caps;
|
font-variant: small-caps;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.action-link-element {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
.i-larger {
|
||||||
|
font-size: 1.3rem;
|
||||||
|
}
|
||||||
|
|
||||||
.btn.btn-edit {
|
.btn.btn-edit {
|
||||||
color: #030303;
|
color: #030303;
|
||||||
background-color: #a2a2ec;
|
background-color: #a2a2ec;
|
||||||
|
@ -219,13 +227,6 @@ a, .btn-link {
|
||||||
}
|
}
|
||||||
/* end led elements */
|
/* end led elements */
|
||||||
|
|
||||||
.action-link-element {
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
.i-larger {
|
|
||||||
font-size: 1.3rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.footer {
|
.footer {
|
||||||
border-top: 2px solid orange;
|
border-top: 2px solid orange;
|
||||||
position: relative;
|
position: relative;
|
||||||
|
|
|
@ -17,11 +17,17 @@ namespace Wonky.Entity.Views;
|
||||||
|
|
||||||
public class ProductInventoryItemView
|
public class ProductInventoryItemView
|
||||||
{
|
{
|
||||||
|
public virtual bool AgedProduct()
|
||||||
|
{
|
||||||
|
return DateTime.Parse(LastInvoiceDate) < DateTime.Now.AddMonths(-12);
|
||||||
|
}
|
||||||
public virtual bool Check { get; set; }
|
public virtual bool Check { get; set; }
|
||||||
public string Description { get; set; } = "";
|
public string Description { get; set; } = "";
|
||||||
public bool Discontinued { get; set; }
|
public bool Discontinued { get; set; }
|
||||||
public string PictureLink { get; set; } = "";
|
public string PictureLink { get; set; } = "";
|
||||||
public int Quantity { get; set; }
|
public int Quantity { get; set; }
|
||||||
|
public string LastInvoiceDate { get; set; } = "";
|
||||||
public string Sku { get; set; } = "";
|
public string Sku { get; set; } = "";
|
||||||
public string VendorItemNo { get; set; } = "";
|
public string VendorItemNo { get; set; } = "";
|
||||||
|
|
||||||
}
|
}
|
Loading…
Reference in a new issue