Merge branch 'dev-v6'
This commit is contained in:
commit
975dc7bf4c
78 changed files with 1313 additions and 656 deletions
|
@ -15,9 +15,9 @@
|
||||||
//
|
//
|
||||||
*@
|
*@
|
||||||
|
|
||||||
<select class="form-select bg-primary text-bg-primary" @bind-value="GroupCol" @bind-value:event="oninput" @onchange="OnSelectionChanged">
|
<select class="form-select bg-danger text-bg-danger" @bind-value="GroupCol" @bind-value:event="oninput" @onchange="OnSelectionChanged">
|
||||||
<option value="-1" disabled>VARE GRUPPE</option>
|
<option value="-1" disabled>VARE GRUPPE</option>
|
||||||
<option value="0" selected>Alle</option>
|
<option value="0" selected>Alle Grupper</option>
|
||||||
<option value="1">Lim Sealer Reparation</option>
|
<option value="1">Lim Sealer Reparation</option>
|
||||||
<option value="2">Grunder Maling</option>
|
<option value="2">Grunder Maling</option>
|
||||||
<option value="3">Smøremidler</option>
|
<option value="3">Smøremidler</option>
|
||||||
|
|
|
@ -15,9 +15,9 @@
|
||||||
//
|
//
|
||||||
*@
|
*@
|
||||||
|
|
||||||
<select class="form-select bg-primary text-bg-primary" @bind-value="@SearchCol" @bind-value:event="oninput" @onchange="OnSelectChanged">
|
<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="-1" selected disabled>SØGNING</option>
|
||||||
<option value="name">Navn</option>
|
<option value="name">Søg Navn</option>
|
||||||
<option value="sku">Nummer</option>
|
<option value="sku">Søg Nummer</option>
|
||||||
<option value="shortName">Forkort.</option>
|
<option value="shortName">Søg Forkort.</option>
|
||||||
</select>
|
</select>
|
|
@ -15,7 +15,7 @@
|
||||||
//
|
//
|
||||||
*@
|
*@
|
||||||
|
|
||||||
<select class="form-select bg-primary text-bg-primary" @bind-value="@SortCol" @bind-value:event="oninput" @onchange="OnSelectChanged">
|
<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="-1" selected disabled>SORTERING</option>
|
||||||
<option value="name">Navn</option>
|
<option value="name">Navn</option>
|
||||||
<option value="sku">Nummer</option>
|
<option value="sku">Nummer</option>
|
||||||
|
|
|
@ -15,11 +15,11 @@
|
||||||
//
|
//
|
||||||
*@
|
*@
|
||||||
|
|
||||||
<select class="form-select bg-primary text-bg-primary" @bind-value="@SearchCol" @bind-value:event="oninput" @onchange="OnSelectionChanged">
|
<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="-1" disabled>SØGNING</option>
|
||||||
<option value="name">Navn</option>
|
<option value="name">Søg Navn</option>
|
||||||
<option value="city">By</option>
|
<option value="city">Søg By</option>
|
||||||
<option value="zip">Postnr</option>
|
<option value="zip">Søg Post</option>
|
||||||
<option value="account">Konto</option>
|
<option value="account">Søg Konto</option>
|
||||||
<option value="phone">Telefon</option>
|
<option value="phone">Søg Tlf.</option>
|
||||||
</select>
|
</select>
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
//
|
//
|
||||||
*@
|
*@
|
||||||
|
|
||||||
<select class="form-select bg-primary text-bg-primary" @bind-value="@SortCol" @bind-value:event="oninput" @onchange="OnSelectionChanged">
|
<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="-1" selected disabled>SORTERING</option>
|
||||||
<option value="name">Navn</option>
|
<option value="name">Navn</option>
|
||||||
<option value="city">By</option>
|
<option value="city">By</option>
|
||||||
|
|
|
@ -0,0 +1,73 @@
|
||||||
|
@using Wonky.Client.Models
|
||||||
|
@using System.ComponentModel.Design
|
||||||
|
@*
|
||||||
|
// 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="row">
|
||||||
|
|
||||||
|
@if (ProductList.Any())
|
||||||
|
{
|
||||||
|
<div class="list-group mt-2">
|
||||||
|
<div class="list-group-item bg-dark text-white">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-sm-4" style="cursor: pointer;" @onclick="() => SortProducts(PSort.Desc)"><i class="bi-sort-alpha-down"></i> Navn <i class="bi-sort-alpha-up-alt"></i></div>
|
||||||
|
<div class="col-sm-3" style="cursor: pointer;" @onclick="() => SortProducts(PSort.Sku)"><i class="bi-sort-alpha-down"></i> Varenr <i class="bi-sort-alpha-up-alt"></i></div>
|
||||||
|
<div class="col-sm-2 text-center" style="cursor: pointer;" @onclick="() => SortProducts(PSort.Qty)"><i class="bi-sort-numeric-down"></i> Antal <i class="bi-sort-numeric-up-alt"></i></div>
|
||||||
|
<div class="col-sm-2"></div>
|
||||||
|
<div class="col-sm-1"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
@foreach (var product in ProductList)
|
||||||
|
{
|
||||||
|
<div class="list-group-item">
|
||||||
|
<div class="row align-items-center">
|
||||||
|
<div class="col-sm-4">
|
||||||
|
@product.Description
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-3">
|
||||||
|
@product.Sku
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-2 text-center">
|
||||||
|
@product.Quantity
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-2">
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-1" @onclick="() => ProductCheck(product.Sku)">
|
||||||
|
<input type="checkbox" class="btn-check" id="btn-@product.Sku.Replace(",", "")" autocomplete="off"/>
|
||||||
|
@if (product.Check)
|
||||||
|
{
|
||||||
|
<label class="btn btn-success" for="btn-@product.Sku.Replace(",", "")">
|
||||||
|
<i class="bi-check"></i>
|
||||||
|
</label>
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
<label class="btn btn-warning" for="btn-@product.Sku.Replace(",", "")">
|
||||||
|
<i class="bi-dash"></i>
|
||||||
|
</label>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
<div>Ingen data</div>
|
||||||
|
}
|
||||||
|
</div>
|
|
@ -0,0 +1,80 @@
|
||||||
|
// 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 CustomerProductCheckListComponent
|
||||||
|
{
|
||||||
|
[Parameter] public List<ProductInventoryView> ProductList { get; set; } = new();
|
||||||
|
[Parameter] public string CompanyId { get; set; } = "";
|
||||||
|
[Inject] public ILocalStorageService Storage { get; set; }
|
||||||
|
// private variables
|
||||||
|
private bool Descending { get; set; }
|
||||||
|
|
||||||
|
private void SortProducts(PSort column)
|
||||||
|
{
|
||||||
|
Descending = !Descending;
|
||||||
|
switch (column)
|
||||||
|
{
|
||||||
|
case PSort.Desc:
|
||||||
|
if (Descending)
|
||||||
|
{
|
||||||
|
ProductList = ProductList.OrderByDescending(x => x.Description).ToList();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
ProductList = ProductList.OrderBy(x => x.Description).ToList();
|
||||||
|
break;
|
||||||
|
case PSort.Sku:
|
||||||
|
if (Descending)
|
||||||
|
{
|
||||||
|
ProductList = ProductList.OrderByDescending(x => x.Sku).ToList();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
ProductList = ProductList.OrderBy(x => x.Sku).ToList();
|
||||||
|
break;
|
||||||
|
case PSort.Qty:
|
||||||
|
if (Descending)
|
||||||
|
{
|
||||||
|
ProductList = ProductList.OrderByDescending(x => x.Quantity).ToList();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
ProductList = ProductList.OrderBy(x => x.Quantity).ToList();
|
||||||
|
break;
|
||||||
|
case PSort.None:
|
||||||
|
break;
|
||||||
|
case PSort.Abbr:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
ProductList = ProductList.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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -19,7 +19,7 @@ using Wonky.Entity.Views;
|
||||||
|
|
||||||
namespace Wonky.Client.Components;
|
namespace Wonky.Client.Components;
|
||||||
|
|
||||||
public partial class ProductLineTableComponent
|
public partial class CustomerProductLineTableComponent
|
||||||
{
|
{
|
||||||
[Parameter] public List<ProductHistoryView> ProductHistory { get; set; } = new();
|
[Parameter] public List<ProductHistoryView> ProductHistory { get; set; } = new();
|
||||||
|
|
76
Wonky.Client/Components/CustomerProductTableComponent.razor
Normal file
76
Wonky.Client/Components/CustomerProductTableComponent.razor
Normal file
|
@ -0,0 +1,76 @@
|
||||||
|
@using Wonky.Client.Models
|
||||||
|
@using System.ComponentModel.Design
|
||||||
|
@*
|
||||||
|
// 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="row">
|
||||||
|
|
||||||
|
@if (ProductList.Any())
|
||||||
|
{
|
||||||
|
<div class="list-group mt-2">
|
||||||
|
<div class="list-group-item bg-dark text-white">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-sm-4" style="cursor: pointer;" @onclick="() => SortProducts(PSort.Desc)"><i class="bi-sort-alpha-down"></i> Navn <i class="bi-sort-alpha-up-alt"></i></div>
|
||||||
|
<div class="col-sm-3" style="cursor: pointer;" @onclick="() => SortProducts(PSort.Sku)"><i class="bi-sort-alpha-down"></i> Varenr <i class="bi-sort-alpha-up-alt"></i></div>
|
||||||
|
<div class="col-sm-2 text-center" style="cursor: pointer;" @onclick="() => SortProducts(PSort.Qty)"><i class="bi-sort-numeric-down"></i> Antal <i class="bi-sort-numeric-up-alt"></i></div>
|
||||||
|
<div class="col-sm-2"></div>
|
||||||
|
<div class="col-sm-1"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
@foreach (var product in ProductList)
|
||||||
|
{
|
||||||
|
<div class="list-group-item">
|
||||||
|
<div class="row align-items-center">
|
||||||
|
<div class="col-sm-4">
|
||||||
|
@product.Description
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-3">
|
||||||
|
@product.Sku
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-2 text-center">
|
||||||
|
@product.Quantity
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-2">
|
||||||
|
<a class="btn btn-info d-block" type="button" @onclick="() => CallShowReorderModal(product.Sku)"><i class="bi-cart"></i> Genbestil</a>
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-1" @onclick="() => ProductCheck(product.Sku)">
|
||||||
|
<input type="checkbox" class="btn-check" id="btn-@product.Sku.Replace(",", "")" autocomplete="off"/>
|
||||||
|
@if (product.Check)
|
||||||
|
{
|
||||||
|
<label class="btn btn-success" for="btn-@product.Sku.Replace(",", "")">
|
||||||
|
<i class="bi-check"></i>
|
||||||
|
</label>
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
<label class="btn btn-warning" for="btn-@product.Sku.Replace(",", "")">
|
||||||
|
<i class="bi-dash"></i>
|
||||||
|
</label>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<InventoryReorderModal OnSelected="@OnSelectedItem" CompanyId="@CompanyId" SalesItem="@SalesItem" @ref="ReorderModal"/>
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
<div>Ingen data</div>
|
||||||
|
}
|
||||||
|
</div>
|
|
@ -14,6 +14,8 @@
|
||||||
//
|
//
|
||||||
|
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using Blazored.LocalStorage;
|
||||||
using Microsoft.AspNetCore.Components;
|
using Microsoft.AspNetCore.Components;
|
||||||
using Wonky.Client.HttpInterfaces;
|
using Wonky.Client.HttpInterfaces;
|
||||||
using Wonky.Client.Models;
|
using Wonky.Client.Models;
|
||||||
|
@ -23,13 +25,13 @@ using Wonky.Entity.Views;
|
||||||
|
|
||||||
namespace Wonky.Client.Components;
|
namespace Wonky.Client.Components;
|
||||||
|
|
||||||
public partial class ProductInventoryTableComponent
|
public partial class CustomerProductTableComponent
|
||||||
{
|
{
|
||||||
[CascadingParameter] public DraftStateProvider DraftStateProvider { get; set; } = new();
|
[CascadingParameter] public DraftStateProvider DraftStateProvider { get; set; } = new();
|
||||||
[Parameter] public List<ProductInventoryView> ProductList { get; set; } = new();
|
[Parameter] public List<ProductInventoryView> ProductList { get; set; } = new();
|
||||||
[Parameter] public string CompanyId { get; set; } = "";
|
[Parameter] public string CompanyId { get; set; } = "";
|
||||||
|
|
||||||
[Inject] public ICatalogHttpRepository Catalog { get; set; }
|
[Inject] public ICatalogHttpRepository Catalog { get; set; }
|
||||||
|
[Inject] public ILocalStorageService Storage { get; set; }
|
||||||
// private variables
|
// private variables
|
||||||
private SalesItemView SalesItem { get; set; } = new();
|
private SalesItemView SalesItem { get; set; } = new();
|
||||||
private string Price { get; set; } = "0";
|
private string Price { get; set; } = "0";
|
||||||
|
@ -37,8 +39,53 @@ public partial class ProductInventoryTableComponent
|
||||||
private string Sku { get; set; } = "";
|
private string Sku { get; set; } = "";
|
||||||
private InventoryReorderModal ReorderModal { get; set; } = new();
|
private InventoryReorderModal ReorderModal { get; set; } = new();
|
||||||
private SelectedSku Item { get; set; } = new();
|
private SelectedSku Item { get; set; } = new();
|
||||||
|
private bool Descending { get; set; }
|
||||||
|
|
||||||
|
private void SortProducts(PSort column)
|
||||||
|
{
|
||||||
|
Descending = !Descending;
|
||||||
|
switch (column)
|
||||||
|
{
|
||||||
|
case PSort.Desc:
|
||||||
|
if (Descending)
|
||||||
|
{
|
||||||
|
ProductList = ProductList.OrderByDescending(x => x.Description).ToList();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
ProductList = ProductList.OrderBy(x => x.Description).ToList();
|
||||||
|
break;
|
||||||
|
case PSort.Sku:
|
||||||
|
if (Descending)
|
||||||
|
{
|
||||||
|
ProductList = ProductList.OrderByDescending(x => x.Sku).ToList();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
ProductList = ProductList.OrderBy(x => x.Sku).ToList();
|
||||||
|
break;
|
||||||
|
case PSort.Qty:
|
||||||
|
if (Descending)
|
||||||
|
{
|
||||||
|
ProductList = ProductList.OrderByDescending(x => x.Quantity).ToList();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
ProductList = ProductList.OrderBy(x => x.Quantity).ToList();
|
||||||
|
break;
|
||||||
|
case PSort.None:
|
||||||
|
break;
|
||||||
|
case PSort.Abbr:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
ProductList = ProductList.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)
|
private async Task CallShowReorderModal(string sku)
|
||||||
{
|
{
|
||||||
// fetch item from http repo
|
// fetch item from http repo
|
||||||
|
@ -51,6 +98,8 @@ public partial class ProductInventoryTableComponent
|
||||||
// add item to order draft
|
// add item to order draft
|
||||||
DraftStateProvider.Draft.DraftType = "order";
|
DraftStateProvider.Draft.DraftType = "order";
|
||||||
DraftStateProvider.Draft.Items.Add(draftItem);
|
DraftStateProvider.Draft.Items.Add(draftItem);
|
||||||
|
// set item checked
|
||||||
|
await ProductCheck(draftItem.Item.Sku);
|
||||||
await DraftStateProvider.SaveChangesAsync();
|
await DraftStateProvider.SaveChangesAsync();
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -20,7 +20,7 @@ namespace Wonky.Client.Components;
|
||||||
|
|
||||||
public partial class OfficeReportTableComponent
|
public partial class OfficeReportTableComponent
|
||||||
{
|
{
|
||||||
[Parameter] public List<NgSalesReportListView> ReportList { get; set; } = new();
|
[Parameter] public List<SalesReportListView> ReportList { get; set; } = new();
|
||||||
[Parameter] public string UserId { get; set; } = "";
|
[Parameter] public string UserId { get; set; } = "";
|
||||||
[Parameter] public string CountryCode { get; set; } = "";
|
[Parameter] public string CountryCode { get; set; } = "";
|
||||||
}
|
}
|
|
@ -15,7 +15,7 @@
|
||||||
//
|
//
|
||||||
*@
|
*@
|
||||||
|
|
||||||
<select class="form-select bg-primary text-bg-primary" @bind-value="@PageSize" @bind-value:event="oninput" @onchange="OnSelectChanged">
|
<select class="form-select bg-info text-bg-info" @bind-value="@PageSize" @bind-value:event="oninput" @onchange="OnSelectChanged">
|
||||||
<option value="-1" selected disabled>RESULTATER</option>
|
<option value="-1" selected disabled>RESULTATER</option>
|
||||||
<option value="5">5</option>
|
<option value="5">5</option>
|
||||||
<option value="10">10</option>
|
<option value="10">10</option>
|
||||||
|
|
|
@ -1,67 +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 (ProductList.Any())
|
|
||||||
{
|
|
||||||
@*
|
|
||||||
<div class="list-group">
|
|
||||||
@foreach (var product in Inventory)
|
|
||||||
{
|
|
||||||
<div class="list-group-item list-group-item-action" @onclick="() => CallShowReorderModal(product.Sku)" style="cursor: pointer;">
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-sm-4">
|
|
||||||
@product.Description
|
|
||||||
</div>
|
|
||||||
<div class="col-sm-3">@product.Sku</div>
|
|
||||||
<div class="col-sm-1">
|
|
||||||
@product.Quantity
|
|
||||||
</div>
|
|
||||||
<div class="col-sm-4">
|
|
||||||
<button class="btn btn-info d-block">Vis mere <i class="bi-arrow-right"></i></button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
*@
|
|
||||||
<table class="table table-striped table-borderless">
|
|
||||||
<tbody>
|
|
||||||
@foreach (var product in ProductList)
|
|
||||||
{
|
|
||||||
<tr style="cursor: pointer" @onclick="() => CallShowReorderModal(product.Sku)">
|
|
||||||
<td class="align-middle">
|
|
||||||
@product.Description
|
|
||||||
</td>
|
|
||||||
<td class="align-middle">
|
|
||||||
@product.Sku
|
|
||||||
</td>
|
|
||||||
<td class="align-middle text-center">
|
|
||||||
@product.Quantity
|
|
||||||
</td>
|
|
||||||
<td class="align-middle">
|
|
||||||
<a class="btn btn-info d-block" type="button" @onclick="() => CallShowReorderModal(product.Sku)"><i class="bi-pen"></i> Genbestil</a>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
}
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
<InventoryReorderModal OnSelected="@OnSelectedItem" CompanyId="@CompanyId" SalesItem="@SalesItem" @ref="ReorderModal"/>
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
<div>Ingen data</div>
|
|
||||||
}
|
|
|
@ -21,8 +21,8 @@ namespace Wonky.Client.Components;
|
||||||
|
|
||||||
public partial class ReportTableComponent
|
public partial class ReportTableComponent
|
||||||
{
|
{
|
||||||
[Parameter] public List<NgSalesReportListView> ReportList { get; set; } = new();
|
[Parameter] public List<SalesReportListView> ReportList { get; set; } = new();
|
||||||
private List<NgSalesReportListView> _reports { get; set; } = new();
|
private List<SalesReportListView> _reports { get; set; } = new();
|
||||||
protected override void OnParametersSet()
|
protected override void OnParametersSet()
|
||||||
{
|
{
|
||||||
_reports = ReportList;
|
_reports = ReportList;
|
||||||
|
|
|
@ -21,10 +21,10 @@
|
||||||
<EditForm EditContext="WorkDateContext">
|
<EditForm EditContext="WorkDateContext">
|
||||||
<div class="container-fluid">
|
<div class="container-fluid">
|
||||||
<div class="row align-items-center">
|
<div class="row align-items-center">
|
||||||
<div class="col-8 work-date fw-bold">
|
<div class="col-sm-7 work-date">
|
||||||
@SelectedDate.ToLongDateString()
|
@SelectedDate.ToLongDateString()
|
||||||
</div>
|
</div>
|
||||||
<div class="col-4">
|
<div class="col-sm-5">
|
||||||
<InputDate class="form-control calendar" @bind-Value="SelectedDate" @oninput="OnDateChanged"/>
|
<InputDate class="form-control calendar" @bind-Value="SelectedDate" @oninput="OnDateChanged"/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -21,7 +21,7 @@ namespace Wonky.Client.HttpInterfaces;
|
||||||
public interface ICrmReportHttpRepository
|
public interface ICrmReportHttpRepository
|
||||||
{
|
{
|
||||||
Task<bool> ReportExist(string workDate);
|
Task<bool> ReportExist(string workDate);
|
||||||
Task<List<NgSalesReportListView>> GetReports();
|
Task<List<SalesReportListView>> GetReports();
|
||||||
Task<ReportView> GetReport(string workDate);
|
Task<ReportView> GetReport(string workDate);
|
||||||
Task<ReportInitDto> InitializeReportData(string workDate);
|
Task<ReportInitDto> InitializeReportData(string workDate);
|
||||||
Task<ApiResponseView> PostReport(string workDate, ReportDto reportDto);
|
Task<ApiResponseView> PostReport(string workDate, ReportDto reportDto);
|
||||||
|
|
|
@ -20,6 +20,6 @@ namespace Wonky.Client.HttpInterfaces;
|
||||||
|
|
||||||
public interface IOfficeReportHttpRepository
|
public interface IOfficeReportHttpRepository
|
||||||
{
|
{
|
||||||
Task<List<NgSalesReportListView>> GetReports(string userId);
|
Task<List<SalesReportListView>> GetReports(string userId);
|
||||||
Task<ReportView> GetReport(string userId, string workDate);
|
Task<ReportView> GetReport(string userId, string workDate);
|
||||||
}
|
}
|
|
@ -132,8 +132,8 @@ public class CrmHistoryHttpRepository : ICrmHistoryHttpRepository
|
||||||
{
|
{
|
||||||
var x = await _client.GetAsync($"{_api.CrmCustomers}/{companyId}/{_api.CrmRpcSyncExt}/{syncDate}");
|
var x = await _client.GetAsync($"{_api.CrmCustomers}/{companyId}/{_api.CrmRpcSyncExt}/{syncDate}");
|
||||||
if (!x.IsSuccessStatusCode)
|
if (!x.IsSuccessStatusCode)
|
||||||
return "";
|
return string.Empty;
|
||||||
var content = await x.Content.ReadAsStringAsync();
|
var content = await x.Content.ReadAsStringAsync();
|
||||||
return content;
|
return content.Replace("\"", "");
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -47,9 +47,9 @@ public class CrmReportHttpRepository :ICrmReportHttpRepository
|
||||||
_apiConfig = configuration.Value;
|
_apiConfig = configuration.Value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<List<NgSalesReportListView>> GetReports()
|
public async Task<List<SalesReportListView>> GetReports()
|
||||||
{
|
{
|
||||||
return await _client.GetFromJsonAsync<List<NgSalesReportListView>>($"{_apiConfig.CrmReports}");
|
return await _client.GetFromJsonAsync<List<SalesReportListView>>($"{_apiConfig.CrmReports}");
|
||||||
}
|
}
|
||||||
public async Task<bool> ReportExist(string workDate)
|
public async Task<bool> ReportExist(string workDate)
|
||||||
{
|
{
|
||||||
|
|
|
@ -46,9 +46,9 @@ public class OfficeReportHttpRepository : IOfficeReportHttpRepository
|
||||||
_apiConfig = configuration.Value;
|
_apiConfig = configuration.Value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<List<NgSalesReportListView>> GetReports(string userId)
|
public async Task<List<SalesReportListView>> GetReports(string userId)
|
||||||
{
|
{
|
||||||
return await _client.GetFromJsonAsync<List<NgSalesReportListView>>($"{_apiConfig.OfficeReports}/{userId}");
|
return await _client.GetFromJsonAsync<List<SalesReportListView>>($"{_apiConfig.OfficeReports}/{userId}");
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<ReportView> GetReport(string userId, string workDate)
|
public async Task<ReportView> GetReport(string userId, string workDate)
|
||||||
|
|
10
Wonky.Client/Models/PSort.cs
Normal file
10
Wonky.Client/Models/PSort.cs
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
namespace Wonky.Client.Models;
|
||||||
|
|
||||||
|
public enum PSort
|
||||||
|
{
|
||||||
|
None,
|
||||||
|
Desc,
|
||||||
|
Sku,
|
||||||
|
Qty,
|
||||||
|
Abbr
|
||||||
|
}
|
9
Wonky.Client/Models/PTarget.cs
Normal file
9
Wonky.Client/Models/PTarget.cs
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
namespace Wonky.Client.Models;
|
||||||
|
|
||||||
|
public enum PTarget
|
||||||
|
{
|
||||||
|
None,
|
||||||
|
All,
|
||||||
|
Report,
|
||||||
|
Order
|
||||||
|
}
|
|
@ -262,23 +262,6 @@ else
|
||||||
@* end draft line ------------------------------------------------- *@
|
@* end draft line ------------------------------------------------- *@
|
||||||
</div>
|
</div>
|
||||||
<div class="accordion" id="crmActivity">
|
<div class="accordion" id="crmActivity">
|
||||||
@*
|
|
||||||
$1$ Order lines #1#
|
|
||||||
<div class="accordion-item" style="@(Activity.ActivityStatusEnum is "order" or "quote" ? "display: block" : "display:none")">
|
|
||||||
<h2 class="accordion-header" id="catalogHeader">
|
|
||||||
<button class="accordion-button collapsed bg-light" type="button"
|
|
||||||
data-bs-toggle="collapse" data-bs-target="#catalogBody"
|
|
||||||
aria-expanded="false" aria-controls="catalogBody">
|
|
||||||
Bestilling
|
|
||||||
</button>
|
|
||||||
</h2>
|
|
||||||
<div id="catalogBody" class="accordion-collapse collapse" aria-labelledby="catalogHeader" data-bs-parent="#crmActivity">
|
|
||||||
<div class="accordion-body">
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
*@
|
|
||||||
@* Delivery address *@
|
@* Delivery address *@
|
||||||
<div class="accordion-item" style="@(Activity.ActivityStatusEnum == "order" ? "display: block" : "display:none")">
|
<div class="accordion-item" style="@(Activity.ActivityStatusEnum == "order" ? "display: block" : "display:none")">
|
||||||
<h2 class="accordion-header" id="deliveryHeader">
|
<h2 class="accordion-header" id="deliveryHeader">
|
||||||
|
@ -329,12 +312,13 @@ else
|
||||||
<a class="btn btn-warning" href="/companies/@Company.CompanyId">Kundekort <i class="bi-arrow-left"></i></a>
|
<a class="btn btn-warning" href="/companies/@Company.CompanyId">Kundekort <i class="bi-arrow-left"></i></a>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-sm-4 text-end">
|
<div class="col-sm-4 text-end">
|
||||||
<button type="button" class="btn btn-warning" @onclick="CreateActivity" disabled="@(PoFormInvalid || Working)">Opret besøg <i class="bi-plus"></i></button>
|
<button type="button" class="btn btn-warning" @onclick="CallConfirmProductCheckModel" disabled="@(PoFormInvalid || Working)">Opret besøg <i class="bi-plus"></i></button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
|
||||||
<ConfirmWorkDateModal BodyMessage="@PromptDateConfirm" OnOkClicked="WorkDateConfirmCallback" @ref="ConfirmWorkDate"/>
|
<ConfirmWorkDateModal BodyMessage="@PromptDateConfirm" OnOkClicked="WorkDateConfirmCallback" @ref="ConfirmWorkDateModal"/>
|
||||||
<PriceListModal OnSelected="PriceListCallback" @ref="PriceListModal"/>
|
<PriceListModal OnSelected="PriceListCallback" @ref="PriceListModal"/>
|
||||||
<ProductHistoryModal CompanyId="@CompanyId" ItemSku="@SelectedItem.Sku" @ref="HistoryModal"/>
|
<ProductHistoryModal CompanyId="@CompanyId" ItemSku="@SelectedItem.Sku" @ref="HistoryModal"/>
|
||||||
<ProductPriceHistoryModal OnSelected="PriceHistoryCallback" CompanyId="@CompanyId" Sku="@SelectedItem.Sku" @ref="PriceHistoryModal"/>
|
<ProductPriceHistoryModal OnSelected="PriceHistoryCallback" CompanyId="@CompanyId" Sku="@SelectedItem.Sku" @ref="PriceHistoryModal"/>
|
||||||
|
<ConfirmProductCheckModal BodyMessage="" CompanyId="@CompanyId" Products="CheckList" OnOkClicked="ConfirmProductCheckCallback" @ref="ConfirmProductCheckModal" />
|
|
@ -31,13 +31,13 @@ using Wonky.Entity.Views;
|
||||||
|
|
||||||
namespace Wonky.Client.Pages;
|
namespace Wonky.Client.Pages;
|
||||||
|
|
||||||
public partial class CrmActivityNewPage : IDisposable
|
public partial class ActivityCreatePage : IDisposable
|
||||||
{
|
{
|
||||||
// Parameters
|
// Parameters
|
||||||
[CascadingParameter] DraftStateProvider DraftProvider { get; set; }
|
[CascadingParameter] DraftStateProvider DraftProvider { get; set; }
|
||||||
[Parameter] public string CompanyId { get; set; }
|
[Parameter] public string CompanyId { get; set; }
|
||||||
// Services
|
// Services
|
||||||
[Inject] public ILogger<CrmActivityNewPage> Logger { get; set; }
|
[Inject] public ILogger<ActivityCreatePage> Logger { get; set; }
|
||||||
[Inject] public HttpInterceptorService Interceptor { get; set; }
|
[Inject] public HttpInterceptorService Interceptor { get; set; }
|
||||||
[Inject] public UserPrefService Prefs { get; set; }
|
[Inject] public UserPrefService Prefs { get; set; }
|
||||||
[Inject] public IToastService Toast { get; set; }
|
[Inject] public IToastService Toast { get; set; }
|
||||||
|
@ -47,6 +47,7 @@ public partial class CrmActivityNewPage : IDisposable
|
||||||
[Inject] public ICrmCompanyHttpRepository CompanyRepo { get; set; }
|
[Inject] public ICrmCompanyHttpRepository CompanyRepo { get; set; }
|
||||||
[Inject] public ICrmActivityHttpRepository ActivityRepo { get; set; }
|
[Inject] public ICrmActivityHttpRepository ActivityRepo { get; set; }
|
||||||
[Inject] public ICrmReportHttpRepository ReportRepo { get; set; }
|
[Inject] public ICrmReportHttpRepository ReportRepo { get; set; }
|
||||||
|
[Inject] public ICrmHistoryHttpRepository HistoryRepo { get; set; }
|
||||||
// variables
|
// variables
|
||||||
private readonly JsonSerializerOptions? _options = new() {PropertyNameCaseInsensitive = true};
|
private readonly JsonSerializerOptions? _options = new() {PropertyNameCaseInsensitive = true};
|
||||||
private SalesItemView SelectedItem { get; set; } = new();
|
private SalesItemView SelectedItem { get; set; } = new();
|
||||||
|
@ -75,7 +76,10 @@ public partial class CrmActivityNewPage : IDisposable
|
||||||
private PriceListModal PriceListModal { get; set; }
|
private PriceListModal PriceListModal { get; set; }
|
||||||
private ProductHistoryModal HistoryModal { get; set; }
|
private ProductHistoryModal HistoryModal { get; set; }
|
||||||
private ProductPriceHistoryModal PriceHistoryModal { get; set; }
|
private ProductPriceHistoryModal PriceHistoryModal { get; set; }
|
||||||
private ConfirmWorkDateModal ConfirmWorkDate { get; set; } = new();
|
private ConfirmWorkDateModal ConfirmWorkDateModal { get; set; } = new();
|
||||||
|
private ConfirmProductCheckModal ConfirmProductCheckModal { get; set; } = new();
|
||||||
|
private List<ProductInventoryView> CheckList { get; set; } = new();
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Page initialization
|
/// Page initialization
|
||||||
|
@ -138,7 +142,7 @@ public partial class CrmActivityNewPage : IDisposable
|
||||||
if (!UserPrefs.DateConfirmed)
|
if (!UserPrefs.DateConfirmed)
|
||||||
{
|
{
|
||||||
PromptDateConfirm = $"Aktiviteter oprettes med dato {SelectedDate.ToShortDateString()}. Er dette OK?";
|
PromptDateConfirm = $"Aktiviteter oprettes med dato {SelectedDate.ToShortDateString()}. Er dette OK?";
|
||||||
ConfirmWorkDate.Show();
|
ConfirmWorkDateModal.Show();
|
||||||
}
|
}
|
||||||
// Lines may already have been added from the company inventory page
|
// Lines may already have been added from the company inventory page
|
||||||
if (DraftProvider.Draft.DraftType == "order")
|
if (DraftProvider.Draft.DraftType == "order")
|
||||||
|
@ -152,13 +156,77 @@ public partial class CrmActivityNewPage : IDisposable
|
||||||
//StateHasChanged();
|
//StateHasChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async Task CallConfirmProductCheckModel()
|
||||||
|
{
|
||||||
|
// check if new account
|
||||||
|
if (string.IsNullOrWhiteSpace(Company.Account)
|
||||||
|
|| Company.Account.ToLower() == "ny"
|
||||||
|
|| Activity.ActivityStatusEnum.ToLower() == "quote")
|
||||||
|
{
|
||||||
|
// proceed to create activity - as there is no product check to be done
|
||||||
|
await CreateActivity();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// check if product has been checked
|
||||||
|
// fetch products from storage
|
||||||
|
var storage = await Storage.GetItemAsStringAsync($"{CompanyId}-products");
|
||||||
|
// fetch pDate from storage
|
||||||
|
var pDate = await Storage.GetItemAsStringAsync($"{CompanyId}-pDate");
|
||||||
|
// check if product data is valid and updated today
|
||||||
|
if (string.IsNullOrWhiteSpace(storage) || DateTime.Parse(pDate.Replace("\"", "")) < DateTime.Now)
|
||||||
|
{
|
||||||
|
Working = true;
|
||||||
|
|
||||||
|
// pop a message
|
||||||
|
Toast.ShowError("Produkt gennemgang mangler. Vent mens produkt oversigt indlæses. Gå ikke væk fra siden!", "Produkt check ...");
|
||||||
|
// product inventory has not been updated
|
||||||
|
// send rpc call to sync ERP to CRM
|
||||||
|
Toast.ShowInfo("Vent mens data synkroniseres ...", "ERP til CRM ...");
|
||||||
|
var ts = await HistoryRepo.ErpInvoiceToCrmRpc(CompanyId, Company.HistorySync);
|
||||||
|
while (string.IsNullOrWhiteSpace(ts))
|
||||||
|
{
|
||||||
|
await Task.Delay(1000);
|
||||||
|
}
|
||||||
|
// save pDate
|
||||||
|
await Storage.SetItemAsync($"{CompanyId}-pDate", ts);
|
||||||
|
// request products from backend
|
||||||
|
Toast.ShowInfo("Vent mens produkt oversigt hentes", "CRM produkt liste");
|
||||||
|
CheckList = await HistoryRepo.FetchInventory(CompanyId);
|
||||||
|
CheckList = CheckList.OrderBy(x => x.Description).ToList();
|
||||||
|
await Storage.SetItemAsync($"{CompanyId}-products", CheckList);
|
||||||
|
Working = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// deserialize storage data
|
||||||
|
CheckList = JsonSerializer.Deserialize<List<ProductInventoryView>>(storage);
|
||||||
|
if(CheckList.Any())
|
||||||
|
CheckList = CheckList.OrderBy(x => x.Description).ToList();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Show CheckList modal
|
||||||
|
ConfirmProductCheckModal.Show();
|
||||||
|
}
|
||||||
|
private async Task ConfirmProductCheckCallback()
|
||||||
|
{
|
||||||
|
await CreateActivity();
|
||||||
|
foreach (var item in CheckList)
|
||||||
|
{
|
||||||
|
item.Check = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
await Storage.SetItemAsync($"{CompanyId}-products", CheckList);
|
||||||
|
ConfirmProductCheckModal.Hide();
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Work Date confirm callback
|
/// Work Date confirm callback
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private async Task WorkDateConfirmCallback()
|
private async Task WorkDateConfirmCallback()
|
||||||
{
|
{
|
||||||
await Prefs.SetDateConfirmed(true);
|
await Prefs.SetDateConfirmed(true);
|
||||||
ConfirmWorkDate.Hide();
|
ConfirmWorkDateModal.Hide();
|
||||||
StateHasChanged();
|
StateHasChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -223,7 +291,7 @@ public partial class CrmActivityNewPage : IDisposable
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private async Task CreateActivity()
|
private async Task CreateActivity()
|
||||||
{
|
{
|
||||||
// disable submit button to avoid multiple clicks
|
// avoid duplication
|
||||||
if (Working)
|
if (Working)
|
||||||
return;
|
return;
|
||||||
// validate customer address1 - this is a required input
|
// validate customer address1 - this is a required input
|
|
@ -25,10 +25,10 @@ using Wonky.Entity.Views;
|
||||||
|
|
||||||
namespace Wonky.Client.Pages;
|
namespace Wonky.Client.Pages;
|
||||||
|
|
||||||
public partial class CrmActivityTodayPage : IDisposable
|
public partial class ActivityListTodayPage : IDisposable
|
||||||
{
|
{
|
||||||
[Inject] public UserPrefService UserPrefService { get; set; }
|
[Inject] public UserPrefService UserPrefService { get; set; }
|
||||||
[Inject] public ILogger<CrmActivityTodayPage> Logger { get; set; }
|
[Inject] public ILogger<ActivityListTodayPage> Logger { get; set; }
|
||||||
[Inject] public HttpInterceptorService Interceptor { get; set; }
|
[Inject] public HttpInterceptorService Interceptor { get; set; }
|
||||||
[Inject] public NavigationManager Navigator { get; set; }
|
[Inject] public NavigationManager Navigator { get; set; }
|
||||||
[Inject] public ICrmActivityHttpRepository CrmActivityRepo { get; set; }
|
[Inject] public ICrmActivityHttpRepository CrmActivityRepo { get; set; }
|
|
@ -29,13 +29,13 @@ using Wonky.Entity.Views;
|
||||||
|
|
||||||
namespace Wonky.Client.Pages;
|
namespace Wonky.Client.Pages;
|
||||||
|
|
||||||
public partial class CrmActivityViewPage : IDisposable
|
public partial class ActivityViewPage : IDisposable
|
||||||
{
|
{
|
||||||
[Parameter] public string CompanyId { get; set; } = "";
|
[Parameter] public string CompanyId { get; set; } = "";
|
||||||
[Parameter] public string OrderId { get; set; } = "";
|
[Parameter] public string OrderId { get; set; } = "";
|
||||||
[Inject] public HttpInterceptorService Interceptor { get; set; }
|
[Inject] public HttpInterceptorService Interceptor { get; set; }
|
||||||
[Inject] public ICrmActivityHttpRepository ActivityRepo { get; set; }
|
[Inject] public ICrmActivityHttpRepository ActivityRepo { get; set; }
|
||||||
[Inject] public ILogger<CrmActivityViewPage> Logger { get; set; }
|
[Inject] public ILogger<ActivityViewPage> Logger { get; set; }
|
||||||
[Inject] public IToastService Toaster { get; set; }
|
[Inject] public IToastService Toaster { get; set; }
|
||||||
[Inject] public NavigationManager Navigator { get; set; }
|
[Inject] public NavigationManager Navigator { get; set; }
|
||||||
private ReportItemView ReportItem { get; set; } = new();
|
private ReportItemView ReportItem { get; set; } = new();
|
|
@ -42,7 +42,7 @@
|
||||||
<PaginationComponent MetaData="MetaInfo" Spread="2" SelectedPage="SetSelectedPage"/>
|
<PaginationComponent MetaData="MetaInfo" Spread="2" SelectedPage="SetSelectedPage"/>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-sm-2 text-end">
|
<div class="col-sm-2 text-end">
|
||||||
<a class="btn btn-secondary" href="/price-catalog/print"><i class="bi-printer"></i> Udskriv</a>
|
<a class="btn btn-secondary" href="/print/catalog"><i class="bi-printer"></i> Udskriv</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,59 +0,0 @@
|
||||||
using System.Net.NetworkInformation;
|
|
||||||
using System.Text.Json;
|
|
||||||
using Blazored.Toast.Services;
|
|
||||||
using Microsoft.AspNetCore.Components;
|
|
||||||
using Wonky.Client.HttpInterceptors;
|
|
||||||
using Wonky.Client.HttpInterfaces;
|
|
||||||
using Wonky.Entity.DTO;
|
|
||||||
using Wonky.Entity.Views;
|
|
||||||
|
|
||||||
namespace Wonky.Client.Pages;
|
|
||||||
|
|
||||||
public partial class CrmCompanyInvoiceListPage : IDisposable
|
|
||||||
{
|
|
||||||
[Parameter] public string CompanyId { get; set; } = "";
|
|
||||||
[Inject] public ICrmCompanyHttpRepository CompanyRepo { get; set; }
|
|
||||||
[Inject] public HttpInterceptorService Interceptor { get; set; }
|
|
||||||
[Inject] public ICrmHistoryHttpRepository HistoryRepo { get; set; }
|
|
||||||
[Inject] public IToastService Toaster { get; set; }
|
|
||||||
private InvoiceListView History { get; set; } = new();
|
|
||||||
private CompanyDto Company { get; set; } = new();
|
|
||||||
private bool Working { get; set; } = true;
|
|
||||||
|
|
||||||
protected override async Task OnInitializedAsync()
|
|
||||||
{
|
|
||||||
Interceptor.RegisterEvent();
|
|
||||||
Interceptor.RegisterBeforeSendEvent();
|
|
||||||
|
|
||||||
Company = await CompanyRepo.GetCompanyById(CompanyId);
|
|
||||||
|
|
||||||
while (string.IsNullOrWhiteSpace(Company.HistorySync))
|
|
||||||
{
|
|
||||||
await Task.Delay(1000);
|
|
||||||
}
|
|
||||||
var ts = await HistoryRepo.ErpInvoiceToCrmRpc(CompanyId, Company.HistorySync);
|
|
||||||
while (string.IsNullOrWhiteSpace(ts))
|
|
||||||
{
|
|
||||||
await Task.Delay(1000);
|
|
||||||
}
|
|
||||||
|
|
||||||
Company = await CompanyRepo.GetCompanyById(CompanyId);
|
|
||||||
|
|
||||||
while (string.IsNullOrWhiteSpace(Company.HistorySync))
|
|
||||||
{
|
|
||||||
await Task.Delay(1000);
|
|
||||||
}
|
|
||||||
ts = await HistoryRepo.ErpInvoiceToCrmRpc(CompanyId, Company.HistorySync);
|
|
||||||
while (string.IsNullOrWhiteSpace(ts))
|
|
||||||
{
|
|
||||||
await Task.Delay(1000);
|
|
||||||
}
|
|
||||||
History = await HistoryRepo.FetchInvoiceList(CompanyId);
|
|
||||||
Working = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Dispose()
|
|
||||||
{
|
|
||||||
Interceptor.DisposeEvent();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,242 +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 Microsoft.AspNetCore.Components
|
|
||||||
@using Wonky.Client.Components
|
|
||||||
@attribute [Authorize(Roles = "Advisor")]
|
|
||||||
@page "/companies/{CompanyId}"
|
|
||||||
|
|
||||||
@if (!string.IsNullOrWhiteSpace(Company.Account))
|
|
||||||
{
|
|
||||||
@if (!string.IsNullOrWhiteSpace(Company.Blocked))
|
|
||||||
{
|
|
||||||
<div class="alert alert-danger">
|
|
||||||
<h4>Ring til kontoret. Denne konto er spærret med kode '@Company.Blocked'</h4>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
<div class="row pt-2 mb-2 rounded rounded-2 bg-dark text-white">
|
|
||||||
<h3>@Company.Name</h3>
|
|
||||||
</div>
|
|
||||||
// erp context
|
|
||||||
<EditForm EditContext="ErpContext">
|
|
||||||
<DataAnnotationsValidator/>
|
|
||||||
<div class="row g-3">
|
|
||||||
@* Company Name *@
|
|
||||||
<label for="name" class="col-sm-1 col-form-label-sm">Navn</label>
|
|
||||||
<div class="col-sm-5">
|
|
||||||
<InputText id="name" class="form-control" @bind-Value="Company.Name"/>
|
|
||||||
<ValidationMessage For="@(() => Company.Name)"></ValidationMessage>
|
|
||||||
</div>
|
|
||||||
@* Company Attention *@
|
|
||||||
<label for="attention" class="col-sm-1 col-form-label-sm">Att.</label>
|
|
||||||
<div class="col-sm-5">
|
|
||||||
<InputText id="attention" class="form-control" @bind-Value="Company.Attention"/>
|
|
||||||
<ValidationMessage For="@(() => Company.Attention)"></ValidationMessage>
|
|
||||||
</div>
|
|
||||||
@* Address 1 *@
|
|
||||||
<label for="address1" class="col-sm-1 col-form-label-sm">Adresse</label>
|
|
||||||
<div class="col-sm-5">
|
|
||||||
<InputText id="address1" class="form-control" @bind-Value="Company.Address1"/>
|
|
||||||
<ValidationMessage For="@(() => Company.Address1)"></ValidationMessage>
|
|
||||||
</div>
|
|
||||||
@* Address 2 *@
|
|
||||||
<label for="address2" class="col-sm-1 col-form-label-sm">Adresse</label>
|
|
||||||
<div class="col-sm-5">
|
|
||||||
<InputText id="address2" class="form-control" @bind-Value="Company.Address2"/>
|
|
||||||
<ValidationMessage For="@(() => Company.Address2)"></ValidationMessage>
|
|
||||||
</div>
|
|
||||||
@* Post Code *@
|
|
||||||
<label for="zipCode" class="col-sm-1 col-form-label-sm">PostNr</label>
|
|
||||||
<div class="col-sm-2">
|
|
||||||
<InputText id="zipCode" class="form-control" @bind-Value="Company.ZipCode"/>
|
|
||||||
<ValidationMessage For="@(() => Company.ZipCode)"></ValidationMessage>
|
|
||||||
</div>
|
|
||||||
@* City Name *@
|
|
||||||
<label for="city" class="col-sm-1 col-form-label-sm">Bynavn</label>
|
|
||||||
<div class="col-sm-8">
|
|
||||||
<InputText id="city" class="form-control" @bind-Value="Company.City"/>
|
|
||||||
<ValidationMessage For="@(() => Company.City)"></ValidationMessage>
|
|
||||||
</div>
|
|
||||||
@* Phone *@
|
|
||||||
<label for="phone" class="col-sm-1 col-form-label-sm">Telefon</label>
|
|
||||||
<div class="col-sm-5">
|
|
||||||
<InputText id="phone" class="form-control" @bind-Value="Company.Phone"/>
|
|
||||||
<ValidationMessage For="@(() => Company.Phone)"></ValidationMessage>
|
|
||||||
</div>
|
|
||||||
@* Mobile *@
|
|
||||||
<label for="mobile" class="col-sm-1 col-form-label-sm">Mobil</label>
|
|
||||||
<div class="col-sm-5">
|
|
||||||
<InputText id="mobile" class="form-control" @bind-Value="Company.Mobile"/>
|
|
||||||
<ValidationMessage For="@(() => Company.Mobile)"></ValidationMessage>
|
|
||||||
</div>
|
|
||||||
@* Email *@
|
|
||||||
<label for="email" class="col-sm-1 col-form-label-sm">Epost</label>
|
|
||||||
<div class="col-sm-7">
|
|
||||||
<InputText id="email" class="form-control" @bind-Value="Company.Email"/>
|
|
||||||
<ValidationMessage For="@(() => Company.Email)"></ValidationMessage>
|
|
||||||
</div>
|
|
||||||
<div class="col-sm-2 text-end">
|
|
||||||
<button type="button" class="btn btn-primary" disabled="@(Company.HasFolded == 0)" onclick="@ForceActivity">Aktiver besøg</button>
|
|
||||||
</div>
|
|
||||||
<div class="col-sm-2 text-end">
|
|
||||||
<button type="button" class="btn btn-primary" onclick="@UpdateErpData" disabled="@(Working)">STAM data <i class="bi-save"></i></button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
@* account *@
|
|
||||||
<label for="account" class="col-sm-1 col-form-label-sm">Konto</label>
|
|
||||||
<div class="col-sm-2">
|
|
||||||
<input id="account" type="text" class="form-control" readonly value="@Company.Account"/>
|
|
||||||
</div>
|
|
||||||
@* vat number*@
|
|
||||||
<label for="vatNumber" class="col-sm-1 col-form-label-sm">Moms Nr</label>
|
|
||||||
<div class="col-sm-4">
|
|
||||||
<div class="input-group">
|
|
||||||
<span class="input-group-text">
|
|
||||||
<DisplayStateComponent StateClass="@VatState"/>
|
|
||||||
</span>
|
|
||||||
<InputText id="vatNumber" class="form-control" @bind-Value="Company.VatNumber"/>
|
|
||||||
<ValidationMessage For="@(() => Company.VatNumber)"></ValidationMessage>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
@* vat lookup *@
|
|
||||||
<div class="col-sm-2 text-end">
|
|
||||||
<button type="button" class="btn btn-primary" @onclick="OpenVatLookupModal">Firma opslag</button>
|
|
||||||
</div>
|
|
||||||
@* save vat number *@
|
|
||||||
<div class="col-sm-2 text-end">
|
|
||||||
<button type="button" class="btn btn-primary" @onclick="UpdateVatNumber">MOMS Nr. <i class="bi-save"></i></button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<hr class="mb-3"/>
|
|
||||||
@* activity buttons *@
|
|
||||||
<div class="row mt-3 mb-2">
|
|
||||||
<div class="col">
|
|
||||||
<a class="btn btn-dark opacity-50 d-block" href="/companies/@Company.CompanyId/invoices">Faktura</a>
|
|
||||||
</div>
|
|
||||||
@*
|
|
||||||
<div class="col">
|
|
||||||
<a class="btn btn-dark opacity-50 d-block" href="/companies/@Company.CompanyId/quotes">Tilbud</a>
|
|
||||||
</div>
|
|
||||||
*@
|
|
||||||
<div class="col">
|
|
||||||
<a class="btn btn-dark opacity-50 d-block" href="/companies/@Company.CompanyId/activities">Tidl. Besøg</a>
|
|
||||||
</div>
|
|
||||||
<div class="col">
|
|
||||||
<a class="btn btn-dark opacity-50 d-block" href="/companies/@Company.CompanyId/h/i">Produkter</a>
|
|
||||||
</div>
|
|
||||||
<div class="col">
|
|
||||||
<ActivityButton ActionLink="@ActionLink"
|
|
||||||
ButtonText="Besøg"
|
|
||||||
ButtonType="primary"
|
|
||||||
Enabled="@EnableActivity">
|
|
||||||
</ActivityButton>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<hr class="mb-3"/>
|
|
||||||
@* crm context - OBS note *@
|
|
||||||
<div class="row mb-1">
|
|
||||||
<label for="note" class="col-sm-1 col-form-label-sm">OBS</label>
|
|
||||||
<div class="col-sm-8">
|
|
||||||
@if (string.IsNullOrWhiteSpace(Company.Note))
|
|
||||||
{
|
|
||||||
<InputText name="note" id="note" class="form-control" @bind-Value="Company.Note"/>
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
<InputText name="note" id="note" class="form-control bg-warning text-black" @bind-Value="Company.Note"/>
|
|
||||||
}
|
|
||||||
<ValidationMessage For="@(() => Company.Note)"></ValidationMessage>
|
|
||||||
</div>
|
|
||||||
@* Save CRM data button *@
|
|
||||||
<div class="col-sm-3 text-end">
|
|
||||||
<button type="button" class="btn btn-primary" @onclick="UpdateCrmData">CRM data <i class="bi-save"></i></button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
@* crm context - contacts *@
|
|
||||||
<div class="row mb-1">
|
|
||||||
<label for="contacts" class="col-sm-1 col-form-label-sm">Kontakt</label>
|
|
||||||
<div id="contacts" class="col-sm-6">
|
|
||||||
<div class="list-group">
|
|
||||||
<div class="list-group-item list-group-item-action bg-dark text-white" @onclick="() => OpenContactPopup(DefaultContact)">
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-sm-4">Stilling</div>
|
|
||||||
<div class="col-sm-4">Navn</div>
|
|
||||||
<div class="col-sm-3">Direkte</div>
|
|
||||||
<div class="col-sm-1 text-end">
|
|
||||||
<i class="bi-plus-circle"></i>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
@if (Contacts.Any())
|
|
||||||
{
|
|
||||||
@foreach (var contact in Contacts)
|
|
||||||
{
|
|
||||||
<div class="list-group-item list-group-item-action" @onclick="() => OpenContactPopup(contact)">
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-sm-4">@contact.JobTitle</div>
|
|
||||||
<div class="col-sm-4">@contact.FirstName @contact.LastName</div>
|
|
||||||
<div class="col-sm-3">@contact.PhoneDirect</div>
|
|
||||||
<div class="col-sm-1 text-end">
|
|
||||||
<i class="bi-pencil"></i>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<label for="crmNotes" class="col-sm-1 col-form-label-sm">Noter</label>
|
|
||||||
<div class="col-sm-4">
|
|
||||||
<InputTextArea id="crmNotes" class="form-control" style="height: 100%;" @bind-Value="Company.CrmNotes"/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
@* crm context - dates and interval *@
|
|
||||||
<div class="row mb-1">
|
|
||||||
<label for="nextVisit" class="col-sm-1 col-form-label-sm">Næste besøg</label>
|
|
||||||
<div class="col-sm-3">
|
|
||||||
<div class="input-group">
|
|
||||||
<span class="input-group-text">
|
|
||||||
<DisplayStateComponent StateClass="@VisitState"/>
|
|
||||||
</span>
|
|
||||||
<InputDate id="nextVisit" class="form-control" @bind-Value="@(NextVisit)"/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<label for="lastVisit" class="col-sm-1 col-form-label-sm">Sidse besøg</label>
|
|
||||||
<div class="col-sm-3">
|
|
||||||
<InputDate id="lastVisit" class="form-control" @bind-Value="@LastVisit"/>
|
|
||||||
</div>
|
|
||||||
<label for="interval" class="col-sm-2 col-form-label-sm">Uge Interval</label>
|
|
||||||
<div class="col-sm-2">
|
|
||||||
<InputNumber id="interval" class="form-control" @bind-Value="Company.Interval"/>
|
|
||||||
<ValidationMessage For="@(() => Company.Interval)"></ValidationMessage>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</EditForm>
|
|
||||||
}
|
|
||||||
|
|
||||||
<VatLookupDkModal VatAddress="CompanyVatAddress" EntityName="@Company.Name" VatNumber="@Company.VatNumber"
|
|
||||||
@ref="VatLookupPopup" OnSelectedCompany="SelectedCompanyCallback" />
|
|
||||||
<ContactModal ParamContact="@SelectedContact" CompanyName="@Company.Name"
|
|
||||||
@ref="ContactPopup" OnSaveClicked="WriteContactCallback" OnDeleteClicked="DeleteContactCallback"/>
|
|
||||||
|
|
||||||
@if (Working)
|
|
||||||
{
|
|
||||||
<WorkingThreeDots />
|
|
||||||
}
|
|
|
@ -27,7 +27,7 @@ public partial class CrmReportListPage : IDisposable
|
||||||
[Inject] public ICrmReportHttpRepository CrmReportRepo { get; set; }
|
[Inject] public ICrmReportHttpRepository CrmReportRepo { get; set; }
|
||||||
[Inject] public HttpInterceptorService Interceptor { get; set; }
|
[Inject] public HttpInterceptorService Interceptor { get; set; }
|
||||||
|
|
||||||
private List<NgSalesReportListView> ReportList { get; set; } = new();
|
private List<SalesReportListView> ReportList { get; set; } = new();
|
||||||
private bool Working { get; set; } = true;
|
private bool Working { get; set; } = true;
|
||||||
|
|
||||||
protected override async Task OnInitializedAsync()
|
protected override async Task OnInitializedAsync()
|
||||||
|
|
|
@ -17,36 +17,43 @@
|
||||||
|
|
||||||
@using Wonky.Client.Components
|
@using Wonky.Client.Components
|
||||||
@using Microsoft.AspNetCore.Authorization
|
@using Microsoft.AspNetCore.Authorization
|
||||||
|
@using Wonky.Client.Models
|
||||||
@page "/sales-reports/view/{ReportDate}"
|
@page "/sales-reports/view/{ReportDate}"
|
||||||
@attribute [Authorize(Roles = "Advisor,Admin,Supervisor")]
|
@attribute [Authorize(Roles = "Advisor,Admin,Supervisor")]
|
||||||
|
|
||||||
<div class="report-main">
|
<div class="report-main">
|
||||||
|
|
||||||
<div class="row bg-dark text-white rounded-2 mb-2 py-2 align-items-center d-print-none">
|
<div class="row bg-dark text-white rounded-2 mb-2 py-2 align-items-center d-print-none">
|
||||||
<div class="col">
|
<div class="col-sm-6">
|
||||||
<WorkDateComponent OnChangedCallback="GetReport" />
|
<WorkDateComponent OnChangedCallback="GetReport"/>
|
||||||
</div>
|
</div>
|
||||||
<div class="col col-md-3 align-content-center">
|
<div class="col-sm-2 d-grid">
|
||||||
<button class="btn btn-warning" type="button" onclick="window.print();">Print</button>
|
<button class="btn btn-warning" @onclick="() => Print(PTarget.Report)"><i class="bi-printer"></i> Rapport</button>
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-2 d-grid">
|
||||||
|
<button class="btn btn-success" @onclick="() => Print(PTarget.Order)"><i class="bi-printer"></i> Ordrer</button>
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-2 d-grid">
|
||||||
|
<button class="btn btn-primary" type="button" onclick="window.print();"><i class="bi-printer"></i> Print</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@if (!string.IsNullOrWhiteSpace(_report.ReportData.DayTypeEnum))
|
@if (!string.IsNullOrWhiteSpace(Report.ReportData.DayTypeEnum))
|
||||||
{
|
{
|
||||||
<PageTitle>@_report.ReportData.Name</PageTitle>
|
<PageTitle>@Report.ReportData.Name</PageTitle>
|
||||||
<div class="alert bg-light text-dark text-center align-content-center">
|
<div class="alert bg-light text-dark text-center align-content-center">
|
||||||
<h2>@_report.ReportData.Name</h2>
|
<h2>@Report.ReportData.Name</h2>
|
||||||
</div>
|
</div>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="w-75">
|
<div class="w-75">
|
||||||
<ReportSummaryComponent ReportData="_report.ReportData" />
|
<ReportSummaryComponent ReportData="Report.ReportData"/>
|
||||||
</div>
|
</div>
|
||||||
<div class="w-25">
|
<div class="w-25">
|
||||||
<ReportDistanceLedgerComponent ReportData="_report.ReportData" />
|
<ReportDistanceLedgerComponent ReportData="Report.ReportData"/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<OfficeActivityTableComponent ActivityList="_report.ReportItems" />
|
<OfficeActivityTableComponent ActivityList="Report.ReportItems"/>
|
||||||
<ReportActivityLedgerComponent ReportData="_report.ReportData" />
|
<ReportActivityLedgerComponent ReportData="Report.ReportData"/>
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -56,13 +63,9 @@
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="report-main">
|
@if (Items.Any())
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
@if (_items.Any())
|
|
||||||
{
|
{
|
||||||
@foreach (var item in _items)
|
@foreach (var item in Items)
|
||||||
{
|
{
|
||||||
<ReportItemComponent ReportItem="@item"></ReportItemComponent>
|
<ReportItemComponent ReportItem="@item"></ReportItemComponent>
|
||||||
}
|
}
|
||||||
|
@ -71,5 +74,5 @@
|
||||||
|
|
||||||
@if (Working)
|
@if (Working)
|
||||||
{
|
{
|
||||||
<WorkingThreeDots />
|
<WorkingThreeDots/>
|
||||||
}
|
}
|
|
@ -13,9 +13,11 @@
|
||||||
// along with this program. If not, see [https://www.gnu.org/licenses/agpl-3.0.en.html]
|
// along with this program. If not, see [https://www.gnu.org/licenses/agpl-3.0.en.html]
|
||||||
//
|
//
|
||||||
|
|
||||||
|
using Blazored.LocalStorage;
|
||||||
using Microsoft.AspNetCore.Components;
|
using Microsoft.AspNetCore.Components;
|
||||||
using Wonky.Client.HttpInterfaces;
|
using Wonky.Client.HttpInterfaces;
|
||||||
using Wonky.Client.HttpRepository;
|
using Wonky.Client.HttpRepository;
|
||||||
|
using Wonky.Client.Models;
|
||||||
using Wonky.Entity.DTO;
|
using Wonky.Entity.DTO;
|
||||||
using Wonky.Entity.Views;
|
using Wonky.Entity.Views;
|
||||||
|
|
||||||
|
@ -24,10 +26,12 @@ namespace Wonky.Client.Pages;
|
||||||
public partial class CrmReportViewPage
|
public partial class CrmReportViewPage
|
||||||
{
|
{
|
||||||
[Parameter] public string ReportDate { get; set; }
|
[Parameter] public string ReportDate { get; set; }
|
||||||
[Inject] public ICrmReportHttpRepository CrmReportRepo { get; set; }
|
[Inject] public ICrmReportHttpRepository ReportRepo { get; set; }
|
||||||
[Inject] public NavigationManager _navigator { get; set; }
|
[Inject] public NavigationManager Navigator { get; set; }
|
||||||
private ReportView _report { get; set; } = new();
|
[Inject] public ILocalStorageService Storage { get; set; }
|
||||||
private List<ReportItemView> _items { get; set; } = new ();
|
private ReportView Report { get; set; } = new();
|
||||||
|
private List<ReportItemView> Items { get; set; } = new ();
|
||||||
|
|
||||||
private bool Working { get; set; } = true;
|
private bool Working { get; set; } = true;
|
||||||
|
|
||||||
protected override async Task OnInitializedAsync()
|
protected override async Task OnInitializedAsync()
|
||||||
|
@ -40,17 +44,27 @@ public partial class CrmReportViewPage
|
||||||
Working = false;
|
Working = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async Task Print(PTarget target)
|
||||||
|
{
|
||||||
|
var ux = await Storage.GetItemAsync<UserInfoView>("_ux");
|
||||||
|
if (target == PTarget.Order)
|
||||||
|
{
|
||||||
|
Navigator.NavigateTo($"/print/orders/{ux.CountryCode}/{ux.Id}/{ReportDate}");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Navigator.NavigateTo($"/print/report/{ux.CountryCode}/{ux.Id}/{ReportDate}");
|
||||||
|
}
|
||||||
private async Task GetReport(string workDate)
|
private async Task GetReport(string workDate)
|
||||||
{
|
{
|
||||||
Working = true;
|
Working = true;
|
||||||
_report = new ReportView();
|
Report = new ReportView();
|
||||||
_items = new List<ReportItemView>();
|
Items = new List<ReportItemView>();
|
||||||
|
|
||||||
if(workDate != ReportDate)
|
if(workDate != ReportDate)
|
||||||
_navigator.NavigateTo($"/sales-reports/view/{workDate}");
|
Navigator.NavigateTo($"/sales-reports/view/{workDate}");
|
||||||
_report = await CrmReportRepo.GetReport(workDate);
|
Report = await ReportRepo.GetReport(workDate);
|
||||||
|
|
||||||
_items = _report.ReportItems.Where(x => x.Lines.Any()).ToList();
|
Items = Report.ReportItems.Where(x => x.Lines.Any()).ToList();
|
||||||
Working = false;
|
Working = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -25,7 +25,7 @@ using Wonky.Entity.Views;
|
||||||
|
|
||||||
namespace Wonky.Client.Pages;
|
namespace Wonky.Client.Pages;
|
||||||
|
|
||||||
public partial class CrmCompanyActivityListPage : IDisposable
|
public partial class CustomerActivityListPage : IDisposable
|
||||||
{
|
{
|
||||||
[Parameter] public string CompanyId { get; set; } = "";
|
[Parameter] public string CompanyId { get; set; } = "";
|
||||||
[Inject] public HttpInterceptorService _interceptor { get; set; }
|
[Inject] public HttpInterceptorService _interceptor { get; set; }
|
|
@ -37,10 +37,10 @@ using Wonky.Entity.Views;
|
||||||
|
|
||||||
namespace Wonky.Client.Pages
|
namespace Wonky.Client.Pages
|
||||||
{
|
{
|
||||||
public partial class CrmCompanyNewPage : IDisposable
|
public partial class CustomerCardCreatePage : IDisposable
|
||||||
{
|
{
|
||||||
[Inject] public IToastService Toaster { get; set; }
|
[Inject] public IToastService Toaster { get; set; }
|
||||||
[Inject] public ILogger<CrmCompanyNewPage> Logger { get; set; }
|
[Inject] public ILogger<CustomerCardCreatePage> Logger { get; set; }
|
||||||
[Inject] public ILocalStorageService Storage { get; set; }
|
[Inject] public ILocalStorageService Storage { get; set; }
|
||||||
[Inject] public NavigationManager Navigator { get; set; }
|
[Inject] public NavigationManager Navigator { get; set; }
|
||||||
[Inject] public ICrmCompanyHttpRepository CompanyRepo { get; set; }
|
[Inject] public ICrmCompanyHttpRepository CompanyRepo { get; set; }
|
239
Wonky.Client/Pages/CustomerCardPage.razor
Normal file
239
Wonky.Client/Pages/CustomerCardPage.razor
Normal file
|
@ -0,0 +1,239 @@
|
||||||
|
@*
|
||||||
|
// 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 Microsoft.AspNetCore.Components
|
||||||
|
@using Wonky.Client.Components
|
||||||
|
@attribute [Authorize(Roles = "Advisor")]
|
||||||
|
@page "/companies/{CompanyId}"
|
||||||
|
|
||||||
|
@if (!string.IsNullOrWhiteSpace(Company.Account))
|
||||||
|
{
|
||||||
|
@if (!string.IsNullOrWhiteSpace(Company.Blocked))
|
||||||
|
{
|
||||||
|
<div class="alert alert-danger">
|
||||||
|
<h4>Ring til kontoret. Denne konto er spærret med kode '@Company.Blocked'</h4>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
<div class="row pt-2 mb-2 rounded rounded-2 bg-dark text-white">
|
||||||
|
<h3>@Company.Name</h3>
|
||||||
|
</div>
|
||||||
|
// erp context
|
||||||
|
<EditForm EditContext="ErpContext">
|
||||||
|
<DataAnnotationsValidator/>
|
||||||
|
<div class="row g-3">
|
||||||
|
@* Company Name *@
|
||||||
|
<label for="name" class="col-sm-1 col-form-label-sm">Navn</label>
|
||||||
|
<div class="col-sm-5">
|
||||||
|
<InputText id="name" class="form-control" @bind-Value="Company.Name"/>
|
||||||
|
<ValidationMessage For="@(() => Company.Name)"></ValidationMessage>
|
||||||
|
</div>
|
||||||
|
@* Company Attention *@
|
||||||
|
<label for="attention" class="col-sm-1 col-form-label-sm">Att.</label>
|
||||||
|
<div class="col-sm-5">
|
||||||
|
<InputText id="attention" class="form-control" @bind-Value="Company.Attention"/>
|
||||||
|
<ValidationMessage For="@(() => Company.Attention)"></ValidationMessage>
|
||||||
|
</div>
|
||||||
|
@* Address 1 *@
|
||||||
|
<label for="address1" class="col-sm-1 col-form-label-sm">Adresse</label>
|
||||||
|
<div class="col-sm-5">
|
||||||
|
<InputText id="address1" class="form-control" @bind-Value="Company.Address1"/>
|
||||||
|
<ValidationMessage For="@(() => Company.Address1)"></ValidationMessage>
|
||||||
|
</div>
|
||||||
|
@* Address 2 *@
|
||||||
|
<label for="address2" class="col-sm-1 col-form-label-sm">Adresse</label>
|
||||||
|
<div class="col-sm-5">
|
||||||
|
<InputText id="address2" class="form-control" @bind-Value="Company.Address2"/>
|
||||||
|
<ValidationMessage For="@(() => Company.Address2)"></ValidationMessage>
|
||||||
|
</div>
|
||||||
|
@* Post Code *@
|
||||||
|
<label for="zipCode" class="col-sm-1 col-form-label-sm">PostNr</label>
|
||||||
|
<div class="col-sm-2">
|
||||||
|
<InputText id="zipCode" class="form-control" @bind-Value="Company.ZipCode"/>
|
||||||
|
<ValidationMessage For="@(() => Company.ZipCode)"></ValidationMessage>
|
||||||
|
</div>
|
||||||
|
@* City Name *@
|
||||||
|
<label for="city" class="col-sm-1 col-form-label-sm">Bynavn</label>
|
||||||
|
<div class="col-sm-8">
|
||||||
|
<InputText id="city" class="form-control" @bind-Value="Company.City"/>
|
||||||
|
<ValidationMessage For="@(() => Company.City)"></ValidationMessage>
|
||||||
|
</div>
|
||||||
|
@* Phone *@
|
||||||
|
<label for="phone" class="col-sm-1 col-form-label-sm">Telefon</label>
|
||||||
|
<div class="col-sm-5">
|
||||||
|
<InputText id="phone" class="form-control" @bind-Value="Company.Phone"/>
|
||||||
|
<ValidationMessage For="@(() => Company.Phone)"></ValidationMessage>
|
||||||
|
</div>
|
||||||
|
@* Mobile *@
|
||||||
|
<label for="mobile" class="col-sm-1 col-form-label-sm">Mobil</label>
|
||||||
|
<div class="col-sm-5">
|
||||||
|
<InputText id="mobile" class="form-control" @bind-Value="Company.Mobile"/>
|
||||||
|
<ValidationMessage For="@(() => Company.Mobile)"></ValidationMessage>
|
||||||
|
</div>
|
||||||
|
@* Email *@
|
||||||
|
<label for="email" class="col-sm-1 col-form-label-sm">Epost</label>
|
||||||
|
<div class="col-sm-7">
|
||||||
|
<InputText id="email" class="form-control" @bind-Value="Company.Email"/>
|
||||||
|
<ValidationMessage For="@(() => Company.Email)"></ValidationMessage>
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-2 d-grid mx-auto">
|
||||||
|
<button type="button" class="btn btn-primary d-block" disabled="@(Company.HasFolded == 0)" onclick="@ForceActivity">Aktiver besøg</button>
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-2 d-grid mx-auto">
|
||||||
|
<button type="button" class="btn btn-primary d-block" onclick="@UpdateErpData" disabled="@(Working)"><i class="bi-save"></i> STAM data </button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
@* account *@
|
||||||
|
<label for="account" class="col-sm-1 col-form-label-sm">Konto</label>
|
||||||
|
<div class="col-sm-2">
|
||||||
|
<input id="account" type="text" class="form-control" readonly value="@Company.Account"/>
|
||||||
|
</div>
|
||||||
|
@* vat number*@
|
||||||
|
<label for="vatNumber" class="col-sm-1 col-form-label-sm">Moms Nr</label>
|
||||||
|
<div class="col-sm-4">
|
||||||
|
<div class="input-group">
|
||||||
|
<span class="input-group-text">
|
||||||
|
<DisplayStateComponent StateClass="@VatState"/>
|
||||||
|
</span>
|
||||||
|
<InputText id="vatNumber" class="form-control" @bind-Value="Company.VatNumber"/>
|
||||||
|
<ValidationMessage For="@(() => Company.VatNumber)"></ValidationMessage>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
@* vat lookup *@
|
||||||
|
<div class="col-sm-2 d-grid mx-auto">
|
||||||
|
<button type="button" class="btn btn-info" @onclick="OpenVatLookupModal">Firma opslag</button>
|
||||||
|
</div>
|
||||||
|
@* save vat number *@
|
||||||
|
<div class="col-sm-2 d-grid mx-auto">
|
||||||
|
<button type="button" class="btn btn-primary d-block" @onclick="UpdateVatNumber"><i class="bi-save"></i> MOMS Nr.</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<hr class="mb-3"/>
|
||||||
|
@* activity buttons *@
|
||||||
|
<div class="row mt-3 mb-3">
|
||||||
|
<div class="col-sm-3">
|
||||||
|
<a class="btn btn-danger d-block" href="/companies/@Company.CompanyId/invoices">Faktura</a>
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-3">
|
||||||
|
<a class="btn btn-warning d-block" href="/companies/@Company.CompanyId/activities">Tidl. Besøg</a>
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-3">
|
||||||
|
<a class="btn btn-success d-block" href="/companies/@Company.CompanyId/h/i">Produkter</a>
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-3">
|
||||||
|
<ActivityButton ActionLink="@ActionLink"
|
||||||
|
ButtonText="Nyt Besøg"
|
||||||
|
ButtonType="primary"
|
||||||
|
Enabled="@EnableActivity">
|
||||||
|
</ActivityButton>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<hr class="mb-3"/>
|
||||||
|
@* crm context - OBS note *@
|
||||||
|
<div class="row mb-2">
|
||||||
|
<label for="note" class="col-sm-1 col-form-label-sm">OBS</label>
|
||||||
|
<div class="col-sm-9">
|
||||||
|
@if (string.IsNullOrWhiteSpace(Company.Note))
|
||||||
|
{
|
||||||
|
<InputText name="note" id="note" class="form-control" @bind-Value="Company.Note"/>
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
<InputText name="note" id="note" class="form-control bg-warning text-black" @bind-Value="Company.Note"/>
|
||||||
|
}
|
||||||
|
<ValidationMessage For="@(() => Company.Note)"></ValidationMessage>
|
||||||
|
</div>
|
||||||
|
@* Save CRM data button *@
|
||||||
|
<div class="col-sm-2 d-grid mx-auto">
|
||||||
|
<button type="button" class="btn btn-primary" @onclick="UpdateCrmData"><i class="bi-save"></i> CRM data</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
@* crm context - contacts *@
|
||||||
|
<div class="row mb-2">
|
||||||
|
<label for="contacts" class="col-sm-1 col-form-label-sm">Kontakt</label>
|
||||||
|
<div id="contacts" class="col-sm-11">
|
||||||
|
<div class="list-group">
|
||||||
|
<div class="list-group-item list-group-item-action bg-dark text-white" @onclick="() => OpenContactPopup(DefaultContact)">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-sm-4">Stilling</div>
|
||||||
|
<div class="col-sm-4">Navn</div>
|
||||||
|
<div class="col-sm-3">Direkte</div>
|
||||||
|
<div class="col-sm-1 text-end">
|
||||||
|
<i class="bi-plus-circle"></i>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
@if (Contacts.Any())
|
||||||
|
{
|
||||||
|
@foreach (var contact in Contacts)
|
||||||
|
{
|
||||||
|
<div class="list-group-item list-group-item-action" @onclick="() => OpenContactPopup(contact)">
|
||||||
|
<div class="row g-2">
|
||||||
|
<div class="col-sm-4">@contact.JobTitle</div>
|
||||||
|
<div class="col-sm-4">@contact.FirstName @contact.LastName</div>
|
||||||
|
<div class="col-sm-3">@contact.PhoneDirect</div>
|
||||||
|
<div class="col-sm-1 text-end">
|
||||||
|
<i class="bi-pencil"></i>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
@* crm context - dates and interval *@
|
||||||
|
<div class="row mb-2">
|
||||||
|
<label for="nextVisit" class="col-sm-1 col-form-label-sm">Næste besøg</label>
|
||||||
|
<div class="col-sm-3">
|
||||||
|
<div class="input-group">
|
||||||
|
<span class="input-group-text">
|
||||||
|
<DisplayStateComponent StateClass="@VisitState"/>
|
||||||
|
</span>
|
||||||
|
<InputDate id="nextVisit" class="form-control" @bind-Value="@(NextVisit)"/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<label for="lastVisit" class="col-sm-1 col-form-label-sm">Sidse besøg</label>
|
||||||
|
<div class="col-sm-3">
|
||||||
|
<InputDate id="lastVisit" class="form-control" @bind-Value="@LastVisit"/>
|
||||||
|
</div>
|
||||||
|
<label for="interval" class="col-sm-2 col-form-label-sm">Uge Interval</label>
|
||||||
|
<div class="col-sm-2">
|
||||||
|
<InputNumber id="interval" class="form-control" @bind-Value="Company.Interval"/>
|
||||||
|
<ValidationMessage For="@(() => Company.Interval)"></ValidationMessage>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row mb-2">
|
||||||
|
<label for="crmNotes" class="col-sm-1 col-form-label-sm">Noter</label>
|
||||||
|
<div class="col-sm-11">
|
||||||
|
<InputTextArea id="crmNotes" class="form-control" @bind-Value="Company.CrmNotes"/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</EditForm>
|
||||||
|
}
|
||||||
|
|
||||||
|
<VatLookupDkModal VatAddress="CompanyVatAddress" EntityName="@Company.Name" VatNumber="@Company.VatNumber"
|
||||||
|
@ref="VatLookupPopup" OnSelectedCompany="SelectedCompanyCallback" />
|
||||||
|
<ContactModal ParamContact="@SelectedContact" CompanyName="@Company.Name"
|
||||||
|
@ref="ContactPopup" OnSaveClicked="WriteContactCallback" OnDeleteClicked="DeleteContactCallback"/>
|
||||||
|
|
||||||
|
@if (Working)
|
||||||
|
{
|
||||||
|
<WorkingThreeDots />
|
||||||
|
}
|
|
@ -31,11 +31,11 @@ using Wonky.Entity.Views;
|
||||||
|
|
||||||
namespace Wonky.Client.Pages;
|
namespace Wonky.Client.Pages;
|
||||||
|
|
||||||
public partial class CrmCompanyViewPage : IDisposable
|
public partial class CustomerCardPage : IDisposable
|
||||||
{
|
{
|
||||||
[Parameter] public string CompanyId { get; set; } = "";
|
[Parameter] public string CompanyId { get; set; } = "";
|
||||||
[Inject] public IToastService Toaster { get; set; }
|
[Inject] public IToastService Toaster { get; set; }
|
||||||
[Inject] public ILogger<CrmCompanyViewPage> Logger { get; set; }
|
[Inject] public ILogger<CustomerCardPage> Logger { get; set; }
|
||||||
[Inject] public NavigationManager Navigator { get; set; }
|
[Inject] public NavigationManager Navigator { get; set; }
|
||||||
[Inject] public ICrmCompanyHttpRepository CompanyRepo { get; set; }
|
[Inject] public ICrmCompanyHttpRepository CompanyRepo { get; set; }
|
||||||
[Inject] public ICrmHistoryHttpRepository HistoryRepo { get; set; }
|
[Inject] public ICrmHistoryHttpRepository HistoryRepo { get; set; }
|
|
@ -14,7 +14,7 @@
|
||||||
<a class="btn btn-primary d-block" href="/companies/@Company.CompanyId/activities/new"><i class="bi-arrow-right"></i> Besøg</a>
|
<a class="btn btn-primary d-block" href="/companies/@Company.CompanyId/activities/new"><i class="bi-arrow-right"></i> Besøg</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<InvoiceTableComponent CompanyId="@CompanyId" InvoiceList="@History.Invoices"/>
|
<InvoiceTableComponent CompanyId="@CompanyId" InvoiceList="@CompanyInvoices.Invoices"/>
|
||||||
}
|
}
|
||||||
|
|
||||||
@if (Working)
|
@if (Working)
|
78
Wonky.Client/Pages/CustomerInvoiceListPage.razor.cs
Normal file
78
Wonky.Client/Pages/CustomerInvoiceListPage.razor.cs
Normal file
|
@ -0,0 +1,78 @@
|
||||||
|
using System.Globalization;
|
||||||
|
using System.Net.NetworkInformation;
|
||||||
|
using System.Text.Json;
|
||||||
|
using Blazored.LocalStorage;
|
||||||
|
using Blazored.Toast.Services;
|
||||||
|
using Microsoft.AspNetCore.Components;
|
||||||
|
using Wonky.Client.HttpInterceptors;
|
||||||
|
using Wonky.Client.HttpInterfaces;
|
||||||
|
using Wonky.Entity.DTO;
|
||||||
|
using Wonky.Entity.Views;
|
||||||
|
|
||||||
|
namespace Wonky.Client.Pages;
|
||||||
|
|
||||||
|
public partial class CustomerInvoiceListPage : IDisposable
|
||||||
|
{
|
||||||
|
[Parameter] public string CompanyId { get; set; } = "";
|
||||||
|
[Inject] public ICrmCompanyHttpRepository CompanyRepo { get; set; }
|
||||||
|
[Inject] public HttpInterceptorService Interceptor { get; set; }
|
||||||
|
[Inject] public ICrmHistoryHttpRepository HistoryRepo { get; set; }
|
||||||
|
[Inject] public IToastService Toaster { get; set; }
|
||||||
|
[Inject] public ILocalStorageService Storage { get; set; }
|
||||||
|
[Inject] public ILogger<CustomerInvoiceListPage> Logger { get; set; }
|
||||||
|
private InvoiceListView CompanyInvoices { get; set; } = new();
|
||||||
|
private CompanyDto Company { get; set; } = new();
|
||||||
|
private bool Working { get; set; } = true;
|
||||||
|
|
||||||
|
protected override async Task OnInitializedAsync()
|
||||||
|
{
|
||||||
|
Interceptor.RegisterEvent();
|
||||||
|
Interceptor.RegisterBeforeSendEvent();
|
||||||
|
|
||||||
|
Company = await CompanyRepo.GetCompanyById(CompanyId);
|
||||||
|
while (string.IsNullOrWhiteSpace(Company.HistorySync))
|
||||||
|
{
|
||||||
|
await Task.Delay(1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
var iDate = await Storage.GetItemAsStringAsync($"{Company.CompanyId}-iDate");
|
||||||
|
if (string.IsNullOrWhiteSpace(iDate) || (iDate == Company.HistorySync && iDate != $"{DateTime.Now:yyyy-MM-dd}"))
|
||||||
|
{
|
||||||
|
// send rpc to sync invoices from ERP to CRM
|
||||||
|
var ts = await HistoryRepo.ErpInvoiceToCrmRpc(CompanyId, Company.HistorySync);
|
||||||
|
// wait until we have the result
|
||||||
|
while (string.IsNullOrWhiteSpace(ts))
|
||||||
|
{
|
||||||
|
await Task.Delay(1000);
|
||||||
|
}
|
||||||
|
await Storage.SetItemAsync($"{Company.CompanyId}-iDate", ts);
|
||||||
|
}
|
||||||
|
|
||||||
|
CompanyInvoices = await FetchCompanyInvoices();
|
||||||
|
Working = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task<InvoiceListView> FetchCompanyInvoices()
|
||||||
|
{
|
||||||
|
var storage = await Storage.GetItemAsStringAsync($"{Company.CompanyId}-invoices");
|
||||||
|
var iDate = await Storage.GetItemAsStringAsync($"{Company.CompanyId}-iDate");
|
||||||
|
// if we have a list and iDate was today return the list
|
||||||
|
if (!string.IsNullOrWhiteSpace(storage) && DateTime.Parse(iDate.Replace("\"", "")) >= DateTime.Now)
|
||||||
|
{
|
||||||
|
Logger.LogDebug("return invoices from storage");
|
||||||
|
return JsonSerializer.Deserialize<InvoiceListView>(storage);
|
||||||
|
}
|
||||||
|
Logger.LogDebug("pulling invoices from backend");
|
||||||
|
// pull invoices
|
||||||
|
var invoices = await HistoryRepo.FetchInvoiceList(CompanyId);
|
||||||
|
// send invoices to storage
|
||||||
|
await Storage.SetItemAsync($"{Company.CompanyId}-invoices", invoices);
|
||||||
|
Logger.LogDebug("return invoices from backend");
|
||||||
|
return invoices;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
Interceptor.DisposeEvent();
|
||||||
|
}
|
||||||
|
}
|
|
@ -28,7 +28,7 @@ using Wonky.Entity.Views;
|
||||||
|
|
||||||
namespace Wonky.Client.Pages
|
namespace Wonky.Client.Pages
|
||||||
{
|
{
|
||||||
public partial class CrmCompanyListPage : IDisposable
|
public partial class CustomerListPage : IDisposable
|
||||||
{
|
{
|
||||||
[Inject] public ILocalStorageService Storage { get; set; }
|
[Inject] public ILocalStorageService Storage { get; set; }
|
||||||
[Inject] public UserPrefService PrefService { get; set; }
|
[Inject] public UserPrefService PrefService { get; set; }
|
|
@ -24,13 +24,13 @@
|
||||||
<h4 class="pt-1">@Company.Name</h4>
|
<h4 class="pt-1">@Company.Name</h4>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-sm-3 align-content-end">
|
<div class="col-sm-3 align-content-end">
|
||||||
<a class="btn btn-primary d-block" href="/companies/@Company.CompanyId"><i class="bi-arrow-right"></i> Kundekort</a>
|
<a class="btn btn-primary d-block" href="/companies/@Company.CompanyId"><i class="bi-arrow-left"></i> Kundekort</a>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-sm-3 align-content-end">
|
<div class="col-sm-3 align-content-end">
|
||||||
<a class="btn btn-primary d-block" href="/companies/@Company.CompanyId/activities/new"><i class="bi-arrow-right"></i> Besøg</a>
|
<a class="btn btn-primary d-block" href="/companies/@Company.CompanyId/activities/new"><i class="bi-arrow-right"></i> Nyt Besøg</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<ProductInventoryTableComponent CompanyId="@CompanyId" ProductList="Inventory"/>
|
<CustomerProductTableComponent CompanyId="@CompanyId" ProductList="Inventory"/>
|
||||||
|
|
||||||
|
|
||||||
@if (Working)
|
@if (Working)
|
|
@ -14,7 +14,9 @@
|
||||||
//
|
//
|
||||||
|
|
||||||
|
|
||||||
|
using System.Globalization;
|
||||||
using System.Text.Json;
|
using System.Text.Json;
|
||||||
|
using Blazored.LocalStorage;
|
||||||
using Blazored.Toast.Services;
|
using Blazored.Toast.Services;
|
||||||
using Microsoft.AspNetCore.Components;
|
using Microsoft.AspNetCore.Components;
|
||||||
using Wonky.Client.HttpInterceptors;
|
using Wonky.Client.HttpInterceptors;
|
||||||
|
@ -25,14 +27,15 @@ using Wonky.Entity.Views;
|
||||||
|
|
||||||
namespace Wonky.Client.Pages;
|
namespace Wonky.Client.Pages;
|
||||||
|
|
||||||
public partial class CrmCompanyInventoryPage : IDisposable
|
public partial class CustomerProductListPage : IDisposable
|
||||||
{
|
{
|
||||||
[Parameter] public string CompanyId { get; set; } = "";
|
[Parameter] public string CompanyId { get; set; } = "";
|
||||||
[Inject] public ICrmHistoryHttpRepository HistoryRepo { get; set; }
|
[Inject] public ICrmHistoryHttpRepository HistoryRepo { get; set; }
|
||||||
[Inject] public ICrmCompanyHttpRepository CompanyRepo { get; set; }
|
[Inject] public ICrmCompanyHttpRepository CompanyRepo { get; set; }
|
||||||
[Inject] public HttpInterceptorService Interceptor { get; set; }
|
[Inject] public HttpInterceptorService Interceptor { get; set; }
|
||||||
[Inject] public IToastService Toaster { get; set; }
|
[Inject] public IToastService Toaster { get; set; }
|
||||||
[Inject] public ILogger<CrmCompanyInventoryPage> Logger { get; set; }
|
[Inject] public ILogger<CustomerProductListPage> Logger { get; set; }
|
||||||
|
[Inject] public ILocalStorageService Storage { get; set; }
|
||||||
private CompanyDto Company { get; set; } = new();
|
private CompanyDto Company { get; set; } = new();
|
||||||
private List<ProductInventoryView> Inventory { get; set; } = new();
|
private List<ProductInventoryView> Inventory { get; set; } = new();
|
||||||
private bool Working { get; set; } = true;
|
private bool Working { get; set; } = true;
|
||||||
|
@ -48,22 +51,41 @@ public partial class CrmCompanyInventoryPage : IDisposable
|
||||||
{
|
{
|
||||||
await Task.Delay(1000);
|
await Task.Delay(1000);
|
||||||
}
|
}
|
||||||
var ts = await HistoryRepo.ErpInvoiceToCrmRpc(CompanyId, Company.HistorySync);
|
|
||||||
while (string.IsNullOrWhiteSpace(ts))
|
|
||||||
{
|
|
||||||
await Task.Delay(1000);
|
|
||||||
}
|
|
||||||
|
|
||||||
await FetchInventory();
|
var pDate = await Storage.GetItemAsStringAsync($"{Company.CompanyId}-pDate");
|
||||||
|
if (string.IsNullOrWhiteSpace(pDate) || (pDate == Company.HistorySync && pDate != $"{DateTime.Now:yyyy-MM-dd}"))
|
||||||
|
{
|
||||||
|
var ts = await HistoryRepo.ErpInvoiceToCrmRpc(CompanyId, Company.HistorySync);
|
||||||
|
while (string.IsNullOrWhiteSpace(ts))
|
||||||
|
{
|
||||||
|
await Task.Delay(1000);
|
||||||
|
}
|
||||||
|
await Storage.SetItemAsync($"{Company.CompanyId}-pDate", ts);
|
||||||
|
}
|
||||||
|
// fetch product inventory
|
||||||
|
Inventory = await FetchProductInventory();
|
||||||
Working = false;
|
Working = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task FetchInventory()
|
private async Task<List<ProductInventoryView>> FetchProductInventory()
|
||||||
{
|
{
|
||||||
Working = true;
|
var storage = await Storage.GetItemAsStringAsync($"{Company.CompanyId}-products");
|
||||||
Inventory = await HistoryRepo.FetchInventory(CompanyId);
|
var pDate = await Storage.GetItemAsStringAsync($"{Company.CompanyId}-pDate");
|
||||||
Inventory = Inventory.Any() ? Inventory.OrderBy(x => x.Description).ToList() : new List<ProductInventoryView>();
|
// if we have a list and pDate was today return the list
|
||||||
Working = false;
|
if (!string.IsNullOrWhiteSpace(storage) || DateTime.Parse(pDate.Replace("\"", "")) >= DateTime.Now)
|
||||||
|
{
|
||||||
|
Logger.LogDebug("return products from storage");
|
||||||
|
return JsonSerializer.Deserialize<List<ProductInventoryView>>(storage);
|
||||||
|
}
|
||||||
|
Logger.LogDebug("pulling products from backend");
|
||||||
|
// fetch product history
|
||||||
|
var inventory = await HistoryRepo.FetchInventory(CompanyId);
|
||||||
|
// default sort order by description
|
||||||
|
inventory = inventory.Any() ? inventory.OrderBy(x => x.Description).ToList() : new List<ProductInventoryView>();
|
||||||
|
// send products to storage
|
||||||
|
await Storage.SetItemAsync($"{Company.CompanyId}-products", inventory);
|
||||||
|
Logger.LogDebug("return products from backend");
|
||||||
|
return inventory;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
|
@ -29,7 +29,7 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<OfficeReportTableComponent CountryCode="@CountryCode" UserId="@UserId" ReportList="@_reports" />
|
<OfficeReportTableComponent CountryCode="@CountryCode" UserId="@UserId" ReportList="@ActivityReports" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
@ -26,22 +26,31 @@ public partial class OfficeReportListPage : IDisposable
|
||||||
{
|
{
|
||||||
[Parameter] public string UserId { get; set; } = "";
|
[Parameter] public string UserId { get; set; } = "";
|
||||||
[Parameter] public string CountryCode { get; set; } = "";
|
[Parameter] public string CountryCode { get; set; } = "";
|
||||||
[Inject] public IOfficeReportHttpRepository _reportRepo { get; set; }
|
[Inject] public IOfficeReportHttpRepository ReportRepo { get; set; }
|
||||||
[Inject] public HttpInterceptorService _interceptor { get; set; }
|
[Inject] public HttpInterceptorService Interceptor { get; set; }
|
||||||
private List<NgSalesReportListView> _reports { get; set; }
|
private List<SalesReportListView> ActivityReports { get; set; } = new();
|
||||||
private bool Working { get; set; } = true;
|
private bool Working { get; set; } = true;
|
||||||
|
|
||||||
|
|
||||||
protected override async Task OnInitializedAsync()
|
protected override async Task OnInitializedAsync()
|
||||||
{
|
{
|
||||||
_interceptor.RegisterEvent();
|
Interceptor.RegisterEvent();
|
||||||
_interceptor.RegisterBeforeSendEvent();
|
Interceptor.RegisterBeforeSendEvent();
|
||||||
|
|
||||||
_reports = await _reportRepo.GetReports(UserId);
|
await FetchReports();
|
||||||
Working = false;
|
Working = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async Task FetchReports()
|
||||||
|
{
|
||||||
|
var reports = await ReportRepo.GetReports(UserId);
|
||||||
|
if (reports.Any())
|
||||||
|
ActivityReports = reports.OrderByDescending(x => x.ReportDate).ToList();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.</summary>
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
_interceptor.DisposeEvent();
|
Interceptor.DisposeEvent();
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -17,60 +17,66 @@
|
||||||
|
|
||||||
@using Wonky.Client.Components
|
@using Wonky.Client.Components
|
||||||
@using Microsoft.AspNetCore.Authorization
|
@using Microsoft.AspNetCore.Authorization
|
||||||
|
@using Wonky.Client.Models
|
||||||
@page "/office/users/advisors/{CountryCode}/{UserId}/reports/{ReportDate}"
|
@page "/office/users/advisors/{CountryCode}/{UserId}/reports/{ReportDate}"
|
||||||
@attribute [Authorize(Roles = "Admin")]
|
@attribute [Authorize(Roles = "Admin")]
|
||||||
|
|
||||||
<div class="report-main">
|
<div class="row mb-3 g-1 d-print-none">
|
||||||
<div class="row mb-3 d-print-none">
|
<div class="col-sm-6">
|
||||||
@* <div class="col-md-6 align-content-center"> *@
|
<WorkDateComponent OnChangedCallback="FetchReport" />
|
||||||
@* <h3 class="workDate">@DateTime.Parse(ReportDate).ToLongDateString()</h3> *@
|
</div>
|
||||||
@* </div> *@
|
<div class="col-sm-2 d-grid">
|
||||||
<div class="col col-md-6 align-content-center">
|
<button class="btn btn-warning" @onclick="() => Print(PTarget.Report)"><i class="bi-printer"></i> Rapport</button>
|
||||||
<WorkDateComponent OnChangedCallback="FetchReport" />
|
</div>
|
||||||
</div>
|
<div class="col-sm-2 d-grid">
|
||||||
<div class="col col-md-6 align-content-center">
|
<button class="btn btn-success" @onclick="() => Print(PTarget.Order)"><i class="bi-printer"></i> Ordrer</button>
|
||||||
<button class="btn btn-warning" type="button" onclick="window.print();">Print</button>
|
</div>
|
||||||
</div>
|
<div class="col-sm-2 d-grid">
|
||||||
@* todo
|
<button class="btn btn-primary" type="button" onclick="window.print();"><i class="bi-printer"></i> Print</button>
|
||||||
option wo print only report
|
|
||||||
*@
|
|
||||||
</div>
|
</div>
|
||||||
@if (!string.IsNullOrWhiteSpace(Report.ReportData.DayTypeEnum))
|
|
||||||
{
|
|
||||||
<PageTitle>@Report.ReportData.Name</PageTitle>
|
|
||||||
<div class="row">
|
|
||||||
<div class="col text-center align-content-center">
|
|
||||||
<h3>@Report.ReportData.Name</h3>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="row">
|
|
||||||
<div class="w-75">
|
|
||||||
<ReportSummaryComponent ReportData="Report.ReportData" />
|
|
||||||
</div>
|
|
||||||
<div class="w-25">
|
|
||||||
<ReportDistanceLedgerComponent ReportData="Report.ReportData" />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<OfficeActivityTableComponent ActivityList="Report.ReportItems" />
|
|
||||||
<ReportActivityLedgerComponent ReportData="Report.ReportData" />
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
<div class="row">
|
|
||||||
<div class="col">Ingen data</div>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@* todo - add flag for printing only report *@
|
@if (ThisTarget is PTarget.Report or PTarget.All)
|
||||||
@if (_items.Any())
|
|
||||||
{
|
{
|
||||||
@foreach (var item in _items.Where(item => item.StatusTypeEnum.ToLower() == "order" && item.ProcessStatusEnum.ToLower() == "none"))
|
<div class="report-main d-print-grid">
|
||||||
{
|
@if (!string.IsNullOrWhiteSpace(Report.ReportData.DayTypeEnum))
|
||||||
<ReportItemComponent ReportItem="@item"></ReportItemComponent>
|
{
|
||||||
}
|
<PageTitle>@Report.ReportData.Name</PageTitle>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col text-center align-content-center">
|
||||||
|
<h3>@Report.ReportData.Name</h3>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="w-75">
|
||||||
|
<ReportSummaryComponent ReportData="Report.ReportData" />
|
||||||
|
</div>
|
||||||
|
<div class="w-25">
|
||||||
|
<ReportDistanceLedgerComponent ReportData="Report.ReportData" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<OfficeActivityTableComponent ActivityList="Report.ReportItems" />
|
||||||
|
<ReportActivityLedgerComponent ReportData="Report.ReportData" />
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
<div class="row">
|
||||||
|
<div class="col">Ingen data</div>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@if (ThisTarget is PTarget.Order or PTarget.All)
|
||||||
|
{
|
||||||
|
if (Activities.Any())
|
||||||
|
{
|
||||||
|
foreach (var item in Activities.Where(item => item.StatusTypeEnum.ToLower() == "order" && item.ProcessStatusEnum.ToLower() == "none"))
|
||||||
|
{
|
||||||
|
<ReportItemComponent ReportItem="@item"></ReportItemComponent>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@if (Working)
|
@if (Working)
|
||||||
{
|
{
|
||||||
|
|
|
@ -13,11 +13,11 @@
|
||||||
// along with this program. If not, see [https://www.gnu.org/licenses/agpl-3.0.en.html]
|
// along with this program. If not, see [https://www.gnu.org/licenses/agpl-3.0.en.html]
|
||||||
//
|
//
|
||||||
|
|
||||||
using System.Text.Json;
|
using Blazored.LocalStorage;
|
||||||
using Microsoft.AspNetCore.Components;
|
using Microsoft.AspNetCore.Components;
|
||||||
using Wonky.Client.HttpInterceptors;
|
using Wonky.Client.HttpInterceptors;
|
||||||
using Wonky.Client.HttpInterfaces;
|
using Wonky.Client.HttpInterfaces;
|
||||||
using Wonky.Client.HttpRepository;
|
using Wonky.Client.Models;
|
||||||
using Wonky.Entity.Views;
|
using Wonky.Entity.Views;
|
||||||
|
|
||||||
namespace Wonky.Client.Pages;
|
namespace Wonky.Client.Pages;
|
||||||
|
@ -27,46 +27,71 @@ public partial class OfficeReportViewPage : IDisposable
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Country code from url parameter
|
/// Country code from url parameter
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Parameter] public string CountryCode { get; set; } = "";
|
[Parameter]
|
||||||
|
public string CountryCode { get; set; } = "";
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Report date from url parameter
|
/// Report date from url parameter
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Parameter] public string ReportDate { get; set; } = "";
|
[Parameter]
|
||||||
|
public string ReportDate { get; set; } = "";
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// User entity Id from url parameter
|
/// User entity Id from url parameter
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Parameter] public string UserId { get; set; } = "";
|
[Parameter]
|
||||||
|
public string UserId { get; set; } = "";
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Injected interceptor service
|
/// Injected interceptor service
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Inject] public HttpInterceptorService _interceptor { get; set; }
|
[Inject]
|
||||||
|
public HttpInterceptorService Interceptor { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Injected administrative report http repo
|
/// Injected administrative report http repo
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Inject] public IOfficeReportHttpRepository _reportRepo { get; set; }
|
[Inject]
|
||||||
|
public IOfficeReportHttpRepository ReportRepo { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Navigation Manager
|
/// Navigation Manager
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Inject] public NavigationManager _navigator { get; set; }
|
[Inject]
|
||||||
|
public NavigationManager Navigator { get; set; }
|
||||||
|
|
||||||
|
[Inject] public ILogger<OfficeReportViewPage> Logger { get; set; }
|
||||||
|
[Inject] public ILocalStorageService Storage { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Report to render
|
/// Report to render
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private ReportView Report { get; set; } = new();
|
private ReportView Report { get; set; } = new();
|
||||||
|
|
||||||
private List<ReportItemView> _items { get; set; } = new();
|
private PTarget ThisTarget { get; set; } = PTarget.All;
|
||||||
private string _workDate { get; set; } = "";
|
private List<ReportItemView> Activities { get; set; } = new();
|
||||||
private bool Working { get; set; } = true;
|
private bool Working { get; set; } = true;
|
||||||
|
|
||||||
protected override async Task OnParametersSetAsync()
|
protected override async Task OnParametersSetAsync()
|
||||||
{
|
{
|
||||||
_interceptor.RegisterEvent();
|
Interceptor.RegisterEvent();
|
||||||
_interceptor.RegisterBeforeSendEvent();
|
Interceptor.RegisterBeforeSendEvent();
|
||||||
|
await Task.Delay(100);
|
||||||
await FetchReport(ReportDate);
|
await FetchReport(ReportDate);
|
||||||
Working = false;
|
Working = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void Print(PTarget target)
|
||||||
|
{
|
||||||
|
if (target == PTarget.Order)
|
||||||
|
{
|
||||||
|
Navigator.NavigateTo($"/print/orders/{CountryCode}/{UserId}/{ReportDate}");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Navigator.NavigateTo($"/print/report/{CountryCode}/{UserId}/{ReportDate}");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Work date component event handler
|
/// Work date component event handler
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -75,20 +100,20 @@ public partial class OfficeReportViewPage : IDisposable
|
||||||
{
|
{
|
||||||
if (workDate != ReportDate)
|
if (workDate != ReportDate)
|
||||||
{
|
{
|
||||||
_navigator.NavigateTo($"/office/users/advisors/{CountryCode}/{UserId}/reports/{workDate}");
|
Navigator.NavigateTo($"/office/users/advisors/{CountryCode}/{UserId}/reports/{workDate}");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Working = true;
|
Working = true;
|
||||||
Report = new ReportView();
|
Report = new ReportView();
|
||||||
_items = new List<ReportItemView>();
|
Activities = new List<ReportItemView>();
|
||||||
|
|
||||||
Report = await FetchUserReport(UserId, workDate);
|
Report = await FetchUserReport(UserId, workDate);
|
||||||
//_items = Report.ReportItems.Where(x => x.OrderAmount > 0).ToList();
|
Activities = Report.ReportItems.Where(x => x.Lines.Any()).ToList();
|
||||||
_items = Report.ReportItems.Where(x => x.Lines.Any()).ToList();
|
await Storage.SetItemAsync($"{UserId}-{ReportDate}", Report);
|
||||||
Working = false;
|
Working = false;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Get report for user with entity Id for work date
|
/// Get report for user with entity Id for work date
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -98,13 +123,13 @@ public partial class OfficeReportViewPage : IDisposable
|
||||||
private async Task<ReportView> FetchUserReport(string userId, string workDate)
|
private async Task<ReportView> FetchUserReport(string userId, string workDate)
|
||||||
{
|
{
|
||||||
Working = true;
|
Working = true;
|
||||||
var x =Report = await _reportRepo.GetReport(userId, workDate);
|
var x = Report = await ReportRepo.GetReport(userId, workDate);
|
||||||
Working = false;
|
Working = false;
|
||||||
return x;
|
return x;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
_interceptor.DisposeEvent();
|
Interceptor.DisposeEvent();
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -15,7 +15,7 @@
|
||||||
//
|
//
|
||||||
*@
|
*@
|
||||||
|
|
||||||
@page "/price-catalog/print"
|
@page "/print/catalog"
|
||||||
@using Wonky.Client.Components
|
@using Wonky.Client.Components
|
||||||
@using Microsoft.AspNetCore.Authorization
|
@using Microsoft.AspNetCore.Authorization
|
||||||
|
|
|
@ -29,7 +29,7 @@ using Wonky.Entity.Views;
|
||||||
|
|
||||||
namespace Wonky.Client.Pages;
|
namespace Wonky.Client.Pages;
|
||||||
|
|
||||||
public partial class CatalogPrintPage : IDisposable
|
public partial class PrintCatalogPage : IDisposable
|
||||||
{
|
{
|
||||||
[Inject] public ILocalStorageService Storage { get; set; }
|
[Inject] public ILocalStorageService Storage { get; set; }
|
||||||
[Inject] public ICatalogHttpRepository ItemRepo { get; set; }
|
[Inject] public ICatalogHttpRepository ItemRepo { get; set; }
|
32
Wonky.Client/Pages/PrintOrdersPage.razor
Normal file
32
Wonky.Client/Pages/PrintOrdersPage.razor
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
@*
|
||||||
|
// Copyright (C) 2022 FCS Frede's Computer Services.
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU Affero General Public License as
|
||||||
|
// published by the Free Software Foundation, either version 3 of the
|
||||||
|
// License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU Affero General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Affero General Public License
|
||||||
|
// along with this program. If not, see [https://www.gnu.org/licenses/agpl-3.0.en.html]
|
||||||
|
//
|
||||||
|
*@
|
||||||
|
|
||||||
|
@using Wonky.Client.Components
|
||||||
|
@using Microsoft.AspNetCore.Authorization
|
||||||
|
@page "/print/orders/{CountryCode}/{UserId}/{ReportDate}"
|
||||||
|
@attribute [Authorize(Roles = "Admin,Advisor")]
|
||||||
|
|
||||||
|
<div class="row mb-3 d-print-none">
|
||||||
|
<div class="col-sm-12 d-grid">
|
||||||
|
<button class="btn btn-primary" type="button" @onclick="Print">Print</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
@foreach (var item in Items.Where(item => item.StatusTypeEnum.ToLower() == "order" && item.ProcessStatusEnum.ToLower() == "none"))
|
||||||
|
{
|
||||||
|
<ReportItemComponent ReportItem="@item"></ReportItemComponent>
|
||||||
|
}
|
64
Wonky.Client/Pages/PrintOrdersPage.razor.cs
Normal file
64
Wonky.Client/Pages/PrintOrdersPage.razor.cs
Normal file
|
@ -0,0 +1,64 @@
|
||||||
|
// 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 Blazored.LocalStorage;
|
||||||
|
using Microsoft.AspNetCore.Components;
|
||||||
|
using Microsoft.JSInterop;
|
||||||
|
using Wonky.Entity.Views;
|
||||||
|
|
||||||
|
namespace Wonky.Client.Pages;
|
||||||
|
|
||||||
|
public partial class PrintOrdersPage
|
||||||
|
{
|
||||||
|
[Parameter] public string CountryCode { get; set; } = "";
|
||||||
|
[Parameter] public string UserId { get; set; } = "";
|
||||||
|
[Parameter] public string ReportDate { get; set; } = "";
|
||||||
|
[Inject] public ILocalStorageService Storage { get; set; }
|
||||||
|
[Inject] public NavigationManager Navigator { get; set; }
|
||||||
|
[Inject] private IJSRuntime JSRuntime { get; set; }
|
||||||
|
[Inject] public ILogger<PrintOrdersPage> Logger { get; set; }
|
||||||
|
private ReportView Report { get; set; } = new();
|
||||||
|
private List<ReportItemView> Items { get; set; } = new();
|
||||||
|
private IJSObjectReference JsModule { get; set; }
|
||||||
|
|
||||||
|
|
||||||
|
protected override async Task OnAfterRenderAsync(bool firstRender)
|
||||||
|
{
|
||||||
|
if (firstRender)
|
||||||
|
{
|
||||||
|
JsModule = await JSRuntime
|
||||||
|
.InvokeAsync<IJSObjectReference>("import", "/scripts/print-invoke.js");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override async Task OnInitializedAsync()
|
||||||
|
{
|
||||||
|
Report = await Storage.GetItemAsync<ReportView>($"{UserId}-{ReportDate}");
|
||||||
|
Items = Report.ReportItems;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task Print()
|
||||||
|
{
|
||||||
|
await JsModule.InvokeVoidAsync("printInvoke");
|
||||||
|
|
||||||
|
Navigator.NavigateTo($"/office/users/advisors/{CountryCode}/{UserId}/reports/{ReportDate}");
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* await Task.Delay(1000);
|
||||||
|
* JS.InvokeVoidAsync("invokePrint");
|
||||||
|
* InvokeAsync(() => StateHasChanged());
|
||||||
|
*/
|
||||||
|
}
|
46
Wonky.Client/Pages/PrintReportPage.razor
Normal file
46
Wonky.Client/Pages/PrintReportPage.razor
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
@*
|
||||||
|
// Copyright (C) 2022 FCS Frede's Computer Services.
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU Affero General Public License as
|
||||||
|
// published by the Free Software Foundation, either version 3 of the
|
||||||
|
// License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU Affero General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Affero General Public License
|
||||||
|
// along with this program. If not, see [https://www.gnu.org/licenses/agpl-3.0.en.html]
|
||||||
|
//
|
||||||
|
*@
|
||||||
|
|
||||||
|
@using Wonky.Client.Components
|
||||||
|
@using Microsoft.AspNetCore.Authorization
|
||||||
|
@page "/print/report/{CountryCode}/{UserId}/{ReportDate}"
|
||||||
|
@attribute [Authorize(Roles = "Admin,Advisor")]
|
||||||
|
|
||||||
|
<div class="row mb-3 d-print-none">
|
||||||
|
<div class="col-sm-12 d-grid">
|
||||||
|
<button class="btn btn-primary" type="button" @onclick="Print">Print</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="report-main d-print-grid">
|
||||||
|
<PageTitle>@Report.ReportData.Name</PageTitle>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col text-center align-content-center">
|
||||||
|
<h3>@Report.ReportData.Name</h3>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="w-75">
|
||||||
|
<ReportSummaryComponent ReportData="Report.ReportData"/>
|
||||||
|
</div>
|
||||||
|
<div class="w-25">
|
||||||
|
<ReportDistanceLedgerComponent ReportData="Report.ReportData"/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<OfficeActivityTableComponent ActivityList="Report.ReportItems"/>
|
||||||
|
<ReportActivityLedgerComponent ReportData="Report.ReportData"/>
|
||||||
|
</div>
|
63
Wonky.Client/Pages/PrintReportPage.razor.cs
Normal file
63
Wonky.Client/Pages/PrintReportPage.razor.cs
Normal file
|
@ -0,0 +1,63 @@
|
||||||
|
// 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 Blazored.LocalStorage;
|
||||||
|
using Microsoft.AspNetCore.Components;
|
||||||
|
using Microsoft.JSInterop;
|
||||||
|
using Wonky.Entity.Views;
|
||||||
|
|
||||||
|
namespace Wonky.Client.Pages;
|
||||||
|
|
||||||
|
public partial class PrintReportPage
|
||||||
|
{
|
||||||
|
[Parameter] public string CountryCode { get; set; } = "";
|
||||||
|
[Parameter] public string UserId { get; set; } = "";
|
||||||
|
[Parameter] public string ReportDate { get; set; } = "";
|
||||||
|
[Inject] public ILocalStorageService Storage { get; set; }
|
||||||
|
[Inject] public NavigationManager Navigator { get; set; }
|
||||||
|
[Inject] private IJSRuntime JSRuntime { get; set; }
|
||||||
|
[Inject] public ILogger<PrintReportPage> Logger { get; set; }
|
||||||
|
private ReportView Report { get; set; } = new();
|
||||||
|
private IJSObjectReference JsModule { get; set; }
|
||||||
|
private bool Printed { get; set; }
|
||||||
|
|
||||||
|
protected override async Task OnInitializedAsync()
|
||||||
|
{
|
||||||
|
Report = await Storage.GetItemAsync<ReportView>($"{UserId}-{ReportDate}");
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override async Task OnAfterRenderAsync(bool firstRender)
|
||||||
|
{
|
||||||
|
if (firstRender)
|
||||||
|
{
|
||||||
|
JsModule = await JSRuntime
|
||||||
|
.InvokeAsync<IJSObjectReference>("import", "/scripts/print-invoke.js");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task Print()
|
||||||
|
{
|
||||||
|
if(!Printed)
|
||||||
|
Printed = true;
|
||||||
|
await JsModule.InvokeVoidAsync("printInvoke");
|
||||||
|
Navigator.NavigateTo($"/office/users/advisors/{CountryCode}/{UserId}/reports/{ReportDate}");
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* await Task.Delay(1000);
|
||||||
|
* JS.InvokeVoidAsync("invokePrint");
|
||||||
|
* InvokeAsync(() => StateHasChanged());
|
||||||
|
*/
|
||||||
|
}
|
|
@ -13,11 +13,11 @@ using Wonky.Entity.Views;
|
||||||
|
|
||||||
namespace Wonky.Client.Pages;
|
namespace Wonky.Client.Pages;
|
||||||
|
|
||||||
public partial class CrmQuotesListPage : IDisposable
|
public partial class QuoteListPage : IDisposable
|
||||||
{
|
{
|
||||||
[Inject] public ICrmActivityHttpRepository ActivityRepo { get; set; }
|
[Inject] public ICrmActivityHttpRepository ActivityRepo { get; set; }
|
||||||
[Inject] public HttpInterceptorService Interceptor { get; set; }
|
[Inject] public HttpInterceptorService Interceptor { get; set; }
|
||||||
[Inject] public ILogger<CrmQuotesListPage> Logger { get; set; }
|
[Inject] public ILogger<QuoteListPage> Logger { get; set; }
|
||||||
[Inject] public IToastService Toaster { get; set; }
|
[Inject] public IToastService Toaster { get; set; }
|
||||||
[Inject] public ILocalStorageService Storage { get; set; }
|
[Inject] public ILocalStorageService Storage { get; set; }
|
||||||
private List<ReportItemView> Quotes { get; set; } = new();
|
private List<ReportItemView> Quotes { get; set; } = new();
|
|
@ -21,7 +21,7 @@ using Wonky.Client.HttpRepository;
|
||||||
|
|
||||||
namespace Wonky.Client.Pages;
|
namespace Wonky.Client.Pages;
|
||||||
|
|
||||||
public partial class CrmWorkplaceDocumentListPage
|
public partial class WorkplaceDocumentListPage
|
||||||
{
|
{
|
||||||
[Parameter] public string CompanyId { get; set; } = "";
|
[Parameter] public string CompanyId { get; set; } = "";
|
||||||
[Parameter] public string WorkplaceId { get; set; } = "";
|
[Parameter] public string WorkplaceId { get; set; } = "";
|
|
@ -24,7 +24,7 @@ using Wonky.Entity.Views;
|
||||||
|
|
||||||
namespace Wonky.Client.Pages;
|
namespace Wonky.Client.Pages;
|
||||||
|
|
||||||
public partial class CrmWorkplaceListPage : IDisposable
|
public partial class WorkplaceListPage : IDisposable
|
||||||
{
|
{
|
||||||
[Parameter] public string CompanyId { get; set; } = "";
|
[Parameter] public string CompanyId { get; set; } = "";
|
||||||
[Inject] public ICrmWorkplaceHttpRepository CrmWorkplaceRepo { get; set; }
|
[Inject] public ICrmWorkplaceHttpRepository CrmWorkplaceRepo { get; set; }
|
|
@ -25,7 +25,7 @@ using Wonky.Entity.Views;
|
||||||
|
|
||||||
namespace Wonky.Client.Pages;
|
namespace Wonky.Client.Pages;
|
||||||
|
|
||||||
public partial class CrmWorkplaceViewPage : IDisposable
|
public partial class WorkplaceViewPage : IDisposable
|
||||||
{
|
{
|
||||||
[Parameter] public string CompanyId { get; set; } = "";
|
[Parameter] public string CompanyId { get; set; } = "";
|
||||||
[Parameter] public string WorkplaceId { get; set; } = "";
|
[Parameter] public string WorkplaceId { get; set; } = "";
|
|
@ -120,7 +120,7 @@ namespace Wonky.Client.Services
|
||||||
{
|
{
|
||||||
((AuthStateProvider)_authStateProvider).NotifyUserLogout();
|
((AuthStateProvider)_authStateProvider).NotifyUserLogout();
|
||||||
_client.DefaultRequestHeaders.Authorization = null;
|
_client.DefaultRequestHeaders.Authorization = null;
|
||||||
await _localStorage.RemoveItemsAsync(new List<string> {"_xa", "_xe", "_xr", "_xu"});
|
await _localStorage.ClearAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<UserInfoView> UserInfo(bool write = false)
|
public async Task<UserInfoView> UserInfo(bool write = false)
|
||||||
|
|
39
Wonky.Client/Shared/ConfirmProductCheckModal.razor
Normal file
39
Wonky.Client/Shared/ConfirmProductCheckModal.razor
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
@*
|
||||||
|
// 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
|
||||||
|
<div class="modal" tabindex="-1" role="dialog" style="display:@_modalDisplay">
|
||||||
|
<div class="modal-dialog modal-dialog-scrollable modal-lg modal-xl">
|
||||||
|
<div class="modal-content">
|
||||||
|
<div class="modal-header">
|
||||||
|
<h2 class="modal-title">PRODUKT GENNEMGANG</h2>
|
||||||
|
<button type="button" class="btn-close" @onclick="Hide" data-bs-dismiss="modal" aria-label="Luk"></button>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body">
|
||||||
|
@((MarkupString) BodyMessage)
|
||||||
|
<CustomerProductCheckListComponent CompanyId="@CompanyId" ProductList="@Products" />
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer">
|
||||||
|
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal" @onclick="Hide">Afbryd</button>
|
||||||
|
<button type="button" class="btn btn-primary" data-bs-dismiss="modal" @onclick="() => OnOkClicked.InvokeAsync()">OK</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
@if (_showBackdrop)
|
||||||
|
{
|
||||||
|
<div class="modal-backdrop fade show"></div>
|
||||||
|
}
|
43
Wonky.Client/Shared/ConfirmProductCheckModal.razor.cs
Normal file
43
Wonky.Client/Shared/ConfirmProductCheckModal.razor.cs
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
// 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.Shared;
|
||||||
|
|
||||||
|
public partial class ConfirmProductCheckModal
|
||||||
|
{
|
||||||
|
private string _modalDisplay = "";
|
||||||
|
private bool _showBackdrop;
|
||||||
|
[Parameter] public string BodyMessage { get; set; } = "";
|
||||||
|
[Parameter] public string CompanyId { get; set; } = "";
|
||||||
|
[Parameter] public List<ProductInventoryView> Products { get; set; } = new();
|
||||||
|
[Parameter] public EventCallback OnOkClicked { get; set; }
|
||||||
|
|
||||||
|
public void Show()
|
||||||
|
{
|
||||||
|
_modalDisplay = "block;";
|
||||||
|
_showBackdrop = true;
|
||||||
|
StateHasChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Hide()
|
||||||
|
{
|
||||||
|
_modalDisplay = "none;";
|
||||||
|
_showBackdrop = false;
|
||||||
|
StateHasChanged();
|
||||||
|
}
|
||||||
|
}
|
|
@ -32,6 +32,6 @@
|
||||||
<div class="content d-none d-print-block">
|
<div class="content d-none d-print-block">
|
||||||
@Body
|
@Body
|
||||||
</div>
|
</div>
|
||||||
<BlazoredToasts Position="ToastPosition.BottomCenter" Timeout="5"/>
|
<BlazoredToasts Position="ToastPosition.BottomRight" Timeout="10" />
|
||||||
</main>
|
</main>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
{
|
{
|
||||||
"appInfo": {
|
"appInfo": {
|
||||||
"name": "Wonky Client",
|
"name": "Wonky Client",
|
||||||
"version": "0.86.0",
|
"version": "0.87.1",
|
||||||
"rc": true,
|
"rc": true,
|
||||||
"sandBox": false,
|
"sandBox": false,
|
||||||
"image": "grumpy-coder.png"
|
"image": "grumpy-coder.png"
|
||||||
},
|
},
|
||||||
"apiConfig": {
|
"apiConfig": {
|
||||||
"baseUrl": "https://dev.innotec.dk",
|
"baseUrl": "https://zeta.innotec.dk",
|
||||||
"catalog": "api/v2/catalog",
|
"catalog": "api/v2/catalog",
|
||||||
"crmCustomers": "api/v2/crm/companies",
|
"crmCustomers": "api/v2/crm/companies",
|
||||||
"crmInventoryExt": "history/inventory",
|
"crmInventoryExt": "history/inventory",
|
||||||
|
@ -34,7 +34,7 @@
|
||||||
},
|
},
|
||||||
"Logging": {
|
"Logging": {
|
||||||
"LogLevel": {
|
"LogLevel": {
|
||||||
"Default": "Information",
|
"Default": "Debug",
|
||||||
"System": "Information",
|
"System": "Information",
|
||||||
"Microsoft": "Information"
|
"Microsoft": "Information"
|
||||||
},
|
},
|
||||||
|
|
|
@ -152,55 +152,3 @@ footer.version {
|
||||||
right: 25px;
|
right: 25px;
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* printer classes */
|
|
||||||
@media print {
|
|
||||||
@page {
|
|
||||||
size: a4;
|
|
||||||
}
|
|
||||||
@font-face {
|
|
||||||
font-family: 'Montserrat';
|
|
||||||
src: url('https://fonts.googleapis.com/css2?family=Montserrat&display=swap');
|
|
||||||
}
|
|
||||||
html, body {
|
|
||||||
height: 290mm;
|
|
||||||
width: 210mm;
|
|
||||||
-webkit-print-color-adjust: exact;
|
|
||||||
color-adjust: exact;
|
|
||||||
}
|
|
||||||
.report-main {
|
|
||||||
font-size: 10px;
|
|
||||||
break-before: page;
|
|
||||||
break-after: page;
|
|
||||||
page-break-after: always;
|
|
||||||
height: initial;
|
|
||||||
border: initial;
|
|
||||||
border-radius: initial;
|
|
||||||
box-shadow: initial;
|
|
||||||
margin: 0;
|
|
||||||
width: initial;
|
|
||||||
-webkit-print-color-adjust: exact;
|
|
||||||
color-adjust: exact;
|
|
||||||
}
|
|
||||||
.report-visit {
|
|
||||||
page-break-before: always;
|
|
||||||
break-after: page;
|
|
||||||
break-before: page;
|
|
||||||
break-inside: avoid-page;
|
|
||||||
height: initial;
|
|
||||||
border: initial;
|
|
||||||
border-radius: initial;
|
|
||||||
box-shadow: initial;
|
|
||||||
margin: 0;
|
|
||||||
width: initial;
|
|
||||||
-webkit-print-color-adjust: exact;
|
|
||||||
color-adjust: exact;
|
|
||||||
}
|
|
||||||
.distance-ledger {}
|
|
||||||
.report-ledger {
|
|
||||||
page-break-inside: avoid;
|
|
||||||
page-break-after: always;
|
|
||||||
break-after: recto;
|
|
||||||
min-height: 300px;
|
|
||||||
}
|
|
||||||
}
|
|
53
Wonky.Client/wwwroot/css/print.css
Normal file
53
Wonky.Client/wwwroot/css/print.css
Normal file
|
@ -0,0 +1,53 @@
|
||||||
|
/* printer classes */
|
||||||
|
@media print {
|
||||||
|
@page {
|
||||||
|
size: a4;
|
||||||
|
}
|
||||||
|
@font-face {
|
||||||
|
font-family: 'Montserrat';
|
||||||
|
src: url('https://fonts.googleapis.com/css2?family=Montserrat&display=swap');
|
||||||
|
}
|
||||||
|
html, body {
|
||||||
|
height: 290mm;
|
||||||
|
width: 210mm;
|
||||||
|
-webkit-print-color-adjust: exact;
|
||||||
|
color-adjust: exact;
|
||||||
|
}
|
||||||
|
.report-main {
|
||||||
|
font-size: 10px;
|
||||||
|
break-before: page;
|
||||||
|
break-after: page;
|
||||||
|
page-break-after: always;
|
||||||
|
height: initial;
|
||||||
|
border: initial;
|
||||||
|
border-radius: initial;
|
||||||
|
box-shadow: initial;
|
||||||
|
margin: 0;
|
||||||
|
width: initial;
|
||||||
|
-webkit-print-color-adjust: exact;
|
||||||
|
color-adjust: exact;
|
||||||
|
}
|
||||||
|
.report-visit {
|
||||||
|
page-break-before: always;
|
||||||
|
page-break-after: always;
|
||||||
|
break-after: page;
|
||||||
|
break-before: page;
|
||||||
|
break-inside: avoid-page;
|
||||||
|
height: initial;
|
||||||
|
border: initial;
|
||||||
|
border-radius: initial;
|
||||||
|
box-shadow: initial;
|
||||||
|
min-height: 250mm;
|
||||||
|
margin: 0;
|
||||||
|
width: initial;
|
||||||
|
-webkit-print-color-adjust: exact;
|
||||||
|
color-adjust: exact;
|
||||||
|
}
|
||||||
|
.distance-ledger {}
|
||||||
|
.report-ledger {
|
||||||
|
page-break-inside: avoid;
|
||||||
|
page-break-after: always;
|
||||||
|
break-after: recto;
|
||||||
|
min-height: 300px;
|
||||||
|
}
|
||||||
|
}
|
|
@ -14,12 +14,13 @@
|
||||||
<meta name="application-TileColor" content="#ffaa00" />
|
<meta name="application-TileColor" content="#ffaa00" />
|
||||||
<meta name="theme-color" content="#000" />
|
<meta name="theme-color" content="#000" />
|
||||||
<base href="/" />
|
<base href="/" />
|
||||||
<link href="bootstrap/css/bootstrap.min.css" rel="stylesheet" />
|
<link href="/bootstrap/css/bootstrap.min.css" rel="stylesheet" />
|
||||||
<link href="bootstrap/css/bootstrap-icons.css" rel="stylesheet" />
|
<link href="/bootstrap/css/bootstrap-icons.css" rel="stylesheet" />
|
||||||
<link href="flag-icons/flag-icons.css" rel="stylesheet" />
|
<link href="/flag-icons/flag-icons.css" rel="stylesheet" />
|
||||||
<link href="css/app-v0.38.css" rel="stylesheet" />
|
<link href="/css/app.css" rel="stylesheet" />
|
||||||
<link href="Wonky.Client.styles.css" rel="stylesheet" />
|
<link href="/css/print.css" rel="stylesheet" />
|
||||||
<link href="_content/Blazored.Toast/blazored-toast.min.css" rel="stylesheet" />
|
<link href="/Wonky.Client.styles.css" rel="stylesheet" />
|
||||||
|
<link href="/_content/Blazored.Toast/blazored-toast.min.css" rel="stylesheet" />
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="app">
|
<div id="app">
|
||||||
|
@ -29,7 +30,7 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<script src="/bootstrap/js/bootstrap.bundle.js"></script>
|
<script src="/bootstrap/js/bootstrap.bundle.js"></script>
|
||||||
<!--<script src="/scripts/bsTooltip.js"></script>-->
|
<script src="/_framework/blazor.webassembly.js"></script>
|
||||||
<script src="_framework/blazor.webassembly.js"></script>
|
<script src="/scripts/print-invoke.js" defer></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
@ -1,4 +0,0 @@
|
||||||
var tooltipTriggerList = [].slice.call(document.querySelectorAll('[data-bs-toggle="tooltip"]'))
|
|
||||||
var tooltipList = tooltipTriggerList.map(function (tooltipTriggerEl) {
|
|
||||||
return new bootstrap.Tooltip(tooltipTriggerEl)
|
|
||||||
})
|
|
7
Wonky.Client/wwwroot/scripts/print-invoke.js
Normal file
7
Wonky.Client/wwwroot/scripts/print-invoke.js
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
export function printInvoke() {
|
||||||
|
window.print();
|
||||||
|
}
|
||||||
|
|
||||||
|
document.addEventListener("load", function() {
|
||||||
|
window.print();
|
||||||
|
});
|
|
@ -1,16 +0,0 @@
|
||||||
(document).ready(function(){
|
|
||||||
$(window).scroll(function () {
|
|
||||||
if ($(this).scrollTop() > 50) {
|
|
||||||
$('#back-to-top').fadeIn();
|
|
||||||
} else {
|
|
||||||
$('#back-to-top').fadeOut();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
// scroll body to 0px on click
|
|
||||||
$('#back-to-top').click(function () {
|
|
||||||
$('body,html').animate({
|
|
||||||
scrollTop: 0
|
|
||||||
}, 400);
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -29,4 +29,8 @@ public class ProductInventoryView
|
||||||
/// quantity bought over time
|
/// quantity bought over time
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public int Quantity { get; set; }
|
public int Quantity { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
/// Virtual checkmark
|
||||||
|
/// </summary>
|
||||||
|
public virtual bool Check { get; set; }
|
||||||
}
|
}
|
|
@ -15,7 +15,7 @@
|
||||||
|
|
||||||
namespace Wonky.Entity.Views;
|
namespace Wonky.Entity.Views;
|
||||||
|
|
||||||
public class NgSalesReportListView
|
public class SalesReportListView
|
||||||
{
|
{
|
||||||
public string ReportId { get; set; } = "";
|
public string ReportId { get; set; } = "";
|
||||||
public string UserId { get; set; } = "";
|
public string UserId { get; set; } = "";
|
Loading…
Reference in a new issue