Merge branch 'dev-v6'

This commit is contained in:
Frede Hundewadt 2023-02-01 09:49:59 +01:00
commit 11b43ab03c
269 changed files with 6132 additions and 3766 deletions

View file

@ -1,6 +1,13 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:Boolean x:Key="/Default/UserDictionary/Words/=Affero/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Bestilling/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Bes_00F8g/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Danmark/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=fejl/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=kontrolleres/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Norge/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=opst_00E5et/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Sverige/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Tilbud/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Venligst/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Virk/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>

View file

@ -8,7 +8,7 @@
@code {
[Inject] public UserProfileService ProfileService { get; set; }
[Inject] private UserProfileService ProfileService { get; set; }
private int KmMorning { get; set; }
private UserPref Prefs { get; set; } = new();

View file

@ -18,7 +18,7 @@
@if (ActivityList.Any())
{
<table class="table table-bordered d-print-table table-striped">
<table class="table table-sm table-bordered d-print-table table-striped">
<thead>
<tr class="bg-dark text-white opacity-75 border-bottom">
<th scope="col">Kunde</th>
@ -38,7 +38,7 @@
@foreach (var activity in ActivityList)
{
<tr>
<td class="align-middle"><a class="btn btn-outline-info text-black d-block" href="/companies/@activity.Company.CompanyId/orders/@activity.ActivityId">@activity.Company.Name</a></td>
<td class="align-middle"><a href="/advisor/customers/@activity.Company.CompanyId/orders/@activity.ActivityId">@activity.Company.Name</a></td>
<td class="align-middle">@activity.Company.City</td>
<td class="align-middle">@activity.Demo</td>
<td class="align-middle">@activity.Sales</td>

View file

@ -13,12 +13,14 @@
// along with this program. If not, see [https://www.gnu.org/licenses/agpl-3.0.en.html]
//
using Wonky.Entity.Views;
using Microsoft.AspNetCore.Components;
using Wonky.Entity.Views;
namespace Wonky.Client.Components;
public partial class ReportActivityLedgerComponent
public partial class AdvisorActivityListComponent
{
[Parameter] public ReportData ReportData { get; set; } = new();
[Parameter] public List<ReportItemView> ActivityList { get; set; } = new();
[Inject] private NavigationManager Navigator { get; set; }
}

View file

@ -42,7 +42,7 @@
<td class="align-middle">
@if (!string.IsNullOrWhiteSpace(company.Note))
{
<i class="bi-exclamation-diamond-fill text-danger" style="font-size: 2rem;"></i>
<i class="bi-exclamation-diamond" style="font-size: 1.3rem;"></i>
}
</td>
<td class="align-middle">
@ -58,7 +58,7 @@
@company.City
</td>
<td class="align-middle">
<ActivityButton CompanyId="@company.CompanyId" ActionLink="/companies/$ID$/activities/new"
<ActivityButton CompanyId="@company.CompanyId" ActionLink="/advisor/customers/$ID$/activities/new"
ButtonText="Besøg" ButtonType="primary" Enabled="@company.ValidVat"/>
</td>
</tr>

View file

@ -27,13 +27,13 @@ using Wonky.Entity.Views;
namespace Wonky.Client.Components
{
public partial class AdvisorCompanyTableComponent
public partial class AdvisorCustomerListComponent
{
[Parameter] public List<CompanyDto> CompanyList { get; set; } = new();
[Parameter] public EventCallback<string> OnDelete { get; set; }
[Parameter] public EventCallback<string> OnSelect { get; set; }
[Inject] public NavigationManager Navigator { get; set; }
[Inject] public IJSRuntime Js { get; set; }
[Inject] private NavigationManager Navigator { get; set; }
[Inject] private IJSRuntime Js { get; set; }
private Lazy<IJSObjectReference> BsTooltip = new();
@ -43,7 +43,7 @@ namespace Wonky.Client.Components
private void ViewCustomer(string companyId)
{
Navigator.NavigateTo($"/companies/{companyId}");
Navigator.NavigateTo($"/advisor/customers/{companyId}");
}
private void CallInformationModal(string info)

View file

@ -0,0 +1,93 @@
@using Wonky.Entity.Views
@using Wonky.Entity.DTO
@*
// 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]
//
*@
<table class="table table-sm table-bordered table-striped">
<thead>
<tr class="bg-dark text-white opacity-75 border-bottom">
<th></th>
<th class="text-center" colspan="2" scope="col">Dagens Demo @(ReportData.NewDemoCount + ReportData.RecallDemoCount)</th>
<th class="text-center border-end" colspan="2" scope="col">Dagens Resultat</th>
<th class="text-center" colspan="4" scope="col">Måneds Resultat</th>
</tr>
</thead>
<tbody>
<tr class="bg-dark bg-opacity-50 border-bottom">
<td></td>
<th class="text-end text-white" scope="col">Besøg</th>
<th class="text-end text-white" scope="col">Demo</th>
<th class="text-end text-white" scope="col">Salg</th>
<th class="text-end text-white border-end" scope="col">Beløb</th>
<th class="text-end text-white" scope="col">Besøg</th>
<th class="text-end text-white" scope="col">Demo</th>
<th class="text-end text-white" scope="col">Salg</th>
<th class="text-end text-white" scope="col">Beløb</th>
</tr>
<tr>
<th scope="row">N</th>
<td class="text-end">@ReportData.NewVisitCount</td>
<td class="text-end">@ReportData.NewDemoCount</td>
<td class="text-end">@ReportData.NewSaleCount</td>
<td class="text-end border-end">@ReportData.NewTurnover</td>
<td class="text-end">@ReportData.NewVisitCountMonth</td>
<td class="text-end">@ReportData.NewDemoCountMonth</td>
<td class="text-end">@ReportData.NewSaleCountMonth</td>
<td class="text-end">@ReportData.NewTurnoverMonth</td>
</tr>
<tr>
<th scope="row">R</th>
<td class="text-end">@ReportData.RecallVisitCount</td>
<td class="text-end">@ReportData.RecallDemoCount</td>
<td class="text-end">@ReportData.RecallSaleCount</td>
<td class="text-end border-end">@ReportData.RecallTurnover</td>
<td class="text-end">@ReportData.RecallVisitCountMonth</td>
<td class="text-end">@ReportData.RecallDemoCountMonth</td>
<td class="text-end">@ReportData.RecallSaleCountMonth</td>
<td class="text-end">@ReportData.RecallTurnoverMonth</td>
</tr>
<tr>
<th scope="row">SAS</th>
<td class="bg-light"></td>
<td class="bg-light"></td>
<td class="text-end">@ReportData.SasCount</td>
<td class="text-end border-end">@ReportData.SasTurnover</td>
<td class="bg-light"></td>
<td class="bg-light"></td>
<td class="text-end">@ReportData.SasCountMonth</td>
<td class="text-end">@ReportData.SasTurnoverMonth</td>
</tr>
<tr>
<th scope="row">TOTAL</th>
<td class="text-end">@ReportData.TotalVisitCount</td>
<td class="text-end">@ReportData.TotalDemoCount</td>
<td class="text-end">@ReportData.TotalSaleCount</td>
<td class="text-end border-end">@ReportData.TotalTurnover</td>
<td class="text-end">@ReportData.TotalVisitCountMonth</td>
<td class="text-end">@ReportData.TotalDemoCountMonth</td>
<td class="text-end">@ReportData.TotalSaleCountMonth</td>
<td class="text-end">@ReportData.TotalTurnoverMonth</td>
</tr>
</tbody>
</table>
@code{
[Parameter]
public ReportFiguresDto ReportData { get; set; } = new();
}

View file

@ -22,8 +22,8 @@ namespace Wonky.Client.Components;
public partial class CatalogGroupComponent
{
[Inject] public ILocalStorageService Storage { get; set; }
[Inject] public UserProfileService ProfileService { get; set; }
[Inject] private ILocalStorageService Storage { get; set; }
[Inject] private UserProfileService ProfileService { get; set; }
[Parameter] public EventCallback<string> OnChanged { get; set; }
private Dictionary<string, string> Items { get; set; } = new();
private UserPref Prefs = new();

View file

@ -21,12 +21,8 @@ using Wonky.Entity.Views;
namespace Wonky.Client.Components;
public partial class CatalogTableComponent
public partial class CatalogListComponent
{
[Parameter] public List<SalesItemView> ItemList { get; set; } = new();
[Inject] public IToastService ToastService { get; set; }
private void AddToDraft()
{
ToastService.ShowInfo("TODO: læg til ordre kladde");
}
[Inject] private IToastService ToastService { get; set; }
}

View file

@ -21,7 +21,7 @@ using Wonky.Entity.Views;
namespace Wonky.Client.Components;
public partial class CatalogTablePrintComponent
public partial class CatalogPrintComponent
{
[Parameter] public List<SalesItemView> ItemList { get; set; } = new();
[Parameter] public string CountryName { get; set; } = "";

View file

@ -17,7 +17,7 @@
<select class="form-select bg-warning text-bg-warning" @bind-value="@SearchCol" @bind-value:event="oninput" @onchange="OnSelectChanged">
<option value="-1" selected disabled>SØGNING</option>
<option value="name">Søg Navn</option>
<option value="sku">Søg Nummer</option>
<option value="shortName">Søg Forkort.</option>
<option value="name">Navn</option>
<option value="sku">Nummer</option>
<option value="shortName">Forkort.</option>
</select>

View file

@ -24,7 +24,7 @@ public partial class CatalogSearchComponent : IDisposable
/// <summary>
/// User preference service
/// </summary>
[Inject] public UserProfileService ProfileService { get; set; }
[Inject] private UserProfileService ProfileService { get; set; }
/// <summary>
/// OnChanged event callback

View file

@ -17,6 +17,6 @@
<select class="form-select bg-success text-bg-success" @bind-value="@SortCol" @bind-value:event="oninput" @onchange="OnSelectChanged">
<option value="-1" selected disabled>SORTERING</option>
<option value="name">Navn sort</option>
<option value="sku">Varenr sort</option>
<option value="name">Navn</option>
<option value="sku">Varenr</option>
</select>

View file

@ -24,7 +24,7 @@ public partial class CatalogSortComponent : IDisposable
/// <summary>
/// User preference service
/// </summary>
[Inject] public UserProfileService ProfileService { get; set; }
[Inject] private UserProfileService ProfileService { get; set; }
/// <summary>
/// OnChanged callback function

View file

@ -1,4 +0,0 @@
.color-code {
max-width: 40px;
}

View file

@ -19,7 +19,7 @@
<div class="row">
@if (ProductList.Any())
@if (Inventory.Any())
{
<div class="list-group mt-2">
<div class="list-group-item bg-dark text-white">
@ -31,12 +31,20 @@
<div class="col-sm-1"></div>
</div>
</div>
@foreach (var product in ProductList)
@foreach (var product in Inventory)
{
<div class="list-group-item">
<div class="row align-items-center">
<div class="col-sm-4">
@product.Description <span class="fw-bold">@(product.Discontinued ? "(UDGÅET)" : "")</span>
<div class="position-relative">
@product.Description
@if (product.Discontinued)
{
<span class="position-absolute top-0 start-100 translate-middle badge rounded-pill bg-danger">Udgået</span>
<span class="visually-hidden">Produktet er udgået</span>
}
</div>
@* @product.Description <span class="fw-bold text-sm-start">@(product.Discontinued ? "(UDGÅET)" : "")</span> *@
</div>
<div class="col-sm-3">
@product.Sku
@ -66,8 +74,6 @@
</div>
}
</div>
<InventoryReorderModal OnSelected="@OnSelectedItem" CompanyId="@CompanyId" SalesItem="@SalesItem" @ref="ReorderModal"/>
}
else
{

View file

@ -25,20 +25,15 @@ using Wonky.Entity.Views;
namespace Wonky.Client.Components;
public partial class CustomerProductTableComponent
public partial class CustomerInventoryListComponent
{
[CascadingParameter] public DraftStateProvider DraftStateProvider { get; set; } = new();
[Parameter] public List<ProductInventoryView> ProductList { get; set; } = new();
[Inject] private ILocalStorageService Storage { get; set; }
// Parameters
[Parameter] public List<ProductInventoryView> Inventory { get; set; } = new();
[Parameter] public string CompanyId { get; set; } = "";
[Inject] public ICatalogHttpRepository Catalog { get; set; }
[Inject] public ILocalStorageService Storage { get; set; }
[Parameter] public EventCallback<string> OnReorderSelected { get; set; }
// private variables
private SalesItemView SalesItem { get; set; } = new();
private string Price { get; set; } = "0";
private string Quantity { get; set; } = "1";
private string Sku { get; set; } = "";
private InventoryReorderModal ReorderModal { get; set; } = new();
private SelectedSku Item { get; set; } = new();
private bool Descending { get; set; }
private void SortProducts(PSort column)
@ -49,57 +44,47 @@ public partial class CustomerProductTableComponent
case PSort.Desc:
if (Descending)
{
ProductList = ProductList.OrderByDescending(x => x.Description).ToList();
Inventory = Inventory.OrderByDescending(x => x.Description).ToList();
break;
}
ProductList = ProductList.OrderBy(x => x.Description).ToList();
Inventory = Inventory.OrderBy(x => x.Description).ToList();
break;
case PSort.Sku:
if (Descending)
{
ProductList = ProductList.OrderByDescending(x => x.Sku).ToList();
Inventory = Inventory.OrderByDescending(x => x.Sku).ToList();
break;
}
ProductList = ProductList.OrderBy(x => x.Sku).ToList();
Inventory = Inventory.OrderBy(x => x.Sku).ToList();
break;
case PSort.Qty:
if (Descending)
{
ProductList = ProductList.OrderByDescending(x => x.Quantity).ToList();
Inventory = Inventory.OrderByDescending(x => x.Quantity).ToList();
break;
}
ProductList = ProductList.OrderBy(x => x.Quantity).ToList();
Inventory = Inventory.OrderBy(x => x.Quantity).ToList();
break;
case PSort.None:
break;
case PSort.Abbr:
break;
default:
ProductList = ProductList.OrderByDescending(x => x.Quantity).ToList();
Inventory = Inventory.OrderByDescending(x => x.Quantity).ToList();
break;
}
}
private async Task ProductCheck(string sku)
{
var x = ProductList.First(x => x.Sku == sku);
x.Check = !x.Check;
await Storage.SetItemAsync($"{CompanyId}-products", ProductList);
}
private async Task CallShowReorderModal(string sku)
{
// fetch item from http repo
SalesItem = await Catalog.GetSalesItemSku(sku);
ReorderModal.Show();
await ProductCheck(sku);
await OnReorderSelected.InvokeAsync(sku);
}
private async Task OnSelectedItem(DraftItem draftItem)
private async Task ProductCheck(string sku)
{
// add item to order draft
DraftStateProvider.Draft.DraftType = "order";
DraftStateProvider.Draft.Items.Add(draftItem);
// set item checked
await ProductCheck(draftItem.Item.Sku);
await DraftStateProvider.SaveChangesAsync();
var x = Inventory.First(x => x.Sku == sku);
x.Check = !x.Check;
await Storage.SetItemAsync($"{CompanyId}-products", Inventory);
}
}

View file

@ -37,7 +37,7 @@
{
<div class="row">
<div class="col-md-1"></div>
<div class="col-md-1"><i class="bi-pencil"></i></div>
<div class="col-md-1"><i class="bi-card-text"></i></div>
<div class="col-md-10 fw-bold">@invoice.OrderNote</div>
</div>
}
@ -48,5 +48,4 @@
else
{
<div>Ingen data</div>
}
<InvoiceViewModal CompanyId="@CompanyId" InvoiceId="@InvoiceId" @ref="InvoiceView" />
}

View file

@ -0,0 +1,17 @@
using Microsoft.AspNetCore.Components;
using Wonky.Client.Shared;
using Wonky.Entity.Views;
namespace Wonky.Client.Components;
public partial class CustomerInvoiceListComponent
{
[Parameter] public string CompanyId { get; set; } = "";
[Parameter] public List<InvoiceListItemView> InvoiceList { get; set; } = new();
[Parameter] public EventCallback<string> OnShowInvoice { get; set; }
private async Task ShowInvoice(string invoiceId)
{
await OnShowInvoice.InvokeAsync(invoiceId);
}
}

View file

@ -28,7 +28,7 @@ public partial class CustomerProductCheckListComponent
{
[Parameter] public List<ProductInventoryView> ProductList { get; set; } = new();
[Parameter] public string CompanyId { get; set; } = "";
[Inject] public ILocalStorageService Storage { get; set; }
[Inject] private ILocalStorageService Storage { get; set; }
// private variables
private bool Descending { get; set; }

View file

@ -19,7 +19,7 @@ using Wonky.Entity.Views;
namespace Wonky.Client.Components;
public partial class CustomerProductLineTableComponent
public partial class CustomerProductLineListComponent
{
[Parameter] public List<ProductHistoryView> ProductHistory { get; set; } = new();

View file

@ -17,9 +17,9 @@
<select class="form-select bg-warning text-bg-warning" @bind-value="@SearchCol" @bind-value:event="oninput" @onchange="OnSelectionChanged">
<option value="-1" disabled>SØGNING</option>
<option value="name">Søg Navn</option>
<option value="city">Søg By</option>
<option value="zip">Søg Post</option>
<option value="account">Søg Konto</option>
<option value="phone">Søg Tlf.</option>
<option value="name">Navn</option>
<option value="city">Bynavn</option>
<option value="zip">Postnr</option>
<option value="account">Konto</option>
<option value="phone">Telefon</option>
</select>

View file

@ -22,10 +22,10 @@ using Wonky.Client.Services;
namespace Wonky.Client.Components;
public partial class CompanySearchColumnComponent : IDisposable
public partial class CustomerSearchColumnComponent : IDisposable
{
[Inject] public ILocalStorageService Storage { get; set; }
[Inject] public UserProfileService ProfileService { get; set; }
[Inject] private ILocalStorageService Storage { get; set; }
[Inject] private UserProfileService ProfileService { get; set; }
[Parameter] public EventCallback<string> OnChanged { get; set; }
private Dictionary<string, string> Items { get; set; } = new();
private UserPref Prefs { get; set; } = new();

View file

@ -20,12 +20,12 @@ using Timer = System.Timers.Timer;
namespace Wonky.Client.Components
{
public partial class CompanySearchPhraseComponent
public partial class CustomerSearchPhraseComponent
{
private Timer InputTimer { get; set; } = new();
private string SearchTerm { get; set; } = "";
private UserPref Prefs { get; set; } = new ();
[Inject] public UserProfileService ProfileService { get; set; }
[Inject] private UserProfileService ProfileService { get; set; }
[Parameter] public EventCallback<string> OnChanged { get; set; }
protected override async Task OnInitializedAsync()

View file

@ -17,6 +17,6 @@
<select class="form-select bg-success text-bg-success" @bind-value="@SortCol" @bind-value:event="oninput" @onchange="OnSelectionChanged">
<option value="-1" selected disabled>SORTERING</option>
<option value="name">Navne sort.</option>
<option value="city">By sort.</option>
<option value="name">Firma</option>
<option value="city">Bynavn</option>
</select>

View file

@ -21,10 +21,10 @@ using Wonky.Client.Services;
namespace Wonky.Client.Components
{
public partial class CompanySortComponent : IDisposable
public partial class CustomerSortComponent : IDisposable
{
[Inject] public ILocalStorageService Storage { get; set; }
[Inject] public UserProfileService ProfileService { get; set; }
[Inject] private ILocalStorageService Storage { get; set; }
[Inject] private UserProfileService ProfileService { get; set; }
[Parameter] public EventCallback<string> OnChanged { get; set; }
private Dictionary<string, string> Items { get; set; } = new();
private UserPref Prefs = new();

View file

@ -0,0 +1,75 @@
@*
// 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]
//
*@
<div class="list-group">
<div class="list-group-item">
<div class="row">
<div class="col">
<h4>Dato</h4>
</div>
<div class="col">
<h4>Demo</h4>
</div>
<div class="col">
<h4>Salg</h4>
</div>
<div class="col">
<h4>Ordre Note</h4>
</div>
<div class="col">
<h4>Ordre Note</h4>
</div>
</div>
</div>
@if (Activities.Any())
{
@foreach (var activity in Activities)
{
<div class="list-group-item list-group-item-action" style="cursor: pointer" @onclick="() => ShowVisitOverlay(activity.ActivityId)">
<div class="row">
<div class="col">
@activity.OrderDate
</div>
<div class="col">
@activity.Demo
</div>
<div class="col">
@activity.Sales
</div>
<div class="col">
@activity.OfficeNote
</div>
<div class="col">
@activity.CrmNote
</div>
</div>
</div>
}
}
else
{
<div class="list-group-item">
<div class="row">
<div class="col">
Ingen data
</div>
</div>
</div>
}
</div>
<CustomerActivityViewModalOverlay ReportItem="Activity" @ref="ActivityViewOverlay"/>

View file

@ -0,0 +1,41 @@
// 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.Globalization;
using System.Runtime.InteropServices;
using Blazored.LocalStorage;
using Microsoft.AspNetCore.Components;
using Wonky.Client.HttpInterfaces;
using Wonky.Client.Models;
using Wonky.Client.Shared;
using Wonky.Entity.DTO;
using Wonky.Entity.Views;
namespace Wonky.Client.Components;
public partial class CustomerVisitListComponent
{
[Parameter] public List<ReportItemView> Activities { get; set; } = new();
private CustomerActivityViewModalOverlay ActivityViewOverlay { get; set; } = new();
private ReportItemView Activity { get; set; } = new();
private void ShowVisitOverlay(string activityId)
{
Activity = Activities.First(x => x.ActivityId == activityId);
ActivityViewOverlay.Show();
}
}

View file

@ -0,0 +1,47 @@
<h3>Sælger</h3>
<table class="table">
<thead>
<tr>
<th>Symbol</th>
<th>Betydning</th>
</tr>
</thead>
<tbody>
<tr>
<td>
<i class="bi-calendar" style="font-size:1.3rem"></i>
</td>
<td>ToDo liste</td>
</tr>
<tr>
<td>
<i class="bi-file-spreadsheet" style="font-size:1.3rem"></i>
</td>
<td>Pris katalog</td>
</tr>
<tr>
<td>
<i class="bi-building" style="font-size:1.3rem"></i>
</td>
<td>Firmaer/Kunder</td>
</tr>
<tr>
<td>
<i class="bi-calculator" style="font-size:1.3rem"></i>
</td>
<td>Aftaler/Tilbud</td>
</tr>
<tr>
<td>
<i class="bi-activity" style="font-size:1.3rem"></i>
</td>
<td>Aktivitet</td>
</tr>
<tr>
<td>
<i class="bi-file-earmark-spreadsheet" style="font-size:1.3rem"></i>
</td>
<td>Dagsrapporter</td>
</tr>
</tbody>
</table>

View file

@ -0,0 +1,9 @@
<h3>Testede browsere</h3>
<ul class="list-group">
<li class="list-group-item">Safari (macOS, iOS)</li>
<li class="list-group-item">Chrome (Linux, Windows, Android)</li>
<li class="list-group-item">Edge (Linux, Windows, Android)</li>
<li class="list-group-item">Firefox (Linux, Windows, Android)</li>
<li class="list-group-item">Chromium (Linux)</li>
<li class="list-group-item">Vivaldi (Linux)</li>
</ul>

View file

@ -16,14 +16,23 @@
*@
@using Wonky.Client.Components
<h3>Kunde Info</h3>
<table class="table">
<thead>
<tr>
<th scope="colgroup" colspan="2">Kunde / Besøg Status</th>
<th scope="colgroup" colspan="2">Pakning / Forsendelse</th>
<th>Symbol</th>
<th>Betydning</th>
</tr>
</thead>
<tbody>
<tr>
<td class="align-middle">
<i class="bi-exclamation-diamond" style="font-size: 1.3rem;"></i>
</td>
<td class="align-middle">
Vigtig info registreret
</td>
</tr>
<tr>
<td class="align-middle">
<div class="color-code">
@ -31,12 +40,6 @@
</div>
</td>
<td class="align-middle">Er nylig besøgt</td>
<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">
@ -45,12 +48,6 @@
</div>
</td>
<td class="align-middle">Planlæg</td>
<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">
@ -59,12 +56,6 @@
</div>
</td>
<td class="align-middle">Interval Overskredet</td>
<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">
@ -73,12 +64,6 @@
</div>
</td>
<td class="align-middle">Ajourfør besøgsdato/interval</td>
<td class="align-middle">
<div class="color-code">
<DisplayStateComponent StateClass="the-dead"/>
</div>
</td>
<td class="align-middle">Varer er afsendt</td>
</tr>
<tr>
<td class="align-middle">
@ -87,8 +72,6 @@
</div>
</td>
<td class="align-middle">Virksomhed ophørt</td>
<td></td>
<td></td>
</tr>
<tr>
<td class="align-middle">
@ -97,8 +80,6 @@
</div>
</td>
<td class="align-middle">CVR/ORG nummer ugyldig</td>
<td></td>
<td></td>
</tr>
</tbody>
</table>

View file

@ -0,0 +1,6 @@
.pictogram {
max-width: 30px;
}
.color-code {
max-width: 30px;
}

View file

@ -0,0 +1,61 @@
@*
// 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>

View file

@ -0,0 +1,6 @@
.pictogram {
max-width: 30px;
}
.color-code {
max-width: 30px;
}

View file

@ -0,0 +1,41 @@
<h3>Fælles</h3>
<table class="table">
<thead>
<tr>
<th>Symbol</th>
<th>Betydning</th>
</tr>
<tr>
<td><i class="bi-cloud-arrow-up" style="font-size:1.3rem"></i></td>
<td>Gem data</td>
</tr>
<tr>
<td><i class="bi-search" style="font-size:1.3rem"></i></td>
<td>Søg</td>
</tr>
<tr>
<td><i class="bi-plus" style="font-size:1.3rem"></i></td>
<td>Opret</td>
</tr>
<tr>
<td><i class="bi-card-text" style="font-size:1.3rem"></i></td>
<td>Notat</td>
</tr>
<tr>
<td><i class="bi-printer" style="font-size:1.3rem"></i></td>
<td>Udskrivning</td>
</tr>
<tr>
<td><i class="bi-sliders" style="font-size:1.3rem"></i></td>
<td>Indstillinger</td>
</tr>
<tr>
<td><i class="bi-lock" style="font-size:1.3rem"></i></td>
<td>Log af</td>
</tr>
<tr>
<td><i class="bi-question" style="font-size:1.3rem"></i></td>
<td>Hjælp/Info</td>
</tr>
</thead>
</table>

View file

@ -0,0 +1,17 @@
<h3>Kontor</h3>
<table class="table">
<thead>
<tr>
<th>Symbol</th>
<th>Betydning</th>
</tr>
</thead>
<tbody>
<tr>
<td>
<i class="bi-people" style="font-size:1.3rem"></i>
</td>
<td>Brugere</td>
</tr>
</tbody>
</table>

View file

@ -0,0 +1,12 @@
<h3>Open Source</h3>
<ul class="list-group">
<a class="list-group-item list-group-item-action" href="https://dotnet.microsoft.com/en-us/apps/aspnet/web-apps/blazor/" target="_blank">Blazor WebAssembly</a>
<a class="list-group-item list-group-item-action" href="https://getbootstrap.com/" target="_blank">Bootstrap</a>
<a class="list-group-item list-group-item-action" href="https://github.com/SamHerbert/SVG-Loaders" target="_blank">SVG-Loaders</a>
<a class="list-group-item list-group-item-action" href="https://github.com/FCS-TECH/fcs-azure" target="_blank">FCS Azure</a>
<a class="list-group-item list-group-item-action" href="https://github.com/FCS-TECH/fcs-brreg" target="_blank">FCS BrReg</a>
<a class="list-group-item list-group-item-action" href="https://github.com/FCS-TECH/fcs-common" target="_blank">FCS Common</a>
<a class="list-group-item list-group-item-action" href="https://github.com/FCS-TECH/fcs-utils" target="_blank">FCS Utils</a>
<a class="list-group-item list-group-item-action" href="https://github.com/FCS-TECH/fcs-vies" target="_blank">FCS Vies</a>
<a class="list-group-item list-group-item-action" href="https://github.com/FCS-TECH/fcs-virk" target="_blank">FCS Virk</a>
</ul>

View file

@ -0,0 +1,38 @@
<h3>Bestilling Status</h3>
<table class="table">
<thead>
<tr>
<th>Symbol</th>
<th>Betydning</th>
</tr>
<tr>
<td><i class="bi-lightning-charge" style="font-size:1.3rem"></i></td>
<td>Ekspress</td>
</tr>
<tr>
<td><i class="bi-phone" style="font-size:1.3rem"></i></td>
<td>Telefon</td>
</tr>
<tr>
<td><i class="bi-file-earmark" style="font-size:1.3rem"></i></td>
<td>Ubehandlet</td>
</tr>
<tr>
<td><i class="bi-hand-thumbs-up" style="font-size:1.3rem"></i></td>
<td>Accepteret</td>
</tr>
<tr>
<td><i class="bi-file-earmark-check" style="font-size:1.3rem"></i></td>
<td>Plukket</td>
</tr>
<tr>
<td><i class="bi-box2" style="font-size:1.3rem"></i></td>
<td>Pakket</td>
</tr>
<tr>
<td><i class="bi-truck" style="font-size:1.3rem"></i></td>
<td>Leveret</td>
</tr>
</thead>
</table>

View file

@ -0,0 +1,33 @@
<h3>Aftaler / Tilbud</h3>
<table class="table">
<thead>
<tr>
<th>Symbol</th>
<th>Betydning</th>
</tr>
<tr>
<td><i class="bi-list" style="font-size:1.3rem"></i></td>
<td>Alle tilbud</td>
</tr>
<tr>
<td><i class="bi-trash" style="font-size:1.3rem"></i></td>
<td>Tabte tilbud</td>
</tr>
<tr>
<td><i class="bi-archive" style="font-size:1.3rem"></i></td>
<td>Ingen svar</td>
</tr>
<tr>
<td><i class="bi-question-circle" style="font-size:1.3rem"></i></td>
<td>Åbne tilbud</td>
</tr>
<tr>
<td><i class="bi-tag" style="font-size:1.3rem"></i></td>
<td>Aktive aftaler</td>
</tr>
<tr>
<td><i class="bi-activity" style="font-size:1.3rem"></i></td>
<td>Åbne tilbud / Aktive aftaler</td>
</tr>
</thead>
</table>

View file

@ -0,0 +1,17 @@
<h3>Lager</h3>
<table class="table">
<thead>
<tr>
<th>Symbol</th>
<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>

View file

@ -1,20 +0,0 @@
using Microsoft.AspNetCore.Components;
using Wonky.Client.Shared;
using Wonky.Entity.Views;
namespace Wonky.Client.Components;
public partial class InvoiceTableComponent
{
[Parameter] public string CompanyId { get; set; } = "";
[Parameter] public List<InvoiceListItemView> InvoiceList { get; set; } = new();
private InvoiceViewModal InvoiceView { get; set; } = new();
private string InvoiceId { get; set; } = "";
private void ShowInvoice(string invoiceId)
{
Console.WriteLine($"invoiceId => {invoiceId}");
Console.WriteLine($"companyId => {CompanyId}");
InvoiceId = invoiceId;
InvoiceView.Show();
}
}

View file

@ -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 Microsoft.AspNetCore.Authorization
@using Wonky.Client.Components
<PageTitle>Innotec Admin</PageTitle>
@*<div class="card mb-3" style="max-width: 300px">
<div class="row g-0">
<div class="col-4">
<i class="img-fluid rounded-start fi fi-dk" alt="dk flag"></i>
</div>
<div class="col-8">
<div class="card-body">
Danmark
</div>
</div>
</div>
</div>
<div class="card mb-3" style="max-width: 300px">
<div class="row g-0">
<div class="col-4">
<i class="img-fluid rounded-start fi fi-no" alt="no flag"></i>
</div>
<div class="col-8">
<div class="card-body">
Norge
</div>
</div>
</div>
</div>
<div class="card mb-3" style="max-width: 300px">
<div class="row g-0">
<div class="col-4">
<i class="img-fluid rounded-start fi fi-se" alt="se flag"></i>
</div>
<div class="col-8">
<div class="card-body">
Sverige
</div>
</div>
</div>
</div>*@

View file

@ -1,6 +0,0 @@
.workDate {
font-size: 1.2em;
font-weight: bold;
font-variant: small-caps;
}

View file

@ -18,12 +18,8 @@
@using Microsoft.AspNetCore.Authorization
@using Wonky.Client.Components
<PageTitle>Innotec Rådgiver</PageTitle>
<AuthorizeView Roles="Advisor">
<div class="bg-dark text-white rounded-2 mb-2 py-2">
<WorkDateComponent OnChangedCallback="GetWorkdayTasks"/>
<WorkDateComponent />
</div>
<TaskItemTableComponent TaskItemList="TaskItems" OnCompleteTask="OnCompleteTask"
OnDeleteTask="OnDeleteConfirmed" OnTaskCompleted="OnTaskCompleted"/>
</AuthorizeView>

View file

@ -30,14 +30,9 @@ using Wonky.Entity.Models;
using Wonky.Entity.Views;
namespace Wonky.Client.Components;
public partial class LandingComponentAdvisor : IDisposable
public partial class LandingComponentAdvisor
{
[Inject] public UserProfileService ProfileService { get; set; }
[Inject] public ILogger<LandingComponentAdvisor> Logger { get; set; }
[Inject] public HttpInterceptorService Inteceptor { get; set; }
[Inject] public IToastService Toaster { get; set; }
[Inject] public ICrmTaskItemHttpRepository TaskItemRepo { get; set; }
[Inject] public NavigationManager Navigator { get; set; }
[Inject] private UserProfileService ProfileService { get; set; }
private readonly JsonSerializerOptions JsonOptions = new JsonSerializerOptions
{
@ -47,59 +42,12 @@ public partial class LandingComponentAdvisor : IDisposable
private UserPref Prefs { get; set; } = new();
private DateTime SelectedDate { get; set; }
private List<TaskItemDto> TaskItems { get; set; } = new();
protected override async Task OnInitializedAsync()
{
Prefs = await ProfileService.GetPreferences();
SelectedDate = string.IsNullOrWhiteSpace(Prefs.WorkDate) ? DateTime.Now : DateTime.Parse(Prefs.WorkDate);
Inteceptor.RegisterEvent();
Inteceptor.RegisterBeforeSendEvent();
//await GetTaskItems(_workDate);
await GetAllTasks();
}
private async Task GetAllTasks()
{
TaskItems = await TaskItemRepo.GetTaskList();
}
private async Task OnCompleteTask(string taskItemId)
{
await ProfileService.SetWorkDate(DateTime.Now);
var item = TaskItems.Find(x => x.TaskItemId == taskItemId);
Navigator.NavigateTo($"/companies/{item.ReferenceId}/activities/new");
}
private async Task GetWorkdayTasks(string workDate)
{
SelectedDate = DateTime.Parse(workDate);
TaskItems = new List<TaskItemDto>();
TaskItems = await TaskItemRepo.GetTaskList($"{SelectedDate:yyyy-MM-dd}");
}
private async Task OnTaskCompleted(string taskItemId)
{
var item = TaskItems.Find(x => x.TaskItemId == taskItemId);
item.IsCompleted = true;
await TaskItemRepo.UpdateTaskItem(taskItemId, item);
TaskItems.Remove(item);
Toaster.ShowInfo("Opgaven er markeret som udført.");
}
private async Task OnDeleteConfirmed(string taskItemId)
{
var item = TaskItems.First(x => x.TaskItemId == taskItemId);
TaskItems.Remove(item);
await TaskItemRepo.DeleteTaskItem(taskItemId);
Toaster.ShowInfo("Opgaven er slettet.");
}
public void Dispose()
{
Inteceptor.DisposeEvent();
}
}

View file

@ -0,0 +1,91 @@
@*
// 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
<div class="row">
<div class="col-lg-4 col-md-12 col-md-4 mb-4">
<div class="card">
<div class="card-header">Danmark</div>
<div class="card-body">
<div class="list-group list-group-flush">
<AuthorizeView Roles="Admin,Office">
<a class="list-group-item list-group-item-action list-group-item-warning" href="/office/users/advisors/dk">
<i class="bi-activity"></i> Sælgere
</a>
</AuthorizeView>
@*
<a class="list-group-item list-group-item-action list-group-item-success" href="/office/customers/dk">
<i class="bi-building"></i> Tlf.Ordre
</a>
*@
<a class="list-group-item list-group-item-action list-group-item-info" href="/catalog/dk">
<i class="bi-file-spreadsheet"></i> Priser
</a>
</div>
</div>
</div>
</div>
<div class="col-lg-4 col-md-12 col-md-4 mb-4">
<div class="card">
<div class="card-header">Norge</div>
<div class="card-body">
<div class="list-group">
<AuthorizeView Roles="Admin,Office">
<a class="list-group-item list-group-item-action list-group-item-warning" href="/office/users/advisors/no">
<i class="bi-activity"></i> Sælgere
</a>
</AuthorizeView>
@*
<a class="list-group-item list-group-item-action list-group-item-success" href="/office/customers/no">
<i class="bi-phone"></i> Tlf.Ordre
</a>
*@
<a class="list-group-item list-group-item-action list-group-item-info" href="/catalog/no">
<i class="bi-file-spreadsheet"></i> Priser
</a>
</div>
</div>
</div>
</div>
<div class="col-lg-4 col-md-12 col-md-4 mb-4">
<div class="card">
<div class="card-header">Sverige</div>
<div class="card-body">
<div class="list-group">
<AuthorizeView Roles="Admin,Office">
<a class="list-group-item list-group-item-action list-group-item-warning" href="/office/users/advisors/se">
<i class="bi-activity"></i> Sælgere
</a>
</AuthorizeView>
@*
<a class="list-group-item list-group-item-action list-group-item-success" href="/office/customers/se">
<i class="bi-phone"></i> Tlf.Ordre
</a>
*@
<a class="list-group-item list-group-item-action list-group-item-info" href="/catalog/se">
<i class="bi-file-spreadsheet"></i> Priser
</a>
</div>
</div>
</div>
</div>
</div>

View file

@ -30,14 +30,9 @@ using Wonky.Entity.Models;
using Wonky.Entity.Views;
namespace Wonky.Client.Components;
public partial class LandingComponentAdmin : IDisposable
public partial class LandingComponentOffice
{
[Inject] public UserProfileService ProfileService { get; set; }
[Inject] public ILogger<LandingComponentAdmin> Logger { get; set; }
[Inject] public HttpInterceptorService Interceptor { get; set; }
[Inject] public IToastService Toaster { get; set; }
[Inject] public ICrmTaskItemHttpRepository CrmTaskItemRepo { get; set; }
[Inject] public NavigationManager Navigator { get; set; }
[Inject] private UserProfileService ProfileService { get; set; }
private readonly JsonSerializerOptions _options = new JsonSerializerOptions
{
@ -46,23 +41,23 @@ public partial class LandingComponentAdmin : IDisposable
};
private UserPref Prefs { get; set; } = new();
private string WordDate { get; set; } = $"{DateTime.Now:yyyy-MM-dd}";
private string WorkDate { get; set; } = $"{DateTime.Now:yyyy-MM-dd}";
private string Today { get; set; } = $"{DateTime.Now:yyyy-MM-dd}";
protected override async Task OnInitializedAsync()
{
ProfileService.OnChange += ProfileChanged;
Prefs = await ProfileService.GetPreferences();
if(!string.IsNullOrWhiteSpace(Prefs.WorkDate))
WordDate = Prefs.WorkDate;
Interceptor.RegisterEvent();
Interceptor.RegisterBeforeSendEvent();
if (string.IsNullOrWhiteSpace(Prefs.WorkDate))
{
await ProfileService.SetWorkDate(DateTime.Now);
}
}
public void Dispose()
private void ProfileChanged(UserPref newPrefs)
{
Interceptor.DisposeEvent();
}
Prefs = newPrefs;
WorkDate = Prefs.WorkDate;
}
}

View file

@ -0,0 +1,92 @@
@*
// 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.Entity.Views
@* Report activities *@
<table class="table table-striped">
<thead>
<tr class="bg-black opacity-75 text-white">
<th scope="col">Kunde</th>
<th scope="col">Bynavn</th>
<th scope="col">Demo</th>
<th scope="col">Salg</th>
<th scope="col">Note</th>
<th scope="col" class="text-end">sas</th>
<th scope="col" class="text-end">Beløb</th>
<th scope="col" class="text-center">
<i style="font-size:1.3em;" class="bi-phone"></i>
</th>
<th scope="col" class="text-center">
<i class="bi-lightning"></i>
</th>
<th scope="col" class="text-center">
<i class="bi-calculator"></i>
</th>
<th scope="col" class="text-center">
<i class="bi-truck"></i>
</th>
</tr>
</thead>
<tbody>
@foreach (var activity in Activities)
{
<tr>
<td class="text-sm-start">@activity.Company.Name</td>
<td class="text-sm-start">@activity.Company.City</td>
<td class="text-sm-start">@activity.Demo</td>
<td class="text-sm-start">@activity.Sales</td>
<td class="text-sm-start">@activity.OfficeNote</td>
<td class="text-end">@($"{activity.SasAmount:N2}")</td>
<td class="text-center">@(activity.StatusTypeEnum.Contains("Quote") ? $"{0:N2}" : $"{activity.OrderAmount:N2}")</td>
<td class="text-center">
@if (activity.OurRef.Contains("T:"))
{
<i style="font-size:1.5em;" class="bi-phone"></i>
}
</td>
<td class="text-center">
@if (activity.Express)
{
<i style="font-size:1.5em;" class="bi-lightning"></i>
}
</td>
<td class="text-center">
@if (activity.StatusTypeEnum == "Quote")
{
<i style="font-size:1.5em;" class="bi-calculator"></i>
}
</td>
<td class="text-center">
<ProcessStateComponent StateClass="@activity.ProcessStatusEnum"/>
</td>
</tr>
}
<tr>
<td class="bg-black opacity-75" colspan="5"></td>
<td class="text-end">Total</td>
<td class="text-end">@Activities.Where(x => x.StatusTypeEnum != "Quote").Sum(x => x.OrderAmount)</td>
<td class="bg-black opacity-75" colspan="4"></td>
</tr>
</tbody>
</table>
@code {
[Parameter]
public List<ReportItemView> Activities { get; set; } = new();
}

View file

@ -1,58 +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]
//
*@
@if (UserList.Any())
{
<table class="table table-striped">
<thead>
<tr>
<th scope="col">
Navn
</th>
<th scope="col">
Telefon
</th>
<th scope="col">
Email
</th>
<th scope="col">
</th>
<th scope="col">
</th>
</tr>
</thead>
<tbody>
@foreach (var user in UserList)
{
<tr class="align-middle">
<td>@user.FullName</td>
<td>@user.PhoneNumber</td>
<td>@user.Email</td>
<td><a class="btn btn-outline-dark" href="/office/users/advisors/@user.CountryCode.ToLower()/@user.UserId/reports">Rapporter</a></td>
<td><a class="btn btn-outline-dark" href="/office/users/advisors/@user.CountryCode.ToLower()/@user.UserId/companies">Kunder</a></td>
<td><a class="btn btn-outline-dark" href="/office/users/advisors/@user.CountryCode.ToLower()/@user.UserId/view">Rediger</a></td>
</tr>
}
</tbody>
</table>
}
else
{
<div>Ingen data</div>
}

View file

@ -0,0 +1,49 @@
@*
// 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]
//
*@
<div class="list-group list-group-flush">
@if (UserList.Any())
{
foreach (var user in UserList)
{
<div class="list-group-item list-group-item-action" style="cursor: pointer;">
<div class="row align-items-center">
<div class="col-sm-1">@user.SalesRep</div>
<div class="col-sm-3">@user.FullName</div>
<div class="col-sm-2">@user.PhoneNumber</div>
<div class="col-sm-2">
<a class="btn btn-warning d-block" href="/office/users/advisors/@user.CountryCode.ToLower()/@user.UserId/reports">Rapporter</a>
</div>
<div class="col-sm-2">
<a class="btn btn-success d-block" href="/office/users/advisors/@user.CountryCode.ToLower()/@user.UserId/customers">Kunder</a>
</div>
<div class="col-sm-2">
<AuthorizeView Roles="Admin">
<Authorized>
<a class="btn btn-info d-block" href="/office/users/advisors/@user.CountryCode.ToLower()/@user.UserId/view">Rediger</a>
</Authorized>
</AuthorizeView>
</div>
</div>
</div>
}
}
else
{
<div>Ingen data</div>
}
</div>

View file

@ -19,7 +19,7 @@ using Wonky.Entity.Views;
namespace Wonky.Client.Components;
public partial class OfficeUserTableComponent
public partial class OfficeCountryAdvisorListComponent
{
[Parameter] public List<UserListAdminView> UserList { get; set; } = new();
}

View file

@ -20,19 +20,20 @@
@if (CompanyList.Any())
{
@*
<div class="list-group list-group-flush">
<div class="list-group-item px-3 bg-black text-white opacity-75">
<div class="row">
<div class="col-md-1">
<div class="col-sm-1">
Sælger
</div>
<div class="col-md-1">
<div class="col-sm-1">
Konto
</div>
<div class="col-md-2">
<div class="col-sm-1">
Telefon
</div>
<div class="col">
<div class="col-sm-3">
Navn
</div>
<div class="col">
@ -40,20 +41,51 @@
</div>
</div>
</div>
*@
<div class="row d-flex g-3">
@foreach (var company in CompanyList)
{
<a class=" list-group-item list-group-item-action" href="/office/customers/@company.CompanyId/orders/new">
<div class="col-sm-6">
<div class="card">
<div class="card-body">
<h5 class="card-title">
@company.Name
</h5>
<div class="row">
<div class="col-sm-3 col-md-3 fw-bold">Konto</div>
<div class="col-sm-3 col-dm-3">@company.Account</div>
<div class="col-sm-3 col-md-3 fw-bold">CVR / ORG</div>
<div class="col-sm-3 col-md-3">@company.VatNumber</div>
</div>
<div class="row">
<div class="col-sm-3 col-md-3 fw-bold">Telefon</div>
<div class="col-sm-3 col-md-3">@company.Phone</div>
</div>
<div class="row">
<div class="col-sm-3 col-md-3 fw-bold">Adresse</div>
<div class="col-sm-9 col-md-9">@company.Address1 @(string.IsNullOrWhiteSpace(company.Address2) ? "" : ",") @company.Address2</div>
</div>
<div class="row">
<div class="col-sm-3 col-md-3 fw-bold">Post By</div>
<div class="col-sm-9 col-md-9">@company.CountryCode.ToUpper()-@company.ZipCode @company.City</div>
</div>
</div>
</div>
</div>
@*
<a class=" list-group-item list-group-item-action" href="/office/customers/@CountryCode/@company.CompanyId/order">
<div class="row align-items-center">
<div class="col-md-1">
<div class="col-sm-1">
@company.SalesRep
</div>
<div class="col-md-1">
<div class="col-sm-1">
@company.Account
</div>
<div class="col-md-2">
<div class="col-sm-1">
@company.Phone
</div>
<div class="col">
<div class="col-sm-3">
@company.Name
</div>
<div class="col">
@ -61,6 +93,7 @@
</div>
</div>
</a>
*@
}
</div>
}

View file

@ -24,9 +24,10 @@ using Wonky.Entity.Views;
namespace Wonky.Client.Components
{
public partial class OfficeCustomerTableComponent
public partial class OfficeCountryCustomerListComponent
{
[Parameter] public List<CompanyDto> CompanyList { get; set; } = new();
[Parameter] public List<CompanyDto> CompanyList { get; set; } = new();
[Parameter] public string CountryCode { get; set; } = "";
}
}

View file

@ -14,12 +14,11 @@
//
using Microsoft.AspNetCore.Components;
using Wonky.Entity.DTO;
using Wonky.Entity.Views;
namespace Wonky.Client.Components;
public partial class OfficeAdvisorTableComponent
public partial class OfficeCountryUserListComponent
{
[Parameter] public List<UserListAdminView> UserList { get; set; } = new();
}

View file

@ -1,3 +1,4 @@
@using Wonky.Client.Helpers
@*
// Copyright (C) 2022 FCS Frede's Computer Services.
// This program is free software: you can redistribute it and/or modify
@ -15,9 +16,10 @@
//
*@
@using Wonky.Client.Helpers
@if (ActivityList.Any())
{
<table class="table table-bordered d-print-table table-striped">
<table class="table table-sm table-bordered d-print-table table-striped">
<thead>
<tr class="bg-dark text-white opacity-75 border-bottom">
<th scope="col">Kunde</th>
@ -27,10 +29,10 @@
<th scope="col">Note</th>
<th class="text-end" scope="col">sas</th>
<th class="text-end" scope="col">Beløb</th>
<th class="text-center" scope="col"><i class="oi oi-phone"></i></th>
<th class="text-center" scope="col"><i class="oi oi-flash"></i></th>
<th class="text-center" scope="col"><i class="oi oi-calculator"></i></th>
<th class="text-center" scope="col"><i class="bi bi-truck"></i></th>
<th class="text-center" scope="col"><i class="bi-phone"></i></th>
<th class="text-center" scope="col"><i class="bi-lightning"></i></th>
<th class="text-center" scope="col"><i class="bi-calculator"></i></th>
<th class="text-center" scope="col"><i class="bi-truck"></i></th>
</tr>
</thead>
<tbody>
@ -59,7 +61,7 @@
<td class="align-middle state">
@if (activity.Lines.Any() && activity.StatusTypeEnum == "Order")
{
<ProcessStateComponent StateClass="@GetProcessStatus(activity.ProcessStatusEnum)"/>
<ProcessStateComponent StateClass="@Utils.GetProcessStatus(activity.ProcessStatusEnum)"/>
}
</td>
</tr>

View file

@ -18,13 +18,13 @@ using Wonky.Entity.Views;
namespace Wonky.Client.Components;
public partial class ActivityTableCrmComponent
public partial class OfficeReportActivityListComponent
{
[Parameter] public List<ReportItemView> ActivityList { get; set; } = new();
[Inject] public NavigationManager Navigator { get; set; }
// private void ShowOrder(string companyId, string orderId)
// {
// Navigator.NavigateTo($"office/customers/{companyId}/orders/{orderId}");
// }
[Inject] private NavigationManager Navigator { get; set; }
private void ShowOrder(string companyId, string orderId)
{
Navigator.NavigateTo($"/office/customers/{companyId}/orders/{orderId}");
}
}

View file

@ -18,7 +18,7 @@ using Wonky.Entity.Views;
namespace Wonky.Client.Components;
public partial class ReportTableOfficeComponent
public partial class OfficeReportListComponent
{
[Parameter] public List<SalesReportListView> ReportList { get; set; } = new();
[Parameter] public string UserId { get; set; } = "";

View file

@ -23,18 +23,20 @@ namespace Wonky.Client.Components
{
public partial class PageSizeComponent : IDisposable
{
[Inject] public ILocalStorageService Storage { get; set; }
[Inject] public UserProfileService ProfileService { get; set; }
[Inject] private ILocalStorageService Storage { get; set; }
[Inject] private UserProfileService ProfileService { get; set; }
[Parameter] public EventCallback<string> OnChanged { get; set; }
private Dictionary<string, string> Items { get; set; } = new();
private UserPref Prefs = new();
private string PageSize { get; set; } = "";
protected override async Task OnInitializedAsync()
{
ProfileService.OnChange += ProfileServiceOnOnChange;
Prefs = await ProfileService.GetPreferences();
PageSize = Prefs.PageSize;
}
private async Task OnSelectChanged(ChangeEventArgs e)
{
var val = e.Value.ToString();
@ -42,11 +44,13 @@ namespace Wonky.Client.Components
await OnChanged.InvokeAsync(val);
await ProfileService.SetPageSize(val);
}
private void ProfileServiceOnOnChange(UserPref newUserPref)
{
Prefs = newUserPref;
StateHasChanged();
}
public void Dispose()
{
ProfileService.OnChange -= ProfileServiceOnOnChange;

View file

@ -30,6 +30,7 @@
"the-bad" => "file-earmark-check",
"the-ugly" => "box2-fill",
"the-dead" => "truck",
"accepted" => "hand-thumbs-up",
_ => "question-square"
};
}

View file

@ -45,38 +45,38 @@
@switch (quote.QuoteStatusEnum)
{
case "None":
<i class="bi-question-circle-fill"></i>
<i class="bi-question-circle-fill"style="font-size: 1.2rem"></i>
break;
case "Lose":
<i class="bi-trash-fill"></i>
<i class="bi-trash-fill"style="font-size: 1.2rem"></i>
break;
case "Note":
<i class="bi-tag-fill"></i>
<i class="bi-tag-fill"style="font-size: 1.2rem"></i>
break;
case "Archive":
<i class="bi-archive-fill"></i>
<i class="bi-archive-fill"style="font-size: 1.2rem"></i>
break;
default:
<i class="bi-question-circle-fill"></i>
<i class="bi-question-circle-fill"style="font-size: 1.2rem"></i>
break;
}
</div>
<div class="col-sm-2 text-center">
<a class="btn btn-outline-dark d-block" style="font-family:monospace;font-size: 14px;"
href="/companies/@quote.Company.CompanyId/quotes/@quote.ActivityId">@quote.ESalesNumber</a>
href="/advisor/customers/@quote.Company.CompanyId/quotes/@quote.ActivityId">@quote.ESalesNumber</a>
</div>
@if (!string.IsNullOrWhiteSpace(quote.OfficeNote))
{
<div class="col-sm-2 text-end">Note</div>
<div class="col-sm-2 text-end">Kontor <i class="bi-card-text"></i></div>
<div class="col-sm-10">
<i class="bi-pencil"></i> @quote.OfficeNote
@quote.OfficeNote
</div>
}
@if (!string.IsNullOrWhiteSpace(quote.CrmNote))
{
<div class="col-sm-2 text-end">CRM note</div>
<div class="col-sm-2 text-end">CRM <i class="bi-card-text"></i></div>
<div class="col-sm-10">
<i class="bi-pencil"></i> @quote.CrmNote
@quote.CrmNote
</div>
}
</div>
@ -89,19 +89,3 @@
}
</div>
@code {
[Parameter]
public List<ReportItemView> Quotes { get; set; } = new();
[Parameter] public EventCallback<QuoteCallbackArgs> OnChangedCallback { get; set; }
private async Task SetQuote(string eSalesNumber, QStatus status)
{
var args = new QuoteCallbackArgs()
{
ESalesNumber = eSalesNumber,
Status = status
};
await OnChangedCallback.InvokeAsync(args);
}
}

View file

@ -0,0 +1,22 @@
using Microsoft.AspNetCore.Components;
using Wonky.Client.Models;
using Wonky.Entity.Views;
namespace Wonky.Client.Components;
public partial class QuoteListComponent
{
[Parameter]
public List<ReportItemView> Quotes { get; set; } = new();
[Parameter] public EventCallback<QCallbackArgs> OnChangedCallback { get; set; }
private async Task SetQuote(string eSalesNumber, QStatus status)
{
var args = new QCallbackArgs()
{
ESalesNumber = eSalesNumber,
Status = status
};
await OnChangedCallback.InvokeAsync(args);
}
}

View file

@ -1,3 +1,4 @@
@using Wonky.Entity.Views
@*
// Copyright (C) 2022 FCS Frede's Computer Services.
// This program is free software: you can redistribute it and/or modify
@ -84,4 +85,8 @@
</tbody>
</table>
</div>
</div>
@code{
[Parameter] public ReportData ReportData { get; set; } = new();
}

View file

@ -1,43 +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.Entity.Views;
namespace Wonky.Client.Components;
public partial class ReportActivityTableOfficeComponent
{
[Parameter] public List<ReportItemView> ActivityList { get; set; } = new();
[Inject] public NavigationManager Navigator { get; set; }
private static string GetProcessStatus(string processStatus)
{
return processStatus.ToLower() switch
{
"express" => "the-fast",
"none" => "the-good",
"picked" => "the-bad",
"packed" => "the-ugly",
"shipped" => "the-dead",
_ => "the-draw"
};
}
private void ShowOrder(string companyId, string orderId)
{
Navigator.NavigateTo($"office/customers/{companyId}/orders/{orderId}");
}
}

View file

@ -22,7 +22,7 @@
<thead>
<tr>
<th class="p-0" colspan="4">
<div class="bg-light text-dark border border-1 rounded-3 pt-3 mb-2">
<div class="alert d-print-block border border-1 border-dark pt-3 mb-2">
<h2 class="fw-bold text-center">@ReportItem.Company.Name</h2>
@if (ReportItem.Express)
{
@ -134,23 +134,10 @@
</table>
@if (!string.IsNullOrWhiteSpace(@ReportItem.OfficeNote))
{
<div class="alert alert-dark d-print-block">
<h4 class="text-center">
<div class="alert d-print-block border border-1 border-dark">
<p class="text-center h4">
@ReportItem.OfficeNote
</h4>
</p>
</div>
}
</div>
@code{
[Parameter]
public ReportItemView ReportItem { get; set; } = new();
protected override void OnParametersSet()
{
var lines = ReportItem.Lines.OrderBy(x => x.Location).ToList();
ReportItem.Lines = lines;
}
}

View file

@ -0,0 +1,16 @@
using Microsoft.AspNetCore.Components;
using Wonky.Entity.Views;
namespace Wonky.Client.Components;
public partial class ReportItemComponent
{
[Parameter]
public ReportItemView ReportItem { get; set; } = new();
protected override void OnParametersSet()
{
var lines = ReportItem.Lines.OrderBy(x => x.Location).ToList();
ReportItem.Lines = lines;
}
}

View file

@ -19,7 +19,7 @@ using Wonky.Entity.Views;
namespace Wonky.Client.Components;
public partial class ReportTableCrmComponent
public partial class ReportListComponent
{
[Parameter] public List<SalesReportListView> ReportList { get; set; } = new();
[Parameter] public EventCallback<string> OnShowReport { get; set; }

View file

@ -47,7 +47,7 @@
</label>
</td>
<td class="align-middle">
<a class="btn btn-light border-dark" href="/tasks/@task.TaskItemId">
<a class="btn btn-light border-dark" href="/advisor/tasks/@task.TaskItemId">
<i class="oi oi-calendar"></i>
</a>
</td>
@ -64,7 +64,7 @@
<td class="align-middle">
@if (task.TaskTypeEnum is "Recall")
{
<a class="btn btn-light border-dark pe-3 me-2" href="/companies/@task.ReferenceId">
<a class="btn btn-light border-dark pe-3 me-2" href="/advisor/customers/@task.ReferenceId">
<i class="oi oi-pencil"></i>
</a>
}
@ -81,7 +81,7 @@
}
</tbody>
</table>
<ConfirmationModal BodyMessage="Handlingen kan ikke gøres om. Vil du slette opgaven?" OnOkClicked="DeleteTask" @ref="_confirmationModal"/>
<ConfirmationModal BodyMessage="Handlingen kan ikke gøres om. Vil du slette opgaven?" OnOkClicked="DeleteTask" OnCancelClicked="OnCancelCallback" @ref="_confirmationModal"/>
}
else
{

View file

@ -61,6 +61,10 @@ namespace Wonky.Client.Components
_confirmationModal.Show();
}
private void OnCancelCallback()
{
_confirmationModal.Hide();
}
/// <summary>
/// Delete task call back
/// </summary>

View file

@ -19,9 +19,9 @@
<AuthorizeView>
<Authorized>
<div class="d-print-none">
<a class="btn btn-outline-light" href="logout" title="Log af" ><i class="bi-lock"></i></a>
<a class="btn btn-outline-light" href="info" title="Information"><i class="bi-question"></i></a>
<a class="btn btn-outline-light" href="preferences" title="Indstillinger"><i class="bi-sliders"></i></a>
<a class="btn btn-outline-light" href="/logout" title="Log af" ><i class="bi-lock"></i></a>
<a class="btn btn-outline-light" href="/info" title="Information"><i class="bi-question"></i></a>
<a class="btn btn-outline-light" href="/preferences" title="Indstillinger"><i class="bi-sliders"></i></a>
</div>
</Authorized>
</AuthorizeView>

View file

@ -1,3 +1,4 @@
@using Wonky.Client.Models
@*
// Copyright (C) 2022 FCS Frede's Computer Services.
// This program is free software: you can redistribute it and/or modify
@ -15,104 +16,86 @@
//
*@
<div class="row mb-3">
<div class="col-md-4">
<div class="btn-group" role="group" aria-label="Ordre status">
<input type="radio" class="btn-check" name="btn-order" id="btn-order1" autocomplete="off" checked @onchange="@GetOrderStatusNone"/>
<label class="btn btn-outline-success" for="btn-order1">Ubehandlet</label>
@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(PStatus.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" autocomplete="off" @onchange="@GetOrderStatusPicked"/>
<label class="btn btn-outline-warning" for="btn-order2">Plukket</label>
<input type="radio" class="btn-check" name="btn-order" id="btn-order2" @onchange="() => GetWithStatus(PStatus.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" autocomplete="off" @onchange="@GetOrderStatusPacked"/>
<label class="btn btn-outline-danger" for="btn-order3">Pakket</label>
<input type="radio" class="btn-check" name="btn-order" id="btn-order4" autocomplete="off" @onchange="@GetOrderStatusShipped"/>
<label class="btn btn-outline-info" for="btn-order4">Afsendt</label>
</div>
</div>
<div class="col-md-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-danger">@OrderList.Count</span>
<span class="visually-hidden">ordrer i listen</span>
</label>
</div>
<div class="col-md-4 text-end">
@if (ReadyToShip && OrderList.Any())
{
<button type="button" class="btn btn-primary text-sm-center" @onclick="SetAllPackedStatusToShipped">Sæt alle afsendt</button>
}
</div>
</div>
<div class="list-group list-group-flush">
<div class="list-group-item">
<div class="row mb-1">
<div class="col-md-2">
<h4>Ordredato</h4>
</div>
<div class="col-md-4">
<h4>Kundenavn</h4>
</div>
<div class="col-md-3">
<h4>Postnr. Bynavn</h4>
</div>
<div class="col-md-1 text-center">
<h4>
<i class="oi oi-flash"></i>
</h4>
</div>
<div class="col-md-2">
<h4>Status</h4>
<input type="radio" class="btn-check" name="btn-order" id="btn-order3" @onchange="() => GetWithStatus(PStatus.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>
@if (OrderList.Any())
{
@foreach (var order in OrderList)
<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)
{
<a class="list-group-item list-group-item-action" href="warehouse/orders/process/@order.OrderId">
<div class="list-group-item list-group-item-action" style="cursor: hand;">
<div class="row">
<div class="col-md-2">
@order.OrderDate
</div>
<div class="col-md-4">
<div class="col-sm-4">
@order.Company.Name
</div>
<div class="col-md-3">
<div class="col-sm-3">
@order.Company.ZipCode @order.Company.City
</div>
<div class="col-md-1 text-center">
<div class="col-sm-2">
@order.OrderDate
</div>
<div class="col-sm-3 d-flex">
@if (order.Express)
{
<i class="oi oi-flash"></i>
<i class="bi-lightning-fill text-warning"></i>
}
</div>
<div class="col-md-2">
@switch (order.ProcessStatusEnum.ToLower())
{
case "none":
<span>Ubehandlet</span>
<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":
<span>Plukket</span>
<a class="btn btn-warning" href="warehouse/orders/process/@order.OrderId">Pak varer</a>
break;
case "packed":
<span>Pakket</span>
break;
case "shipped":
<span>Afsendt</span>
<a class="btn btn-warning" href="warehouse/orders/process/@order.OrderId">Afhent varer</a>
break;
}
</div>
</div>
</a>
</div>
}
}
else
{
<div>
Flot klaret - bordet er ryddet
</div>
}
</div>
</div>
}

View file

@ -13,131 +13,43 @@
// 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.HttpInterfaces;
using Wonky.Client.HttpRepository;
using Wonky.Client.Models;
using Wonky.Entity.Views;
namespace Wonky.Client.Components;
public partial class WarehouseListComponent
{
[Parameter] public string Status { get; set; } = "none";
[Inject] public HttpInterceptorService Interceptor { get; set; }
[Inject] public IWarehouseHttpRepository WarehouseRepo { get; set; }
[Inject] public IToastService Toaster { get; set; }
private string ItemList { get; set; } = "";
private bool ReadyToShip;
private string Header = "Ubehandlet";
[Parameter] public string Header { get; set; } = "";
[Parameter] public List<WarehouseOrderView>? OrderList { get; set; }
[Parameter] public bool ReadyToShip { get; set; }
[Parameter] public EventCallback<PStatus> OnGetStatus { get; set; }
[Parameter] public EventCallback OnSetShipped { get; set; }
[Parameter] public EventCallback<string> OnQPak { get; set; }
private List<WarehouseOrderView> OrderList { get; set; }
private bool Working { get; set; } = true;
private List<WarehouseOrderView> Orders { get; set; } = new();
protected override async Task OnInitializedAsync()
protected override async Task OnParametersSetAsync()
{
Interceptor.RegisterEvent();
Interceptor.RegisterBeforeSendEvent();
switch (Status.ToLower())
{
case "none":
Header = "Ubehandlede ordrer";
await GetOrderStatusNone();
break;
case "picked":
Header = "Plukkede ordrer";
await GetOrderStatusPicked();
break;
case "packed":
Header = "Pakkede ordrer";
await GetOrderStatusPacked();
break;
case "shipped":
Header = "Afsendte ordrer";
await GetOrderStatusShipped();
break;
default:
await GetOrderStatusNone();
break;
}
}
private async Task GetOrderStatusNone()
{
Working = true;
OrderList = new List<WarehouseOrderView>();
Header = "Ubehandlede ordrer";
ReadyToShip = false;
Working = true;
OrderList = new List<WarehouseOrderView>();
OrderList = await WarehouseRepo.GetWarehouseOrderListByStatus("none");
if(OrderList.Any(x => x.Express))
OrderList = OrderList.OrderByDescending(x => x.Express).ToList();
Working = false;
}
private async Task GetOrderStatusPicked()
{
Working = true;
OrderList = new List<WarehouseOrderView>();
Header = "Plukkede ordrer";
ReadyToShip = false;
Working = true;
OrderList = new List<WarehouseOrderView>();
OrderList = await WarehouseRepo.GetWarehouseOrderListByStatus("picked");
Working = false;
}
private async Task GetOrderStatusPacked()
{
Working = true;
OrderList = new List<WarehouseOrderView>();
Header = "Pakkede ordrer";
Working = true;
OrderList = new List<WarehouseOrderView>();
OrderList = await WarehouseRepo.GetWarehouseOrderListByStatus("packed");
ReadyToShip = true;
Working = false;
}
private async Task GetOrderStatusShipped()
{
Working = true;
OrderList = new List<WarehouseOrderView>();
Header = "Afsendte ordrer";
ReadyToShip = false;
Toaster.ShowWarning("Det kan tage lidt tid at hente alle.\nVent venligst.\nMåske skal vi tænke over hvor mange vi henter?");
Working = true;
OrderList = new List<WarehouseOrderView>();
var orderList = await WarehouseRepo.GetWarehouseOrderListByStatus("shipped");
OrderList = orderList.OrderByDescending(x => x.OrderDate).ToList();
Toaster.ShowInfo("Her er de så ....");
Working = false;
while (OrderList == null)
await Task.Delay(500);
Orders = OrderList;
}
private async Task SetAllPackedStatusToShipped()
private async Task SetShipStatus()
{
Working = true;
foreach (var order in OrderList.Where(order => order.ProcessStatusEnum.ToLower() == "packed"))
{
order.ProcessStatusEnum = "shipped";
var process = new WarehouseProcess
{
OrderId = order.OrderId,
ProcessStatusEnum = "shipped"
};
await WarehouseRepo.UpdateWarehouseOrderStatus(process);
}
Working = false;
await OnSetShipped.InvokeAsync();
}
public void Dispose()
private async Task GetWithStatus(PStatus status)
{
Interceptor.DisposeEvent();
await OnGetStatus.InvokeAsync(status);
}
private async Task QuickPak(string orderId)
{
await OnQPak.InvokeAsync(orderId);
}
}

View file

@ -21,8 +21,8 @@
<EditForm EditContext="WorkDateContext">
<div class="container-fluid">
<div class="row align-items-center">
<div class="col-sm-7 work-date">
@SelectedDate.ToLongDateString()
<div class="col-sm-7 fw-bold">
d. @(SelectedDate.Day)/@(SelectedDate.Month)
</div>
<div class="col-sm-5">
<InputDate class="form-control calendar" @bind-Value="SelectedDate" @oninput="OnDateChanged"/>

View file

@ -14,7 +14,7 @@
</div>
@foreach (var workplace in Workplaces)
{
<a class="list-group-item list-group-item-action" href="/companies/@CompanyId/workplaces/@workplace.WorkplaceId">
<a class="list-group-item list-group-item-action" href="/advisor/customers/@CompanyId/workplaces/@workplace.WorkplaceId">
<div class="row">
<div class="col">
@workplace.Name
@ -31,10 +31,3 @@ else
{
<div>Ingen data</div>
}
@code {
[Parameter] public List<WorkplaceListView> Workplaces { get; set; } = new();
[Parameter] public string CompanyId { get; set; } = "";
}

View file

@ -0,0 +1,11 @@
using Microsoft.AspNetCore.Components;
using Wonky.Entity.Views;
namespace Wonky.Client.Components;
public partial class WorkplaceListComponent
{
[Parameter] public List<WorkplaceListView> Workplaces { get; set; } = new();
[Parameter] public string CompanyId { get; set; } = "";
}

View file

@ -14,14 +14,34 @@
//
namespace Wonky.Client.Features;
/// <summary>
/// PagingLink class
/// </summary>
public class PagingLink
{
/// <summary>
/// Text
/// </summary>
public string Text { get; set; }
/// <summary>
/// Page
/// </summary>
public int Page { get; set; }
/// <summary>
/// Enabled
/// </summary>
public bool Enabled { get; set; }
/// <summary>
/// Active
/// </summary>
public bool Active { get; set; }
/// <summary>
/// The paging link
/// </summary>
/// <param name="page"></param>
/// <param name="enabled"></param>
/// <param name="text"></param>
public PagingLink(int page, bool enabled, string text)
{
Page = page;

View file

@ -18,8 +18,18 @@ using Wonky.Entity.Requests;
namespace Wonky.Client.Features;
/// <summary>
/// PagingResponse T class
/// </summary>
/// <typeparam name="T"></typeparam>
public class PagingResponse<T> where T : class
{
/// <summary>
/// Items
/// </summary>
public List<T>? Items { get; set; }
/// <summary>
/// Meta DAta
/// </summary>
public MetaData? MetaData { get; set; }
}

View file

@ -21,73 +21,99 @@ using Microsoft.AspNetCore.Components.Rendering;
namespace Wonky.Client.Helpers;
/// <summary>
/// InputDateTime Component
/// </summary>
/// <typeparam name="TValue"></typeparam>
public class InputDateTime<TValue> : InputDate<TValue>
{
private const string DateFormat = "yyyy-MM-ddTHH:mm";
/// <inheritdoc />
protected override void BuildRenderTree ( RenderTreeBuilder builder )
/// <summary>
/// BuildTender
/// </summary>
/// <param name="builder"></param>
protected override void BuildRenderTree(RenderTreeBuilder builder)
{
builder.OpenElement( 0, "input" );
builder.AddMultipleAttributes( 1, AdditionalAttributes );
builder.AddAttribute( 2, "type", "datetime-local" );
builder.AddAttribute( 3, "class", CssClass );
builder.AddAttribute( 4, "value", BindConverter.FormatValue( CurrentValueAsString ) );
builder.AddAttribute( 5, "onchange", EventCallback.Factory.CreateBinder<string>( this, __value => CurrentValueAsString = __value, CurrentValueAsString ) );
builder.OpenElement(0, "input");
builder.AddMultipleAttributes(1, AdditionalAttributes);
builder.AddAttribute(2, "type", "datetime-local");
builder.AddAttribute(3, "class", CssClass);
builder.AddAttribute(4, "value", BindConverter.FormatValue(CurrentValueAsString));
builder.AddAttribute(5, "onchange",
EventCallback.Factory.CreateBinder<string>(this, __value => CurrentValueAsString = __value,
CurrentValueAsString));
builder.CloseElement();
}
/// <inheritdoc />
protected override string FormatValueAsString ( TValue value )
/// <summary>
/// Format value as string
/// </summary>
/// <param name="value"></param>
/// <returns></returns>
protected override string FormatValueAsString(TValue value)
{
switch ( value )
return value switch
{
case DateTime dateTimeValue:
return BindConverter.FormatValue( dateTimeValue, DateFormat, CultureInfo.InvariantCulture );
case DateTimeOffset dateTimeOffsetValue:
return BindConverter.FormatValue( dateTimeOffsetValue, DateFormat, CultureInfo.InvariantCulture );
default:
return string.Empty; // Handles null for Nullable<DateTime>, etc.
}
DateTime dateTimeValue =>
BindConverter.FormatValue(dateTimeValue, DateFormat, CultureInfo.InvariantCulture),
DateTimeOffset dateTimeOffsetValue => BindConverter.FormatValue(dateTimeOffsetValue, DateFormat,
CultureInfo.InvariantCulture),
_ => string.Empty
};
}
/// <inheritdoc />
protected override bool TryParseValueFromString ( string value, out TValue result, out string validationErrorMessage )
/// <summary>
/// TryParseValueFromString
/// </summary>
/// <param name="value"></param>
/// <param name="result"></param>
/// <param name="validationErrorMessage"></param>
/// <returns></returns>
/// <exception cref="InvalidOperationException"></exception>
protected override bool TryParseValueFromString(string value, out TValue result, out string validationErrorMessage)
{
// Unwrap nullable types. We don't have to deal with receiving empty values for nullable
// types here, because the underlying InputBase already covers that.
var targetType = Nullable.GetUnderlyingType( typeof( TValue ) ) ?? typeof( TValue );
var targetType = Nullable.GetUnderlyingType(typeof(TValue)) ?? typeof(TValue);
bool success;
if ( targetType == typeof( DateTime ) )
if (targetType == typeof(DateTime))
{
success = TryParseDateTime( value, out result );
success = TryParseDateTime(value, out result);
}
else if ( targetType == typeof( DateTimeOffset ) )
else if (targetType == typeof(DateTimeOffset))
{
success = TryParseDateTimeOffset( value, out result );
success = TryParseDateTimeOffset(value, out result);
}
else
{
throw new InvalidOperationException( $"The type '{targetType}' is not a supported date type." );
throw new InvalidOperationException($"The type '{targetType}' is not a supported date type.");
}
if ( success )
if (success)
{
validationErrorMessage = null;
return true;
}
else
{
validationErrorMessage = string.Format( ParsingErrorMessage, FieldIdentifier.FieldName );
validationErrorMessage = string.Format(ParsingErrorMessage, FieldIdentifier.FieldName);
return false;
}
}
static bool TryParseDateTime ( string value, out TValue result )
/// <summary>
/// TrypParseDateTime
/// </summary>
/// <param name="value"></param>
/// <param name="result"></param>
/// <returns></returns>
private static bool TryParseDateTime(string value, out TValue result)
{
var success = BindConverter.TryConvertToDateTime( value, CultureInfo.InvariantCulture, DateFormat, out var parsedValue );
if ( success )
var success =
BindConverter.TryConvertToDateTime(value, CultureInfo.InvariantCulture, DateFormat, out var parsedValue);
if (success)
{
result = (TValue)(object)parsedValue;
return true;
@ -99,10 +125,18 @@ public class InputDateTime<TValue> : InputDate<TValue>
}
}
static bool TryParseDateTimeOffset ( string value, out TValue result )
/// <summary>
/// TryParseDateTimeOffset
/// </summary>
/// <param name="value"></param>
/// <param name="result"></param>
/// <returns></returns>
private static bool TryParseDateTimeOffset(string value, out TValue result)
{
var success = BindConverter.TryConvertToDateTimeOffset( value, CultureInfo.InvariantCulture, DateFormat, out var parsedValue );
if ( success )
var success =
BindConverter.TryConvertToDateTimeOffset(value, CultureInfo.InvariantCulture, DateFormat,
out var parsedValue);
if (success)
{
result = (TValue)(object)parsedValue;
return true;

View file

@ -28,36 +28,79 @@ using System.Diagnostics;
namespace Wonky.Client.Helpers
{
/// <summary>
/// Squid is guid string shortened and url safe
/// </summary>
[DebuggerDisplay("{" + nameof(Value) + "}")]
public readonly struct Squid : IEquatable<Squid>
{
{
/// <summary>
/// Return Empty value
/// </summary>
// ReSharper disable once MemberCanBePrivate.Global
public static readonly Squid Empty = new(Guid.Empty);
/// <summary>
/// Decode Squid to Guid
/// </summary>
/// <param name="value"></param>
public Squid(string value)
{
Value = value;
Guid = DecodeSquid(value);
}
/// <summary>
/// Generate Squid from Guid object
/// </summary>
/// <param name="obj"></param>
public Squid(Guid obj)
{
Value = EncodeGuid(obj);
Guid = obj;
}
#pragma warning disable CA1720 // Identifier contains type name
/// <summary>
/// Guid
/// </summary>
// ReSharper disable once MemberCanBePrivate.Global
public Guid Guid { get; }
#pragma warning restore CA1720 // Identifier contains type name
public string Value { get; }
/// <summary>
/// ToString() function
/// </summary>
/// <returns></returns>
public override string ToString()
{
return Value;
}
public override bool Equals(object obj)
/// <summary>
/// Equality
/// </summary>
/// <param name="obj"></param>
/// <returns></returns>
public override bool Equals(object? obj)
{
return obj is Squid other && Equals(other);
}
/// <summary>
/// EQuality
/// </summary>
/// <param name="obj"></param>
/// <returns></returns>
public bool Equals(Squid obj)
{
return Guid.Equals(obj.Guid) && Value == obj.Value;
}
/// <summary>
/// Get hashcode
/// </summary>
/// <returns></returns>
public override int GetHashCode()
{
unchecked
@ -65,15 +108,33 @@ namespace Wonky.Client.Helpers
return (Guid.GetHashCode() * 397) ^ (Value != null ? Value.GetHashCode() : 0);
}
}
/// <summary>
/// Create Squid from new Guid
/// </summary>
/// <returns></returns>
public static Squid NewGuid()
{
return new(Guid.NewGuid());
return new Squid(Guid.NewGuid());
}
/// <summary>
/// Encode string
/// </summary>
/// <param name="value"></param>
/// <returns></returns>
public static string EncodeString(string value)
{
var guid = new Guid(value);
return EncodeGuid(guid);
}
/// <summary>
/// Encode Guid
/// </summary>
/// <param name="obj"></param>
/// <returns></returns>
// ReSharper disable once MemberCanBePrivate.Global
public static string EncodeGuid(Guid obj)
{
var encoded = Convert.ToBase64String(obj.ToByteArray());
@ -82,25 +143,52 @@ namespace Wonky.Client.Helpers
.Replace("+", "-");
return encoded.Substring(0, 22);
}
/// <summary>
/// Decode Squid
/// </summary>
/// <param name="value"></param>
/// <returns></returns>
// ReSharper disable once MemberCanBePrivate.Global
public static Guid DecodeSquid(string value)
{
if (value == null) return Empty;
if (!value.Any()) return Empty;
value = value
.Replace("_", "/")
.Replace("-", "+");
var blob = Convert.FromBase64String(value + "==");
return new Guid(blob);
}
/// <summary>
/// Guid From Squid
/// </summary>
/// <param name="obj"></param>
/// <returns></returns>
public static Guid FromSquid(Squid obj)
{
return obj.Guid;
}
/// <summary>
/// Squid From String
/// </summary>
/// <param name="value"></param>
/// <returns></returns>
public static Squid FromString(string value)
{
if (string.IsNullOrEmpty(value))
return Empty;
return TryParse(value, out Squid obj) ? obj : Empty;
}
/// <summary>
/// TryDecode
/// </summary>
/// <param name="value"></param>
/// <param name="obj"></param>
/// <returns></returns>
// ReSharper disable once MemberCanBePrivate.Global
public static bool TryDecode(string value, out Guid obj)
{
try
@ -109,15 +197,21 @@ namespace Wonky.Client.Helpers
obj = DecodeSquid(value);
return true;
}
#pragma warning disable CA1031 // Do not catch general exception types
catch (Exception)
#pragma warning restore CA1031 // Do not catch general exception types
{
// Return empty Guid
obj = Guid.Empty;
return false;
}
}
/// <summary>
/// TryParse
/// </summary>
/// <param name="value"></param>
/// <param name="obj"></param>
/// <returns></returns>
// ReSharper disable once MemberCanBePrivate.Global
public static bool TryParse(string value, out Squid obj)
{
// Parse as Squid string.
@ -126,15 +220,24 @@ namespace Wonky.Client.Helpers
obj = oGuid;
return true;
}
// Parse as Guid string.
if (Guid.TryParse(value, out oGuid))
{
obj = oGuid;
return true;
}
obj = Empty;
return false;
}
/// <summary>
/// TryParse
/// </summary>
/// <param name="value"></param>
/// <param name="obj"></param>
/// <returns></returns>
public static bool TryParse(string value, out Guid obj)
{
// Try a Squid string.
@ -146,38 +249,98 @@ namespace Wonky.Client.Helpers
obj = Guid.Empty;
return false;
}
/// <summary>
/// Operator
/// </summary>
/// <param name="x"></param>
/// <param name="y"></param>
/// <returns></returns>
public static bool operator ==(Squid x, Squid y)
{
return x.Guid == y.Guid;
}
/// <summary>
/// Operator
/// </summary>
/// <param name="x"></param>
/// <param name="y"></param>
/// <returns></returns>
public static bool operator ==(Squid x, Guid y)
{
return x.Guid == y;
}
/// <summary>
/// Operator
/// </summary>
/// <param name="x"></param>
/// <param name="y"></param>
/// <returns></returns>
public static bool operator ==(Guid x, Squid y)
{
return y == x; // NB: order of arguments
}
/// <summary>
/// Operator
/// </summary>
/// <param name="x"></param>
/// <param name="y"></param>
/// <returns></returns>
public static bool operator !=(Squid x, Squid y)
{
return !(x == y);
}
/// <summary>
/// Operator
/// </summary>
/// <param name="x"></param>
/// <param name="y"></param>
/// <returns></returns>
public static bool operator !=(Squid x, Guid y)
{
return !(x == y);
}
/// <summary>
/// Operator
/// </summary>
/// <param name="x"></param>
/// <param name="y"></param>
/// <returns></returns>
public static bool operator !=(Guid x, Squid y)
{
return !(x == y);
}
/// <summary>
/// Operator
/// </summary>
/// <param name="oSquid"></param>
/// <returns></returns>
public static implicit operator string(Squid oSquid)
{
return oSquid.Value;
}
/// <summary>
/// Operator
/// </summary>
/// <param name="oSquid"></param>
/// <returns></returns>
public static implicit operator Guid(Squid oSquid)
{
return oSquid.Guid;
}
/// <summary>
/// Operator
/// </summary>
/// <param name="value"></param>
/// <returns></returns>
public static implicit operator Squid(string value)
{
if (string.IsNullOrEmpty(value))
@ -185,6 +348,12 @@ namespace Wonky.Client.Helpers
return TryParse(value, out Squid oSquid) ? oSquid : Empty;
}
/// <summary>
/// Operator
/// </summary>
/// <param name="oGuid"></param>
/// <returns></returns>
public static implicit operator Squid(Guid oGuid)
{
return oGuid == Guid.Empty ? Empty : new Squid(oGuid);

View file

@ -17,7 +17,13 @@ namespace Wonky.Client.Helpers;
public static class StringExtensions
{
public static string Left(this string value, int maxLength)
/// <summary>
/// Left Pad a string with spaces until maxlength
/// </summary>
/// <param name="value"></param>
/// <param name="maxLength"></param>
/// <returns></returns>
public static string PadLeft(this string value, int maxLength)
{
if (string.IsNullOrEmpty(value)) return value;
maxLength = Math.Abs(maxLength);

View file

@ -18,63 +18,125 @@ using System.Net.Mail;
using Wonky.Entity.DTO;
namespace Wonky.Client.Helpers;
/// <summary>
/// Utilities
/// </summary>
public static class Utils
{
/// <summary>
/// return Country Name from countryCode
/// </summary>
/// <param name="countryCode"></param>
/// <returns></returns>
public static string CountryName(string countryCode)
{
return countryCode.ToLower() switch
{
"dk" => "Danmark",
"no" => "Norge",
"se" => "Sverige",
_ => ""
};
}
/// <summary>
/// Helper to parse querystring
/// </summary>
/// <param name="query"></param>
/// <returns></returns>
public static Dictionary<string, string> ParseQuery(string query)
{
if (string.IsNullOrWhiteSpace(query) || query.Contains("://"))
return new Dictionary<string, string>();
// remove the question mark
query = query.Replace("?", "");
// split into pairs
var elements = query.Split("&");
// return elements as list
return elements.Select(
data
=> data.Split("="))
data
=> data.Split("="))
.ToDictionary(element => element[0], element => element[1]);
}
/// <summary>
/// Validate email format
/// </summary>
/// <param name="email"></param>
/// <returns></returns>
public static bool IsValidEmail(string email)
{
var trimmedEmail = email.Trim();
if (trimmedEmail.EndsWith(".")) {
if (trimmedEmail.EndsWith("."))
{
return false; // suggested by @TK-421
}
try {
try
{
var addr = new MailAddress(email);
return addr.Address == trimmedEmail;
}
catch {
catch
{
return false;
}
}
/// <summary>
/// return enum as the string value
/// </summary>
/// <param name="value"></param>
/// <returns></returns>
public static string EnumToString(Enum value)
{
return value.ToString();
}
/// <summary>
/// Parse string to enum of T
/// </summary>
/// <param name="value"></param>
/// <typeparam name="T"></typeparam>
/// <returns></returns>
public static T StringToEnum<T>(string value)
{
return (T)Enum.Parse(typeof(T), value, true);
}
/// <summary>
/// Generate unique hashcode from time
/// </summary>
/// <returns></returns>
public static int GetHashFromNow()
{
return DateTime.Now.ToFileTimeUtc().GetHashCode();
}
/// <summary>
/// Get visit state as colored icon
/// </summary>
/// <param name="dtNextVisit"></param>
/// <returns></returns>
public static string GetVisitState(string dtNextVisit)
{
if (dtNextVisit is "0001-01-01" or "1970-01-01")
return "the-draw";
if (!DateTime.TryParse(dtNextVisit, out _))
return "the-draw";
var dtNow = DateTime.Now;
var dtNext = DateTime.Parse(dtNextVisit);
if (dtNow > dtNext)
return "the-ugly";
return dtNow > dtNext.AddDays(-14) ? "the-bad" : "the-good";
}
/// <summary>
/// Translate process status to icon
/// </summary>
/// <param name="processStatus"></param>
/// <returns></returns>
public static string GetProcessStatus(string processStatus)
{
return processStatus.ToLower() switch
@ -84,7 +146,8 @@ public static class Utils
"picked" => "the-bad",
"packed" => "the-ugly",
"shipped" => "the-dead",
_ => "question-square"
"accepted" => "accepted",
_ => "question"
};
}
}
}

View file

@ -14,6 +14,9 @@
//
using System.Globalization;
using System.Reflection.Metadata.Ecma335;
using System.Runtime.CompilerServices;
using System.Text.RegularExpressions;
namespace Wonky.Client.Helpers;
@ -21,10 +24,15 @@ public class VatUtils
{
// https://ec.europa.eu/taxation_customs/vies/faqvies.do#item_11
// https://ec.europa.eu/taxation_customs/vies/
/// <summary>
/// Entrypoint for validating vat number
/// </summary>
/// <param name="countryCode"></param>
/// <param name="vatNumber"></param>
/// <returns></returns>
public static bool ValidateFormat(string countryCode, string vatNumber)
{
if (string.IsNullOrWhiteSpace(vatNumber) || string.IsNullOrWhiteSpace(countryCode) || !IsDigitsOnly(vatNumber))
if (string.IsNullOrWhiteSpace(vatNumber) || string.IsNullOrWhiteSpace(countryCode))
return false;
var sanitisedVat = SanitizeVatNumber(vatNumber);
@ -38,10 +46,34 @@ public class VatUtils
};
}
/// <summary>
/// Sanitize Vat remove everything but digits
/// </summary>
/// <param name="vatNumber"></param>
/// <returns></returns>
public static string SanitizeVatNumber(string vatNumber)
{
if (string.IsNullOrWhiteSpace(vatNumber))
return "";
var regexObj = new Regex(@"[^\d]");
return regexObj.Replace(vatNumber, "");
}
/// <summary>
/// Validate string is only numbers
/// </summary>
/// <param name="check"></param>
/// <returns></returns>
private static bool IsDigitsOnly(string check)
{
return check.All(c => c is >= '0' and <= '9');
}
/// <summary>
/// Validate Danish Vat number format
/// </summary>
/// <param name="vatNumber"></param>
/// <returns></returns>
private static bool ValidateFormatDk(string vatNumber)
{
// https://wiki.scn.sap.com/wiki/display/CRM/Denmark
@ -57,6 +89,11 @@ public class VatUtils
return ValidateMod11(vatNumber);
}
/// <summary>
/// Validate Norwegian Vat number format
/// </summary>
/// <param name="vatNumber"></param>
/// <returns></returns>
private static bool ValidateFormatNo(string vatNumber)
{
// https://wiki.scn.sap.com/wiki/display/CRM/Norway
@ -69,7 +106,40 @@ public class VatUtils
return long.Parse(vatNumber) != 0 && ValidateMod11(vatNumber);
}
/// <summary>
/// Validate Swedish Vat number format
/// </summary>
/// <param name="vatNumber"></param>
/// <returns></returns>
private static bool ValidateFormatSe(string vatNumber)
{
var vatToCheck = vatNumber;
if (long.Parse(vatToCheck) == 0)
return false;
switch (vatToCheck.Length)
{
// if less than 10 chars validate as SSI
case 6:
return ValidateFormatSeExt(vatToCheck);
case < 10:
return false;
case > 10:
vatNumber = vatNumber[..10];
break;
}
// calculate check digit
var c10 = C10(vatToCheck);
// return comparison
return $"{vatToCheck[..9]}{c10}" == vatNumber;
}
/// <summary>
/// Calculate check digit for swedish org number
/// </summary>
/// <param name="orgNumber"></param>
/// <returns></returns>
private static int C10(string orgNumber)
{
// https://wiki.scn.sap.com/wiki/display/CRM/Sweden
// 12 digits 0 to 9
@ -78,22 +148,62 @@ public class VatUtils
// Si = int(Ci/5) + (Ci*2)MOD10)
// https://www.skatteverket.se/skatter/mervardesskattmoms/momsregistreringsnummer.4.18e1b10334ebe8bc80002649.html
// C11 C12 == 01 (De två sista siffrorna är alltid 01)
var vatToCheck = vatNumber;
if (vatToCheck.Length < 10 || long.Parse(vatToCheck) == 0)
return false;
var r = new[] { 0, 2, 4, 6, 8 }
.Sum(m => (int)char.GetNumericValue(vatToCheck[m]) / 5 +
(int)char.GetNumericValue(vatToCheck[m]) * 2 % 10);
var c1 = new[] { 1, 3, 5, 7 }.Sum(m => (int)char.GetNumericValue(vatToCheck[m]));
var c10 = (10 - (r + c1) % 10) % 10;
if (vatToCheck.Length == 10)
.Sum(m => (int)char.GetNumericValue(orgNumber[m]) / 5 +
(int)char.GetNumericValue(orgNumber[m]) * 2 % 10);
var c1 = new[] { 1, 3, 5, 7 }.Sum(m => (int)char.GetNumericValue(orgNumber[m]));
var c10 = (10 - (r + c1) % 10) % 10;
return c10;
// end check digit calculation
}
/// <summary>
///
/// </summary>
/// <param name="data"></param>
/// <returns></returns>
private static bool ValidateFormatSeExt(string data)
{
// Swedish personally held companies uses SSN number
// a relaxed validation is required as only first 6 digits is supplied
// birthday format e.g. 991231 yyMMdd
var y = int.Parse(data[..2]);
var m = int.Parse(data[2..4]);
var d = int.Parse(data[4..6]);
// this calculation is only valid within 21st century
var leap = y % 4 == 0; // 2000 was a leap year;
// day
if(d is < 1 or > 31)
return false;
// month
switch (m)
{
return $"{vatToCheck[..9]}{c10}" == vatNumber;
// feb
case 2:
{
if (leap)
return d <= 29;
return d <= 28;
}
// apr, jun, sep, nov
case 4 or 6 or 9 or 11:
return d <= 30;
// jan, mar, may, july, aug, oct, dec
case 1 or 3 or 5 or 7 or 8 or 10 or 12:
return true;
// does not exist
default:
return false;
}
return $"{vatToCheck[..9]}{c10}01" == vatNumber;
}
/// <summary>
/// Modulus11 validator
/// </summary>
/// <param name="number"></param>
/// <returns></returns>
private static bool ValidateMod11(string number)
{
if (long.Parse(number) == 0)
@ -107,15 +217,4 @@ public class VatUtils
return sum % 11 == 0;
}
private static string SanitizeVatNumber(string vatNumber)
{
return vatNumber.ToUpperInvariant()
.Replace(" ", "")
.Replace("-", "")
.Replace("DK", "")
.Replace("NO", "")
.Replace("SE","")
.Replace("MVA", "");
}
}

View file

@ -15,6 +15,7 @@
using System.Net;
using System.Net.Http.Headers;
using System.Text.Json;
using System.Threading.Tasks;
using Blazored.LocalStorage;
using Blazored.Toast.Services;
@ -31,9 +32,9 @@ namespace Wonky.Client.HttpInterceptors
private readonly NavigationManager _navigation;
private readonly IToastService _toast;
private readonly RefreshTokenService _refreshTokenService;
private ILogger<HttpInterceptorService> _logger;
private readonly ILogger<HttpInterceptorService> _logger;
private readonly ILocalStorageService _storage;
private IAuthenticationService _authenticationService;
private readonly IAuthenticationService _authenticationService;
public HttpInterceptorService(HttpClientInterceptor interceptor,
NavigationManager navigation, IToastService toast,
@ -56,18 +57,18 @@ namespace Wonky.Client.HttpInterceptors
public void RegisterBeforeSendEvent()
{
_interceptor.BeforeSendAsync += InterceptBeforeSendAsync;
_interceptor.BeforeSendAsync += InterceptBeforeSend;
}
public void DisposeEvent()
{
_interceptor.AfterSend -= AfterSend;
_interceptor.BeforeSendAsync -= InterceptBeforeSendAsync;
_interceptor.BeforeSendAsync -= InterceptBeforeSend;
}
private async Task InterceptBeforeSendAsync(object sender, HttpClientInterceptorEventArgs e)
private async Task InterceptBeforeSend(object sender, HttpClientInterceptorEventArgs e)
{
var absolutePath = e.Request.RequestUri.AbsolutePath;
if (!absolutePath.Contains("token"))
{
// call TryRefreshToken
@ -86,35 +87,37 @@ namespace Wonky.Client.HttpInterceptors
if (e.Response == null || e.Response.IsSuccessStatusCode)
return;
var message = "En ukendt fejl er opstået";
var message = $"En fejl er opstået \n {JsonSerializer.Serialize(e)}";
var currDoc = _navigation.ToBaseRelativePath(_navigation.Uri);
if (currDoc.Contains("login/"))
currDoc = "";
switch (e.Response.StatusCode)
{
case HttpStatusCode.NotFound:
// message = "Der var ingen data ...";
// _toast.ShowInfo(message);
case HttpStatusCode.NotFound:
_logger.LogDebug("NotFound <= {}", currDoc);
break;
case HttpStatusCode.BadRequest:
// message = "Der er et problem med data ...";
// _toast.ShowWarning(message);
_logger.LogDebug("BadRequest <= {}", currDoc);
_logger.LogDebug("{}", message);
break;
case HttpStatusCode.Unauthorized:
_logger.LogDebug("Unauthorized <= {}", currDoc);
_logger.LogDebug("{}", message);
_authenticationService.Logout();
_navigation.NavigateTo($"/login/{currDoc}");
message = "Venligst login ...";
_toast.ShowInfo(message);
_toast.ShowInfo("Venligst Login. Tak.");
break;
case HttpStatusCode.Conflict:
_logger.LogDebug("Conflict <= {}", currDoc);
_logger.LogDebug("{}", message);
break;
case HttpStatusCode.InternalServerError:
// message = "Der er interne problemer på serveren ...";
// _toast.ShowError(message);
_logger.LogDebug("InternalServerError <= {}", currDoc);
_logger.LogDebug("{}", message);
break;
default:
_toast.ShowError(message);
_logger.LogDebug("{}", message);
break;
}
// throw new HttpResponseException(message);

View file

@ -18,7 +18,10 @@ using Wonky.Entity.Views;
namespace Wonky.Client.HttpInterfaces;
public interface ICrmActivityHttpRepository
/// <summary>
/// Interface Activity CRM Http repository
/// </summary>
public interface IAdvisorActivityRepository
{
/// <summary>
/// Get a list of open quotes
@ -33,13 +36,6 @@ public interface ICrmActivityHttpRepository
/// <returns></returns>
Task<ApiResponseView> UpdateQuoteStatus(ReportItemView activity);
/// <summary>
/// Get activities by date
/// </summary>
/// <param name="activityDate"></param>
/// <returns></returns>
Task<ReportStatusView> GetActivities(string activityDate);
/// <summary>
/// Create new activity
/// </summary>
@ -47,12 +43,26 @@ public interface ICrmActivityHttpRepository
/// <returns></returns>
Task<ApiResponseView> CreateActivity(ActivityDto model);
/// <summary>
/// Get activities by date
/// </summary>
/// <param name="activityDate"></param>
/// <returns></returns>
Task<ReportStatusView> GetActivities(string activityDate);
/// <summary>
/// Get activity data by id
/// </summary>
/// <param name="activityId"></param>
/// <returns></returns>
Task<ActivityDto> GetActivity(string activityId);
/// <summary>
/// Get activities for customer Id
/// </summary>
/// <param name="customerId"></param>
/// <returns></returns>
Task<List<ReportItemView>> GetCustomerActivities(string customerId);
/// <summary>
/// Get activity by id formatted for report
@ -61,20 +71,13 @@ public interface ICrmActivityHttpRepository
/// <returns></returns>
Task<ReportItemView> GetReportItem(string activityId);
/// <summary>
/// Get activities for customer Id
/// </summary>
/// <param name="customerId"></param>
/// <returns></returns>
Task<List<ReportItemView>> GetCustomerActivities(string customerId);
/// <summary>
/// Set backend process state to express
/// </summary>
/// <param name="activityId"></param>
/// <returns>ApiResponseView</returns>
Task<ApiResponseView> GetExpressState(string activityId);
/// <summary>
/// Update office note for activity
/// </summary>

View file

@ -0,0 +1,47 @@
using Wonky.Entity.DTO;
namespace Wonky.Client.HttpInterfaces;
/// <summary>
/// Interface for Contacts CRM Http repository
/// </summary>
/// <returns></returns>
public interface IAdvisorContactRepository
{
/// <summary>
/// Create Contact
/// </summary>
/// <param name="model"></param>
/// <returns></returns>
Task<string> CreateContact(ContactDto model);
/// <summary>
/// Get Contact
/// </summary>
/// <param name="companyId"></param>
/// <param name="contactId"></param>
/// <returns></returns>
Task<ContactDto> GetContact(string companyId, string contactId);
/// <summary>
/// Get Contacts
/// </summary>
/// <param name="companyId"></param>
/// <returns></returns>
Task<List<ContactDto>> GetContacts(string companyId);
/// <summary>
/// Delete Contact
/// </summary>
/// <param name="companyId"></param>
/// <param name="contactId"></param>
/// <returns></returns>
Task DeleteContact(string companyId, string contactId);
/// <summary>
/// Update Contact
/// </summary>
/// <param name="model"></param>
/// <returns></returns>
Task UpdateContact(ContactDto model);
}

View file

@ -0,0 +1,70 @@
// 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.Entity.Views;
namespace Wonky.Client.HttpInterfaces;
/// <summary>
/// Interface Customer History CRM Http repository
/// </summary>
public interface IAdvisorCustomerHistoryRepository
{
/// <summary>
/// Fetch Invoice LIst
/// </summary>
/// <param name="companyId"></param>
/// <returns></returns>
Task<InvoiceListView> FetchInvoiceList(string companyId);
/// <summary>
/// Fetch given invoice for given customer
/// </summary>
/// <param name="companyId"></param>
/// <param name="invoiceId"></param>
/// <returns></returns>
Task<InvoiceView> FetchInvoice(string companyId, string invoiceId);
/// <summary>
/// Fetch inventory from given customer
/// </summary>
/// <param name="companyId"></param>
/// <returns></returns>
Task<List<ProductInventoryView>> FetchInventory(string companyId);
/// <summary>
/// Fetch History for given customer
/// </summary>
/// <param name="companyId"></param>
/// <returns></returns>
Task<List<ProductHistoryView>> FetchHistory(string companyId);
/// <summary>
/// Fetch history for given customer and a given product
/// </summary>
/// <param name="companyId"></param>
/// <param name="sku"></param>
/// <returns></returns>
Task<List<ProductHistoryView>> FetchHistory(string companyId, string sku);
/// <summary>
/// RPC call to initiate remote server sync for given customer
/// </summary>
/// <param name="companyId"></param>
/// <param name="syncDate"></param>
/// <returns></returns>
Task<string> InvoiceErpToCrmRpc(string companyId, string syncDate);
}

View file

@ -19,48 +19,57 @@ using Wonky.Entity.Requests;
namespace Wonky.Client.HttpInterfaces;
public interface ICrmCompanyHttpRepository
/// <summary>
/// Interface Customer CRM Http repository
/// </summary>
public interface IAdvisorCustomerRepository
{
/// <summary>
/// Get a list of CRM entities
/// Get a list of CRM customers (SalesRep)
/// </summary>
/// <param name="pagingParameters"></param>
/// <returns>A paged response defined by pagingParameters</returns>
Task<PagingResponse<CompanyDto>> GetCompanies(CompanyPagingParams pagingParameters);
Task<PagingResponse<CompanyDto>> GetCompanies(CustomerPaging pagingParameters);
/// <summary>
/// Get CRM entity by Id
/// Get CRM customer by Id (SalesRep)
/// </summary>
/// <param name="companyId"></param>
/// <returns>A CRM Company entity</returns>
Task<CompanyDto> GetCompanyById(string companyId);
/// <summary>
/// Create new CRM entity
/// Create Customer (SalesRep)
/// </summary>
/// <param name="model"></param>
/// <returns>The Id of the entity</returns>
Task<string> CreateCompany(CompanyDto model);
/// <summary>
/// Delete the CRM entity
/// Delete the CRM customer (SalesRep)
/// </summary>
/// <param name="companyId"></param>
/// <returns>true/false to define success</returns>
Task<bool> DeleteCompany(string companyId);
/// <summary>
/// Update CRM entity properties
/// Update CRM customer properties (SalesRep)
/// </summary>
/// <param name="companyId"></param>
/// <param name="model"></param>
/// <returns>A CRM Company entity</returns>
Task<CompanyDto> UpdateCrmData(string companyId, CompanyDto model);
/// <summary>
/// Update ERP entity properties
/// Update ERP customer properties (SalesRep)
/// </summary>
/// <param name="companyId"></param>
/// <param name="model"></param>
/// <returns>A CRM Company entity</returns>
Task<CompanyDto> UpdateErpData(string companyId, CompanyDto model);
/// <summary>
/// Update Entity Vat Number
/// Update customer Vat Number (SalesRep)
/// </summary>
/// <param name="companyId"></param>
/// <param name="vatNumber"></param>

View file

@ -18,11 +18,43 @@ using Wonky.Entity.Views;
namespace Wonky.Client.HttpInterfaces;
public interface ICrmReportHttpRepository
/// <summary>
/// Interface Report Http repository
/// </summary>
public interface IAdvisorReportRepository
{
/// <summary>
/// Report Exist for given data (SalesRep)
/// </summary>
/// <param name="workDate"></param>
/// <returns></returns>
Task<bool> ReportExist(string workDate);
/// <summary>
/// Get Reports for (SalesRep)
/// </summary>
/// <returns></returns>
Task<List<SalesReportListView>> GetReports();
/// <summary>
/// Get Report for given date (SalesRep)
/// </summary>
/// <param name="workDate"></param>
/// <returns></returns>
Task<ReportView> GetReport(string workDate);
/// <summary>
/// Initialize Report for given data (SalesRep)
/// </summary>
/// <param name="workDate"></param>
/// <returns></returns>
Task<ReportInitDto> InitializeReportData(string workDate);
Task<ApiResponseView> PostReport(string workDate, ReportDto reportDto);
/// <summary>
/// Create Report for given data - using reportData
/// </summary>
/// <param name="workDate"></param>
/// <param name="reportDto"></param>
/// <returns></returns>
Task<ApiResponseView> CreateReport(string workDate, ReportDto reportDto);
}

View file

@ -0,0 +1,66 @@
// 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.Entity.DTO;
namespace Wonky.Client.HttpInterfaces;
/// <summary>
/// Interface for handling CRM Tasks http repository
/// </summary>
public interface IAdvisorTaskItemRepository
{
/// <summary>
/// Get Task List (SalesRep)
/// </summary>
/// <returns></returns>
Task<List<TaskItemDto>> GetTaskList();
/// <summary>
/// Get Task List for given workDate (SalesRep)
/// </summary>
/// <param name="workDate"></param>
/// <returns></returns>
Task<List<TaskItemDto>> GetTaskList(string workDate);
/// <summary>
/// Get Task Item by id (SalesRep)
/// </summary>
/// <param name="taskItemId"></param>
/// <returns></returns>
Task<TaskItemDto> GetTaskItem(string taskItemId);
/// <summary>
/// Create task using taskItem (SalesRep)
/// </summary>
/// <param name="taskItem"></param>
/// <returns></returns>
Task CreateTaskItem(TaskItemDto taskItem);
/// <summary>
/// Delete Task Item (SalesRep
/// </summary>
/// <param name="taskItemId"></param>
/// <returns></returns>
Task UpdateTaskItem(string taskItemId, TaskItemDto taskItem);
/// <summary>
/// Delete Task Item (SalesRep
/// </summary>
/// <param name="taskItemId"></param>
/// <returns></returns>
Task DeleteTaskItem(string taskItemId);
}

View file

@ -18,11 +18,47 @@ using Wonky.Entity.Views;
namespace Wonky.Client.HttpInterfaces;
public interface ICrmWorkplaceHttpRepository
/// <summary>
/// Interface for handling Customer Workplaces (chemical document service)
/// </summary>
public interface IAdvisorWorkplaceRepository
{
/// <summary>
/// Get Workplaces for given customer id
/// </summary>
/// <param name="companyId"></param>
/// <returns></returns>
Task<List<WorkplaceListView>> GetWorkplaces(string companyId);
/// <summary>
/// Get specific workplace using customer id and workplace id
/// </summary>
/// <param name="companyId"></param>
/// <param name="workplaceId"></param>
/// <returns></returns>
Task<WorkplaceDto> GetWorkplace(string companyId, string workplaceId);
/// <summary>
/// Create new workplace given the customer id and workplace data
/// </summary>
/// <param name="companyId"></param>
/// <param name="workplace"></param>
/// <returns></returns>
Task CreateWorkplace(string companyId, WorkplaceDto workplace);
/// <summary>
/// Update workplace given the customer id and updated data
/// </summary>
/// <param name="companyId"></param>
/// <param name="workplace"></param>
/// <returns></returns>
Task UpdateWorkplace(string companyId, WorkplaceDto workplace);
/// <summary>
/// Delete workplace given customer id and workplace id
/// </summary>
/// <param name="companyId"></param>
/// <param name="workplaceId"></param>
/// <returns></returns>
Task DeleteWorkplace(string companyId, string workplaceId);
}

View file

@ -1,12 +0,0 @@
using Wonky.Entity.DTO;
namespace Wonky.Client.HttpInterfaces;
public interface ICrmContactHttpRepository
{
Task<string> CreateContact(ContactDto model);
Task<ContactDto> GetContact(string companyId, string contactId);
Task<List<ContactDto>> GetContacts(string companyId);
Task DeleteContact(string companyId, string contactId);
Task UpdateContact(ContactDto model);
}

View file

@ -1,29 +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.Entity.Views;
namespace Wonky.Client.HttpInterfaces;
public interface ICrmHistoryHttpRepository
{
Task<InvoiceListView> FetchInvoiceList(string companyId);
Task<InvoiceView> FetchInvoice(string companyId, string invoiceId);
Task<List<ProductInventoryView>> FetchInventory(string companyId);
Task<List<ProductHistoryView>> FetchHistory(string companyId);
Task<List<ProductHistoryView>> FetchHistory(string companyId, string sku);
Task<string> ErpInvoiceToCrmRpc(string companyId, string syncDate);
}

View file

@ -1,29 +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.Entity.DTO;
namespace Wonky.Client.HttpInterfaces;
public interface ICrmTaskItemHttpRepository
{
Task<List<TaskItemDto>?> GetTaskList();
Task<List<TaskItemDto>?> GetTaskList(string workDate);
Task<TaskItemDto?> GetTaskItem(string taskItemId);
Task CreateTaskItem(TaskItemDto taskItem);
Task UpdateTaskItem(string taskItemId, TaskItemDto taskItem);
Task DeleteTaskItem(string taskItemId);
}

View file

@ -19,43 +19,47 @@ using Wonky.Entity.Views;
namespace Wonky.Client.HttpInterfaces;
public interface ICatalogHttpRepository
/// <summary>
/// Interface Catalog Http repository
/// </summary>
public interface ICountryCatalogRepository
{
/// <summary>
/// Get a paged sales item list
/// </summary>
/// <param name="pagingParameters"></param>
/// <param name="countryCode"></param>
/// <param name="pager"></param>
/// <returns></returns>
Task<PagingResponse<SalesItemView>> GetSalesItemsPaged(CatalogPagingParams pagingParameters);
Task<PagingResponse<SalesItemView>> GetSalesItemsPaged(string countryCode, CatalogPager pager);
/// <summary>
/// Get sales item by id
/// </summary>
/// <param name="countryCode"></param>
/// <param name="salesItemId"></param>
/// <returns></returns>
Task<SalesItemView> GetSalesItemId(string salesItemId);
Task<SalesItemView> GetSalesItemId(string countryCode, string salesItemId);
/// <summary>
/// Get sales item by sku
/// </summary>
/// <param name="sku"></param>
/// <returns></returns>
Task<SalesItemView> GetSalesItemSku(string sku);
/// <summary>
/// Overload Get sales item by id and country code
/// Overload Get sales item by sku and country code
/// </summary>
/// <param name="sku"></param>
/// <param name="countryCode"></param>
/// <returns></returns>
Task<SalesItemView> GetSalesItemSku(string sku, string countryCode);
Task<SalesItemView> GetSalesItemSku(string countryCode, string sku);
/// <summary>
/// Get sales item by variant id
/// </summary>
/// <param name="countryCode"></param>
/// <param name="variantId"></param>
/// <returns></returns>
Task<SalesItemView> GetSalesVariantId(string variantId);
Task<List<SalesItemView>> GetPriceList();
Task<SalesItemView> GetSalesVariantId(string countryCode, string variantId);
/// <summary>
/// Complete catalog for print country
/// </summary>
/// <param name="countryCode"></param>
/// <returns></returns>
Task<List<SalesItemView>> GetPriceList(string countryCode);
}

Some files were not shown because too many files have changed in this diff Show more