FEAT: add statistic page, add history filter class

REN: drawer cabinet service -> cabinet drawer service
FIX: page size component - prefix function call
WIP: create user with web shop permission - attach to company
FEAT: add workaround for Swedish moms numbers - new api call
FIX: advisor create activity page
FIX: advisor customer CRM data edit and reload
FEAT: add button to statistic on customer view page
FIX: advisor customer create - set correct segment for no and se
This commit is contained in:
Frede Hundewadt 2023-06-09 13:38:36 +02:00
parent 7d21b834fc
commit 2d9ee3c9ce
33 changed files with 703 additions and 450 deletions

View file

@ -35,7 +35,7 @@ public partial class AdvisorLandingComponent
{ {
// ############################################################## // ##############################################################
[Inject] public UserPreferenceService PreferenceService { get; set; } [Inject] public UserPreferenceService PreferenceService { get; set; }
[Inject] public IDrawerCabinetService DrawerCabinetService { get; set; } [Inject] public ICabinetDrawerService CabinetDrawerService { get; set; }
[Inject] public IUserInfoService UserInfo { get; set; } [Inject] public IUserInfoService UserInfo { get; set; }
[Inject] public ICountryCatalogRepository CatalogRepo { get; set; } [Inject] public ICountryCatalogRepository CatalogRepo { get; set; }
@ -60,7 +60,7 @@ public partial class AdvisorLandingComponent
// if (firstRender) // if (firstRender)
// { // {
// var countryCode = await UserInfo.GetCountryCode(); // var countryCode = await UserInfo.GetCountryCode();
// var _ = await DrawerCabinetService.GetCatalogDrawer(countryCode); // var _ = await CabinetDrawerService.GetCatalogDrawer(countryCode);
// } // }
// } // }
} }

View file

@ -1,72 +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 (Inventory.Any())
{
<table class="table table-striped">
<thead>
<tr class="rounded-2 border border-1">
<th scope="col">
Dato
</th>
<th scope="col">
Antal
</th>
<th scope="col">
Vare
</th>
<th scope="col">
Varenummer
</th>
<th scope="col" class="align-content-end">
Rabat
</th>
<th scope="col" class="align-content-end">
Pris
</th>
</tr>
</thead>
<tbody>
@foreach (var line in Inventory)
{
<tr class="align-content-center">
<td>
@line.DeliveryDate
</td>
<td>
@line.Quantity
</td>
<td>
@line.Description
</td>
<td>
@line.Sku
</td>
<td class="align-content-end">
@(line.Discount)%
</td>
<td class="align-content-end">
@line.Price
</td>
</tr>
}
</tbody>
</table>
}
else
{
<div>Ingen data</div>
}

View file

@ -1,30 +0,0 @@
// Copyright (C) 2022 FCS Frede's Computer Services.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see [https://www.gnu.org/licenses/agpl-3.0.en.html]
//
using Microsoft.AspNetCore.Components;
using Wonky.Entity.Views;
namespace Wonky.Client.Components;
public partial class CustomerProductLineListComponent
{
[Parameter] public List<ProductHistoryView> Inventory { get; set; } = new();
protected override void OnParametersSet()
{
if(Inventory.Any())
Inventory = Inventory.OrderBy(x => x.Description).ToList();
}
}

View file

@ -14,7 +14,7 @@
*@ *@
<select class="form-select bg-info text-bg-info" @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>ANTAL svar</option> <option value="-1" selected disabled>ANTAL svar</option>
<option value="5">5 svar</option> <option value="5">5 svar</option>
<option value="10">10 svar</option> <option value="10">10 svar</option>

View file

@ -6,9 +6,9 @@ namespace Wonky.Client.Helpers;
public class Mapper public class Mapper
{ {
public static UserManagerCreateView MapCreateUser(CreateUserInputModel model) public static ManagerNewUserDto MapCreateUser(NewUserForm model)
{ {
return new UserManagerCreateView return new ManagerNewUserDto
{ {
Description = model.Description, Description = model.Description,
Email = model.Email, Email = model.Email,

View file

@ -90,10 +90,13 @@ public class VatUtils
var vatToCheck = vatNumber; var vatToCheck = vatNumber;
if (long.Parse(vatToCheck) == 0) if (long.Parse(vatToCheck) == 0)
return false; return false;
switch (vatToCheck.Length) switch (vatToCheck.Length)
{ {
// if less than 10 chars validate as SSI /*
* if less than 10 chars validate as SSI
* only the first 6 chars are known
* yyMMdd
*/
case 6: case 6:
return ValidateFormatSeExt(vatToCheck); return ValidateFormatSeExt(vatToCheck);
case < 10: case < 10:
@ -102,12 +105,17 @@ public class VatUtils
vatNumber = vatNumber[..10]; vatNumber = vatNumber[..10];
break; break;
} }
// calculate check digit /*
* calculate check digit
*/
var c10 = C10(vatToCheck); var c10 = C10(vatToCheck);
// return comparison /*
* return comparison
*/
return $"{vatToCheck[..9]}{c10}" == vatNumber; return $"{vatToCheck[..9]}{c10}" == vatNumber;
} }
/// <summary> /// <summary>
/// Calculate check digit for swedish org number /// Calculate check digit for swedish org number
/// </summary> /// </summary>
@ -115,14 +123,15 @@ public class VatUtils
/// <returns></returns> /// <returns></returns>
private static int C10(string orgNumber) private static int C10(string orgNumber)
{ {
// https://wiki.scn.sap.com/wiki/display/CRM/Sweden /*
// 12 digits 0 to 9 * https://wiki.scn.sap.com/wiki/display/CRM/Sweden
// C10 = (10 (18 + 5 + 1 + 8 + 4)MOD10 10) MOD10 * 12 digits 0 to 9
// R = S1 + S3 + S5 + S7 + S9 * C10 = (10 (18 + 5 + 1 + 8 + 4)MOD10 10) MOD10
// Si = int(Ci/5) + (Ci*2)MOD10) * R = S1 + S3 + S5 + S7 + S9
// https://www.skatteverket.se/skatter/mervardesskattmoms/momsregistreringsnummer.4.18e1b10334ebe8bc80002649.html * Si = int(Ci/5) + (Ci*2)MOD10)
// C11 C12 == 01 (De två sista siffrorna är alltid 01) * https://www.skatteverket.se/skatter/mervardesskattmoms/momsregistreringsnummer.4.18e1b10334ebe8bc80002649.html
* C11 C12 == 01 (De två sista siffrorna är alltid 01)
*/
var r = new[] { 0, 2, 4, 6, 8 } var r = new[] { 0, 2, 4, 6, 8 }
.Sum(m => (int)char.GetNumericValue(orgNumber[m]) / 5 + .Sum(m => (int)char.GetNumericValue(orgNumber[m]) / 5 +
(int)char.GetNumericValue(orgNumber[m]) * 2 % 10); (int)char.GetNumericValue(orgNumber[m]) * 2 % 10);
@ -130,8 +139,9 @@ public class VatUtils
var c10 = (10 - (r + c1) % 10) % 10; var c10 = (10 - (r + c1) % 10) % 10;
return c10; return c10;
// end check digit calculation // end check digit calculation
} }
/// <summary> /// <summary>
/// ///
/// </summary> /// </summary>
@ -173,6 +183,7 @@ public class VatUtils
} }
} }
/// <summary> /// <summary>
/// Modulus11 validator /// Modulus11 validator
/// </summary> /// </summary>

View file

@ -47,7 +47,7 @@ public interface ISystemUserRepository
/// </summary> /// </summary>
/// <param name="model"></param> /// <param name="model"></param>
/// <returns></returns> /// <returns></returns>
Task<UserManagerEditView> CreateUser(UserManagerCreateView model); Task<UserManagerEditView> PostNewUser(ManagerNewUserDto model);
/// <summary> /// <summary>
/// Update User using userId and updated data /// Update User using userId and updated data

View file

@ -72,7 +72,7 @@ public class SystemUserRepository : ISystemUserRepository
/// </summary> /// </summary>
/// <param name="model"></param> /// <param name="model"></param>
/// <returns></returns> /// <returns></returns>
public async Task<UserManagerEditView> CreateUser(UserManagerCreateView model) public async Task<UserManagerEditView> PostNewUser(ManagerNewUserDto model)
{ {
var result = await _client.PostAsJsonAsync($"{_api.UserManager}", model, _options); var result = await _client.PostAsJsonAsync($"{_api.UserManager}", model, _options);
if (!result.IsSuccessStatusCode) if (!result.IsSuccessStatusCode)

View file

@ -5,15 +5,14 @@ using Wonky.Client.Models;
namespace Wonky.Client.Local.Services; namespace Wonky.Client.Local.Services;
public class DrawerCabinetService : IDrawerCabinetService public class CabinetDrawerService : ICabinetDrawerService
{ {
private readonly JsonSerializerOptions _options = new () private readonly JsonSerializerOptions _options = new ()
{ {
PropertyNameCaseInsensitive = true PropertyNameCaseInsensitive = true
}; };
private readonly ILogger<DrawerCabinetService> _logger; private readonly ILogger<CabinetDrawerService> _logger;
private readonly ILocalStorageService _asyncStorageService; private readonly ILocalStorageService _asyncStorageService;
private readonly ISyncLocalStorageService _syncStorageService;
private readonly IAdvisorActivityRepository _activityRepo; private readonly IAdvisorActivityRepository _activityRepo;
private readonly IAdvisorCustomerRepository _customerRepo; private readonly IAdvisorCustomerRepository _customerRepo;
private readonly IAdvisorCustomerHistoryRepository _historyRepo; private readonly IAdvisorCustomerHistoryRepository _historyRepo;
@ -24,15 +23,13 @@ public class DrawerCabinetService : IDrawerCabinetService
/// </summary> /// </summary>
/// <param name="logger"></param> /// <param name="logger"></param>
/// <param name="asyncStorageService"></param> /// <param name="asyncStorageService"></param>
/// <param name="syncStorageService"></param>
/// <param name="catalogRepo"></param> /// <param name="catalogRepo"></param>
/// <param name="historyRepo"></param> /// <param name="historyRepo"></param>
/// <param name="customerRepo"></param> /// <param name="customerRepo"></param>
/// <param name="activityRepo"></param> /// <param name="activityRepo"></param>
public DrawerCabinetService( public CabinetDrawerService(
ILogger<DrawerCabinetService> logger, ILogger<CabinetDrawerService> logger,
ILocalStorageService asyncStorageService, ILocalStorageService asyncStorageService,
ISyncLocalStorageService syncStorageService,
ICountryCatalogRepository catalogRepo, ICountryCatalogRepository catalogRepo,
IAdvisorCustomerHistoryRepository historyRepo, IAdvisorCustomerHistoryRepository historyRepo,
IAdvisorCustomerRepository customerRepo, IAdvisorCustomerRepository customerRepo,
@ -40,7 +37,6 @@ public class DrawerCabinetService : IDrawerCabinetService
{ {
_logger = logger; _logger = logger;
_asyncStorageService = asyncStorageService; _asyncStorageService = asyncStorageService;
_syncStorageService = syncStorageService;
_catalogRepo = catalogRepo; _catalogRepo = catalogRepo;
_historyRepo = historyRepo; _historyRepo = historyRepo;
_customerRepo = customerRepo; _customerRepo = customerRepo;
@ -196,10 +192,19 @@ public class DrawerCabinetService : IDrawerCabinetService
if (force) if (force)
{ {
var result = await _historyRepo.GetProductInvoiceLines(companyId); var result = await _historyRepo.GetProductInvoiceLines(companyId);
var content = result.Select(x => new HistoryFilter
{
DeliveryDate = DateTime.Parse(x.DeliveryDate),
Description = x.Description,
Discount = x.Discount,
Price = x.Price,
Quantity = x.Quantity,
Sku = x.Sku
}).ToList();
drawer = new StatisticDrawer drawer = new StatisticDrawer
{ {
LastDateModified = DateTime.Today, LastDateModified = DateTime.Today,
Content = result Content = content
}; };
await StoreStatisticDrawerAsync(companyId, drawer); await StoreStatisticDrawerAsync(companyId, drawer);
} }

View file

@ -4,7 +4,7 @@ using Wonky.Entity.DTO;
namespace Wonky.Client.Local.Services; namespace Wonky.Client.Local.Services;
public interface IDrawerCabinetService public interface ICabinetDrawerService
{ {
Task<ActivityDrawer> GetActivityDrawerAsync(string companyId, bool force = false); Task<ActivityDrawer> GetActivityDrawerAsync(string companyId, bool force = false);
Task<CatalogDrawer> GetCatalogDrawerAsync(string countryCode, bool force = false); Task<CatalogDrawer> GetCatalogDrawerAsync(string countryCode, bool force = false);

View file

@ -0,0 +1,8 @@
using Wonky.Client.Models;
namespace Wonky.Client.Local.Services;
public interface ISwedishPersonalOrgService
{
Task<PersonalOrgNumber> GetPersonalOrgNumber(string companyName);
}

View file

@ -0,0 +1,47 @@
using System.Text;
using System.Text.Json;
using System.Text.RegularExpressions;
using Microsoft.Extensions.Options;
using Wonky.Client.Models;
using Wonky.Entity.Configuration;
using Wonky.Entity.Views;
namespace Wonky.Client.Local.Services;
public class SwedishPersonalOrgService : ISwedishPersonalOrgService
{
private readonly ILogger<SwedishPersonalOrgService> _logger;
private readonly HttpClient _client;
private readonly ApiConfig _api;
public SwedishPersonalOrgService(HttpClient client, ILogger<SwedishPersonalOrgService> logger, IOptions<ApiConfig> api)
{
_client = client;
_logger = logger;
_api = api.Value;
}
public async Task<PersonalOrgNumber> GetPersonalOrgNumber(string companyName)
{
var result = new PersonalOrgNumber
{
CompanyName = companyName,
PersonalId = ""
};
var response = await _client.GetAsync($"{_api.ServicesVatSe}?companyName={companyName}");
var content = await response.Content.ReadAsStringAsync();
_logger.LogDebug("response {}", content);
if (!response.IsSuccessStatusCode)
{
return result;
}
result.PersonalId = content.Replace("\"", "");
return result;
}
}

View file

@ -0,0 +1,11 @@
namespace Wonky.Client.Models;
public class HistoryFilter
{
public DateTime DeliveryDate { get; set; }
public string Description { get; set; } = "";
public string Sku { get; set; } = "";
public int Quantity { get; set; }
public decimal Price { get; set; }
public decimal Discount { get; set; }
}

View file

@ -3,7 +3,7 @@ using Wonky.Entity.DTO;
namespace Wonky.Client.Models; namespace Wonky.Client.Models;
public class CreateUserInputModel public class NewUserForm
{ {
[MaxLength(128)] public string CompanyId { get; set; } = ""; [MaxLength(128)] public string CompanyId { get; set; } = "";

View file

@ -0,0 +1,7 @@
namespace Wonky.Client.Models;
public class PersonalOrgNumber
{
public string CompanyName { get; set; } = "";
public string PersonalId { get; set; } = "";
}

View file

@ -6,5 +6,5 @@ public class StatisticDrawer
{ {
public const string Label = "Statistic"; public const string Label = "Statistic";
public DateTime LastDateModified { get; set; } public DateTime LastDateModified { get; set; }
public List<ProductHistoryView> Content { get; set; } = new(); public List<HistoryFilter> Content { get; set; } = new();
} }

View file

@ -170,10 +170,16 @@ else
</div> </div>
<div class="col-sm-6"></div> <div class="col-sm-6"></div>
<label for="vatNumber" class="col-sm-2 col-form-label-sm">Cvr/Org nr.</label> <label for="vatNumber" class="col-sm-2 col-form-label-sm">Cvr/Org nr.</label>
<div class="col-sm-4"> <div class="col-sm-2">
<InputText id="vatNumber" class="form-control" @bind-Value="Activity.VatNumber"/> <InputText id="vatNumber" class="form-control" @bind-Value="Activity.VatNumber"/>
<ValidationMessage For="@(() => Activity.VatNumber)"/> <ValidationMessage For="@(() => Activity.VatNumber)"/>
</div> </div>
<div class="col-sm-2">
@if (Activity.CountryCode.ToLower() == "se")
{
<button type="button" class="btn btn-warning" @onclick="@TestOrgNumber">ORG Nr.</button>
}
</div>
<label for="orderMessage" class="col-sm-2 col-form-label-sm">Note /Kontor</label> <label for="orderMessage" class="col-sm-2 col-form-label-sm">Note /Kontor</label>
<div class="col-sm-4"> <div class="col-sm-4">
<InputTextArea id="orderMessage" class="form-control" @bind-Value="Activity.OrderMessage"/> <InputTextArea id="orderMessage" class="form-control" @bind-Value="Activity.OrderMessage"/>

View file

@ -50,7 +50,8 @@ public partial class AdvisorActivityCreatePage : IDisposable
[Inject] public IAdvisorSalesReportRepository ReportRepo { get; set; } [Inject] public IAdvisorSalesReportRepository ReportRepo { get; set; }
[Inject] public IAdvisorCustomerHistoryRepository HistoryRepo { get; set; } [Inject] public IAdvisorCustomerHistoryRepository HistoryRepo { get; set; }
[Inject] public IUserInfoService UserInfo { get; set; } [Inject] public IUserInfoService UserInfo { get; set; }
[Inject] public IDrawerCabinetService CabinetService { get; set; } [Inject] public ICabinetDrawerService DrawerService { get; set; }
[Inject] public ISwedishPersonalOrgService OrgService { get; set; }
// ############################################################# // #############################################################
[CascadingParameter] private DraftStateProvider DraftProvider { get; set; } = new(); [CascadingParameter] private DraftStateProvider DraftProvider { get; set; } = new();
@ -101,8 +102,8 @@ public partial class AdvisorActivityCreatePage : IDisposable
protected override async Task OnInitializedAsync() protected override async Task OnInitializedAsync()
{ {
ActivityContext = new EditContext(Activity); ActivityContext = new EditContext(Activity);
ActivityContext.OnFieldChanged += HandleFieldChanged; ActivityContext.OnFieldChanged += ContextHandleFieldChanged;
ActivityContext.OnValidationStateChanged += ValidationChanged; ActivityContext.OnValidationStateChanged += ContextValidationChanged;
Interceptor.RegisterEvent(); Interceptor.RegisterEvent();
Interceptor.RegisterBeforeSendEvent(); Interceptor.RegisterBeforeSendEvent();
@ -111,10 +112,10 @@ public partial class AdvisorActivityCreatePage : IDisposable
// User Info // User Info
SalesRep = await UserInfo.GetUserInfo(); SalesRep = await UserInfo.GetUserInfo();
_infoDrawer = await CabinetService.GetInfoDrawerAsync(CompanyId); _infoDrawer = await DrawerService.GetInfoDrawerAsync(CompanyId);
_activityDrawer = await CabinetService.GetActivityDrawerAsync(CompanyId); _activityDrawer = await DrawerService.GetActivityDrawerAsync(CompanyId);
_inventoryDrawer = await CabinetService.GetInventoryDrawerAsync(CompanyId); _inventoryDrawer = await DrawerService.GetInventoryDrawerAsync(CompanyId);
_invoiceDrawer = await CabinetService.GetInvoiceDrawerAsync(CompanyId); _invoiceDrawer = await DrawerService.GetInvoiceDrawerAsync(CompanyId);
Company = _infoDrawer.Content; Company = _infoDrawer.Content;
@ -139,11 +140,12 @@ public partial class AdvisorActivityCreatePage : IDisposable
Activity.ActivityVisitEnum = Company.Account.StartsWith("NY") Activity.ActivityVisitEnum = Company.Account.StartsWith("NY")
? "new" ? "new"
: "recall"; : "recall";
if (string.IsNullOrWhiteSpace(Company.Segment) && SalesRep.CountryCode.ToLower() == "dk")
{ // if (string.IsNullOrWhiteSpace(Company.Segment) && SalesRep.CountryCode.ToLower() == "dk")
Toaster.ShowError("Der mangler information om Segment. Ret kunde segment, gem erp data og prøv igen."); // {
Navigator.NavigateTo($"/advisor/customers/{CompanyId}"); // Toaster.ShowError("Der mangler information om Segment. Ret kunde segment, gem erp data og prøv igen.");
} // // Navigator.NavigateTo($"/advisor/customers/{CompanyId}");
// }
} }
// Populate base activity information // Populate base activity information
@ -170,8 +172,15 @@ public partial class AdvisorActivityCreatePage : IDisposable
Activity.Segment = Company.Segment; Activity.Segment = Company.Segment;
Activity.EanNumber = Company.EanNumber; Activity.EanNumber = Company.EanNumber;
// Initialize date variable /*
* debug loggin
*/
Logger.LogDebug("company.segment = {}", Company.Segment);
Logger.LogDebug("activity.segment = {}", Activity.Segment);
Logger.LogDebug("AdvisorActivityCreatePage => DateTime parser => {}", UserPreference.WorkDate); Logger.LogDebug("AdvisorActivityCreatePage => DateTime parser => {}", UserPreference.WorkDate);
/*
* set selected date
*/
SelectedDate = string.IsNullOrWhiteSpace(UserPreference.WorkDate) SelectedDate = string.IsNullOrWhiteSpace(UserPreference.WorkDate)
? DateTime.Now ? DateTime.Now
: DateTime.Parse(UserPreference.WorkDate); : DateTime.Parse(UserPreference.WorkDate);
@ -200,11 +209,27 @@ public partial class AdvisorActivityCreatePage : IDisposable
PoFormInvalid = false; PoFormInvalid = false;
} }
if (SalesRep.CountryCode.ToLower() == "se")
{
await TestOrgNumber();
}
Working = false; Working = false;
StateHasChanged(); StateHasChanged();
} }
private async Task TestOrgNumber()
{
var result = await OrgService.GetPersonalOrgNumber(Activity.Name);
if (!string.IsNullOrWhiteSpace(result.PersonalId))
{
// Toaster.ShowSuccess($"PersonId for {result.CompanyName} er fundet til at være {result.PersonalId}");
Activity.VatNumber = result.PersonalId;
}
}
/// <summary> /// <summary>
/// Show Activity Overlay /// Show Activity Overlay
/// </summary> /// </summary>
@ -332,7 +357,7 @@ public partial class AdvisorActivityCreatePage : IDisposable
{ {
item.Check = false; item.Check = false;
} }
await CabinetService.StoreInventoryDrawerAsync(CompanyId, _inventoryDrawer); await DrawerService.StoreInventoryDrawerAsync(CompanyId, _inventoryDrawer);
await CreateActivity(); await CreateActivity();
} }
@ -483,26 +508,34 @@ public partial class AdvisorActivityCreatePage : IDisposable
/// <summary> /// <summary>
/// Show Incomplete Organization Number Warning /// Show Incomplete Organization Number Warning
/// </summary> /// </summary>
private void ShowOrgWarning() private async Task ShowOrgWarning()
{ {
if (_kanvas) if (_kanvas)
{ {
return; return;
} }
// if (OrgWarning)
if (OrgWarning) // {
{ // return;
return; // }
} // OrgWarning = true;
OrgWarning = true;
if (Company.CountryCode.ToLower() == "se" if (Company.CountryCode.ToLower() == "se"
&& Utils.StringToDigits(Activity.VatNumber).Length < 10 && Utils.StringToDigits(Activity.VatNumber).Length < 10
&& Activity.ActivityStatusEnum == "order") && Activity.ActivityStatusEnum == "order")
{ {
Toaster.ShowWarning("Org nummer er ufuldstændig. Skal opdateres før bestilling kan sendes. "); Toaster.ShowWarning("Org nummer er ufuldstændig. Skal opdateres før bestilling kan sendes.");
Toaster.ShowInfo("Vent mens vi soger at finde de manglende cifre ...");
var result = await OrgService.GetPersonalOrgNumber(Activity.Name);
if (!string.IsNullOrWhiteSpace(result.PersonalId))
{
Activity.VatNumber = result.PersonalId;
Toaster.ShowSuccess($"Org nummer for {result.CompanyName} er fundet at være {result.PersonalId}.");
} }
} }
// OrgWarning = false;
}
/// <summary> /// <summary>
@ -571,9 +604,9 @@ public partial class AdvisorActivityCreatePage : IDisposable
/// <param name="sender"></param> /// <param name="sender"></param>
/// <param name="e"></param> /// <param name="e"></param>
/// <exception cref="ArgumentOutOfRangeException"></exception> /// <exception cref="ArgumentOutOfRangeException"></exception>
private void HandleFieldChanged(object sender, FieldChangedEventArgs e) private void ContextHandleFieldChanged(object sender, FieldChangedEventArgs e)
{ {
Logger.LogDebug("ActivityNewPage => HandleFieldChanged => ActivityStatusEnum <= '{}'", Logger.LogDebug("ActivityNewPage => ContextHandleFieldChanged => ActivityStatusEnum <= '{}'",
Activity.ActivityStatusEnum); Activity.ActivityStatusEnum);
DraftProvider.Draft.DraftType = Activity.ActivityStatusEnum; DraftProvider.Draft.DraftType = Activity.ActivityStatusEnum;
if (Activity.ActivityStatusEnum == "noSale") if (Activity.ActivityStatusEnum == "noSale")
@ -614,7 +647,7 @@ public partial class AdvisorActivityCreatePage : IDisposable
/// </summary> /// </summary>
/// <param name="sender"></param> /// <param name="sender"></param>
/// <param name="e"></param> /// <param name="e"></param>
private void ValidationChanged(object sender, ValidationStateChangedEventArgs e) private void ContextValidationChanged(object sender, ValidationStateChangedEventArgs e)
{ {
if (string.IsNullOrEmpty(Activity.ActivityTypeEnum) && !ReportClosed) if (string.IsNullOrEmpty(Activity.ActivityTypeEnum) && !ReportClosed)
{ {
@ -627,17 +660,17 @@ public partial class AdvisorActivityCreatePage : IDisposable
&& Company.CountryCode.ToLower() == "se" && Company.CountryCode.ToLower() == "se"
&& Utils.StringToDigits(Activity.VatNumber).Length < 10) && Utils.StringToDigits(Activity.VatNumber).Length < 10)
{ {
ShowOrgWarning(); Toaster.ShowError("Org nummer er ufuldstændig ...");
PoFormInvalid = true; // ShowOrgWarning();
return; // return;
} }
PoFormInvalid = false; PoFormInvalid = false;
ActivityContext.OnFieldChanged -= HandleFieldChanged; ActivityContext.OnFieldChanged -= ContextHandleFieldChanged;
ActivityContext.OnValidationStateChanged -= ValidationChanged; ActivityContext.OnValidationStateChanged -= ContextValidationChanged;
ActivityContext = new EditContext(Activity); ActivityContext = new EditContext(Activity);
ActivityContext.OnFieldChanged += HandleFieldChanged; ActivityContext.OnFieldChanged += ContextHandleFieldChanged;
ActivityContext.OnValidationStateChanged += ValidationChanged; ActivityContext.OnValidationStateChanged += ContextValidationChanged;
} }
@ -647,7 +680,7 @@ public partial class AdvisorActivityCreatePage : IDisposable
public void Dispose() public void Dispose()
{ {
Interceptor.DisposeEvent(); Interceptor.DisposeEvent();
ActivityContext.OnFieldChanged -= HandleFieldChanged; ActivityContext.OnFieldChanged -= ContextHandleFieldChanged;
ActivityContext.OnValidationStateChanged -= ValidationChanged; ActivityContext.OnValidationStateChanged -= ContextValidationChanged;
} }
} }

View file

@ -32,7 +32,7 @@ public partial class AdvisorCustomerActivityListPage : IDisposable
[Inject] public HttpInterceptorService Interceptor { get; set; } [Inject] public HttpInterceptorService Interceptor { get; set; }
[Inject] public IAdvisorActivityRepository AdvisorActivityRepo { get; set; } [Inject] public IAdvisorActivityRepository AdvisorActivityRepo { get; set; }
[Inject] public IAdvisorCustomerRepository CompanyRepo { get; set; } [Inject] public IAdvisorCustomerRepository CompanyRepo { get; set; }
[Inject] public IDrawerCabinetService CabinetService { get; set; } [Inject] public ICabinetDrawerService DrawerService { get; set; }
[Inject] public ILogger<AdvisorCustomerActivityListPage> Logger { get; set; } [Inject] public ILogger<AdvisorCustomerActivityListPage> Logger { get; set; }
// ###################################################################### // ######################################################################
@ -58,7 +58,7 @@ public partial class AdvisorCustomerActivityListPage : IDisposable
private async Task GetActivities() private async Task GetActivities()
{ {
Activities = new List<ReportItemView>(); Activities = new List<ReportItemView>();
var drawer = await CabinetService.GetActivityDrawerAsync(CompanyId); var drawer = await DrawerService.GetActivityDrawerAsync(CompanyId);
if (drawer.Content.Any()) if (drawer.Content.Any())
{ {
Activities = drawer.Content Activities = drawer.Content

View file

@ -137,7 +137,7 @@
else else
{ {
<div class="col-sm-3"> <div class="col-sm-3">
@* placeholder *@ @(Company.Segment = UserInfo.CountryCode.ToLower() == "no" ? "10" : "11")
</div> </div>
} }
@* entity mobile *@ @* entity mobile *@

View file

@ -35,21 +35,25 @@ namespace Wonky.Client.Pages;
public partial class AdvisorCustomerInventoryListPage : IDisposable public partial class AdvisorCustomerInventoryListPage : IDisposable
{ {
// ############################################################## /**
* Injected services
*/
[Inject] public ILogger<AdvisorCustomerInventoryListPage> Logger { get; set; }
[Inject] public IAdvisorCustomerHistoryRepository HistoryRepo { get; set; } [Inject] public IAdvisorCustomerHistoryRepository HistoryRepo { get; set; }
[Inject] public IAdvisorCustomerRepository CustomerRepo { get; set; } [Inject] public IAdvisorCustomerRepository CustomerRepo { 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<AdvisorCustomerInventoryListPage> Logger { get; set; }
[Inject] public ILocalStorageService Storage { get; set; } [Inject] public ILocalStorageService Storage { get; set; }
[Inject] public ICountryCatalogRepository CatalogRepo { get; set; } [Inject] public ICountryCatalogRepository CatalogRepo { get; set; }
[Inject] public IDrawerCabinetService CabinetService { get; set; } [Inject] public ICabinetDrawerService DrawerService { get; set; }
/*
// ############################################################## * Parameters
*/
[CascadingParameter] public DraftStateProvider DraftStateProvider { get; set; } = new(); [CascadingParameter] public DraftStateProvider DraftStateProvider { get; set; } = new();
[Parameter] public string CompanyId { get; set; } = ""; [Parameter] public string CompanyId { get; set; } = "";
/*
// ############################################################## * Variables
*/
private readonly JsonSerializerOptions _options = new JsonSerializerOptions(JsonSerializerDefaults.Web); private readonly JsonSerializerOptions _options = new JsonSerializerOptions(JsonSerializerDefaults.Web);
private CompanyDto Company { get; set; } = new(); private CompanyDto Company { get; set; } = new();
private bool Working { get; set; } = true; private bool Working { get; set; } = true;
@ -63,7 +67,7 @@ public partial class AdvisorCustomerInventoryListPage : IDisposable
Interceptor.RegisterEvent(); Interceptor.RegisterEvent();
Interceptor.RegisterBeforeSendEvent(); Interceptor.RegisterBeforeSendEvent();
var drawer = await CabinetService.GetInfoDrawerAsync(CompanyId); var drawer = await DrawerService.GetInfoDrawerAsync(CompanyId);
Company = drawer.Content; Company = drawer.Content;
// fetch product inventory // fetch product inventory
@ -93,7 +97,7 @@ public partial class AdvisorCustomerInventoryListPage : IDisposable
private async Task FetchProductInventory() private async Task FetchProductInventory()
{ {
var drawer = await CabinetService.GetInventoryDrawerAsync(CompanyId); var drawer = await DrawerService.GetInventoryDrawerAsync(CompanyId);
if (drawer.Content.Any()) if (drawer.Content.Any())
{ {
Inventory = drawer.Content; Inventory = drawer.Content;

View file

@ -32,6 +32,7 @@
<a class="btn btn-primary d-block" href="/advisor/customers/@_company.CompanyId/activities/new"><i class="bi-chevron-right"></i> Besøg</a> <a class="btn btn-primary d-block" href="/advisor/customers/@_company.CompanyId/activities/new"><i class="bi-chevron-right"></i> Besøg</a>
</div> </div>
</div> </div>
<CustomerInvoiceListComponent OnShowInvoice="ShowInvoiceModal" Invoices="@_invoiceDrawer.Content"/> <CustomerInvoiceListComponent OnShowInvoice="ShowInvoiceModal" Invoices="@_invoiceDrawer.Content"/>
} }

View file

@ -36,7 +36,7 @@ public partial class AdvisorCustomerInvoiceListPage : IDisposable
[Inject] public HttpInterceptorService Interceptor { get; set; } [Inject] public HttpInterceptorService Interceptor { get; set; }
[Inject] public IAdvisorCustomerHistoryRepository HistoryRepo { get; set; } [Inject] public IAdvisorCustomerHistoryRepository HistoryRepo { get; set; }
[Inject] public IToastService Toaster { get; set; } [Inject] public IToastService Toaster { get; set; }
[Inject] public IDrawerCabinetService CabinetService { get; set; } [Inject] public ICabinetDrawerService DrawerService { get; set; }
// ############################################################## // ##############################################################
[Parameter] public string CompanyId { get; set; } = ""; [Parameter] public string CompanyId { get; set; } = "";
@ -55,8 +55,8 @@ public partial class AdvisorCustomerInvoiceListPage : IDisposable
Interceptor.RegisterEvent(); Interceptor.RegisterEvent();
Interceptor.RegisterBeforeSendEvent(); Interceptor.RegisterBeforeSendEvent();
_infoDrawer = await CabinetService.GetInfoDrawerAsync(CompanyId); _infoDrawer = await DrawerService.GetInfoDrawerAsync(CompanyId);
_invoiceDrawer = await CabinetService.GetInvoiceDrawerAsync(CompanyId); _invoiceDrawer = await DrawerService.GetInvoiceDrawerAsync(CompanyId);
_company = _infoDrawer.Content; _company = _infoDrawer.Content;
_invoices = _invoiceDrawer.Content; _invoices = _invoiceDrawer.Content;

View file

@ -0,0 +1,99 @@
@* Copyright (C) 2022 FCS Frede's Computer Services.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see [https://www.gnu.org/licenses/agpl-3.0.en.html]
*@
@using Wonky.Client.Components
@using Microsoft.AspNetCore.Authorization
@attribute [Authorize(Roles = "Advisor")]
@page "/advisor/customers/{CompanyId}/statistic"
<PageTitle>Produktkøb @_company.Name</PageTitle>
<div class="row d-print-none pb-3 mb-3 border-bottom">
<div class="col-sm-5"></div>
<div class="col-sm-2 text-end">
<select class="form-select bg-info text-bg-info me-3" @bind-value="Months" @bind-value:event="oninput" @onchange="@OnSelectChanged">
<option value="6">Vis 6 måneder</option>
<option value="12">Vis 12 måneder</option>
<option value="18">Vis 18 måneder</option>
<option value="24">Vis 24 måneder</option>
</select>
</div>
<div class="col-sm-5 text-end">
<button type="button" class="btn btn-primary me-3" onclick="window.print();"><i class="bi-printer"></i> Udskriv (24 md.)</button>
<a class="btn btn-primary" href="/advisor/customers/@CompanyId"><i class="bi-chevron-left"></i> Tilbage</a>
</div>
</div>
@if (DisplayList.Any())
{
<table class="table table-striped d-print-table">
<thead>
<tr>
<th class="text-center" colspan="6">
<h2>Produktkøb @_company.Name</h2>
<p>Dannet @DateTime.Today.ToLongDateString() (@Months md.)</p>
</th>
</tr>
<tr class="rounded-2 border border-1">
<th scope="col">
Beskrivelse
</th>
<th scope="col">
Vare Nr.
</th>
<th scope="col">
Dato
</th>
<th scope="col" class="text-end">
Antal
</th>
<th scope="col" class="text-end">
Pris
</th>
<th scope="col" class="text-end">
Afslag
</th>
</tr>
</thead>
<tbody>
@foreach (var item in DisplayList)
{
<tr class="align-content-center">
<td>
@item.Description
</td>
<td>
@item.Sku
</td>
<td>
@item.DeliveryDate.ToShortDateString()
</td>
<td class="text-end">
@item.Quantity
</td>
<td class="text-end">
@item.Price
</td>
<td class="text-end">
@(item.Discount)%
</td>
</tr>
}
</tbody>
</table>
}
else
{
<div>Ingen data</div>
}

View file

@ -0,0 +1,54 @@
using Microsoft.AspNetCore.Components;
using Wonky.Client.Local.Services;
using Wonky.Client.Models;
using Wonky.Entity.DTO;
using Wonky.Entity.Views;
#pragma warning disable CS8618
namespace Wonky.Client.Pages;
public partial class AdvisorCustomerStatisticPage
{
[Inject] public ICabinetDrawerService DrawerService { get; set; }
[Parameter] public string CompanyId { get; set; } = "";
private InfoDrawer _infoDrawer = new();
private StatisticDrawer _statisticDrawer = new();
private List<HistoryFilter> DisplayList { get; set; } = new();
private CompanyDto _company = new();
private int Months { get; set; }
protected override async Task OnInitializedAsync()
{
_infoDrawer = await DrawerService.GetInfoDrawerAsync(CompanyId);
_statisticDrawer = await DrawerService.GetStatisticDrawerAsync(CompanyId);
_company = _infoDrawer.Content;
if (Months == 0)
{
Months = 24;
}
FilterDisplayList(Months);
}
private void FilterDisplayList(int months)
{
if (_statisticDrawer.Content.Any())
{
DisplayList = _statisticDrawer.Content
.Where(x => x.DeliveryDate > DateTime.Now.AddMonths(-months))
.OrderBy(x => x.Description).ThenByDescending(x => x.DeliveryDate)
.ToList();
}
}
private void OnSelectChanged(ChangeEventArgs e)
{
var val = e.Value?.ToString();
var x = Convert.ToInt32(val);
if (x > 24) x = 24;
FilterDisplayList(x);
}
}

View file

@ -28,87 +28,88 @@
</div> </div>
} }
<div class="row pt-2 pb-2 mb-2 rounded rounded-2 bg-dark text-white"> <div class="row pt-2 pb-2 mb-2 rounded rounded-2 bg-dark text-white">
<div class="col-sm-7"> <div class="col-sm-6">
<div class="mt-1"> <div class="mt-1">
<span class="h3">@_infoDrawer.Content.Name</span> <span>(@_infoDrawer.Content.Account)</span> <span class="h3">@_infoDrawer.Content.Name</span> <span>(@_infoDrawer.Content.Account)</span>
</div> </div>
</div> </div>
<div class="col-sm-5 text-end"> <div class="col-sm-6 text-end">
@if (_userInfo.CountryCode is "DK") @if (_userInfo.CountryCode is "DK")
{ {
<a class="btn btn-secondary me-2" href="/advisor/customers/@CompanyId/workplaces/new"><i class="bi-plus-lg"></i> Arbejdssted</a> <a class="btn btn-secondary btn-sm me-2" href="/advisor/customers/@CompanyId/workplaces/new"><i class="bi-plus-lg"></i> Arbejdssted</a>
} }
<button class="btn btn-secondary me-2" @onclick="@ReloadHistory" disabled="@Working"><i class="bi-repeat"></i> Historik</button> <a class="btn btn-secondary btn-sm me-2" href="/advisor/customers/@CompanyId/statistic"><i class="bi-activity"></i> Statistik</a>
<a class="btn btn-primary me-2" href="/advisor/customers"><i class="bi-chevron-left"></i> Tilbage</a> <button class="btn btn-secondary btn-sm me-2" @onclick="@ReloadHistory" disabled="@_working"><i class="bi-repeat"></i> Historik</button>
<a class="btn btn-primary btn-sm me-2" href="/advisor/customers"><i class="bi-chevron-left"></i> Tilbage</a>
</div> </div>
</div> </div>
// erp context // erp context
<EditForm EditContext="ErpContext"> <EditForm EditContext="_erpContext">
<DataAnnotationsValidator/> <DataAnnotationsValidator/>
<div class="row g-1"> <div class="row g-1">
@* Company Name *@ @* Company Name *@
<label for="name" class="col-sm-1 col-form-label-sm">Navn</label> <label for="name" class="col-sm-1 col-form-label-sm">Navn</label>
<div class="col-sm-5"> <div class="col-sm-5">
<InputText id="name" class="form-control" @bind-Value="_infoDrawer.Content.Name" readonly="@(ErpEditDisabled)"/> <InputText id="name" class="form-control" @bind-Value="_infoDrawer.Content.Name" readonly="@(_erpEditDisabled)"/>
<ValidationMessage For="@(() => _infoDrawer.Content.Name)"></ValidationMessage> <ValidationMessage For="@(() => _infoDrawer.Content.Name)"></ValidationMessage>
</div> </div>
@* Company Attention *@ @* Company Attention *@
<label for="attention" class="col-sm-1 col-form-label-sm">Att.</label> <label for="attention" class="col-sm-1 col-form-label-sm">Att.</label>
<div class="col-sm-5"> <div class="col-sm-5">
<InputText id="attention" class="form-control" @bind-Value="_infoDrawer.Content.Attention" readonly="@(ErpEditDisabled)"/> <InputText id="attention" class="form-control" @bind-Value="_infoDrawer.Content.Attention" readonly="@(_erpEditDisabled)"/>
<ValidationMessage For="@(() => _infoDrawer.Content.Attention)"></ValidationMessage> <ValidationMessage For="@(() => _infoDrawer.Content.Attention)"></ValidationMessage>
</div> </div>
@* Address 1 *@ @* Address 1 *@
<label for="address1" class="col-sm-1 col-form-label-sm">Adresse</label> <label for="address1" class="col-sm-1 col-form-label-sm">Adresse</label>
<div class="col-sm-5"> <div class="col-sm-5">
<InputText id="address1" class="form-control" @bind-Value="_infoDrawer.Content.Address1" readonly="@(ErpEditDisabled)"/> <InputText id="address1" class="form-control" @bind-Value="_infoDrawer.Content.Address1" readonly="@(_erpEditDisabled)"/>
<ValidationMessage For="@(() => _infoDrawer.Content.Address1)"></ValidationMessage> <ValidationMessage For="@(() => _infoDrawer.Content.Address1)"></ValidationMessage>
</div> </div>
@* Address 2 *@ @* Address 2 *@
<label for="address2" class="col-sm-1 col-form-label-sm">Adresse</label> <label for="address2" class="col-sm-1 col-form-label-sm">Adresse</label>
<div class="col-sm-5"> <div class="col-sm-5">
<InputText id="address2" class="form-control" @bind-Value="_infoDrawer.Content.Address2" readonly="@(ErpEditDisabled)"/> <InputText id="address2" class="form-control" @bind-Value="_infoDrawer.Content.Address2" readonly="@(_erpEditDisabled)"/>
<ValidationMessage For="@(() => _infoDrawer.Content.Address2)"></ValidationMessage> <ValidationMessage For="@(() => _infoDrawer.Content.Address2)"></ValidationMessage>
</div> </div>
@* Post Code *@ @* Post Code *@
<label for="zipCode" class="col-sm-1 col-form-label-sm">PostNr</label> <label for="zipCode" class="col-sm-1 col-form-label-sm">PostNr</label>
<div class="col-sm-1"> <div class="col-sm-1">
<InputText id="zipCode" class="form-control" @bind-Value="_infoDrawer.Content.ZipCode" readonly="@(ErpEditDisabled)"/> <InputText id="zipCode" class="form-control" @bind-Value="_infoDrawer.Content.ZipCode" readonly="@(_erpEditDisabled)"/>
<ValidationMessage For="@(() => _infoDrawer.Content.ZipCode)"></ValidationMessage> <ValidationMessage For="@(() => _infoDrawer.Content.ZipCode)"></ValidationMessage>
</div> </div>
@* City Name *@ @* City Name *@
<label for="city" class="col-sm-1 col-form-label-sm">Bynavn</label> <label for="city" class="col-sm-1 col-form-label-sm">Bynavn</label>
<div class="col-sm-3"> <div class="col-sm-3">
<InputText id="city" class="form-control" @bind-Value="_infoDrawer.Content.City" readonly="@(ErpEditDisabled)"/> <InputText id="city" class="form-control" @bind-Value="_infoDrawer.Content.City" readonly="@(_erpEditDisabled)"/>
<ValidationMessage For="@(() => _infoDrawer.Content.City)"></ValidationMessage> <ValidationMessage For="@(() => _infoDrawer.Content.City)"></ValidationMessage>
</div> </div>
@* Email *@ @* Email *@
<label for="email" class="col-sm-1 col-form-label-sm">Epost</label> <label for="email" class="col-sm-1 col-form-label-sm">Epost</label>
<div class="col-sm-5"> <div class="col-sm-5">
<InputText id="email" class="form-control" @bind-Value="_infoDrawer.Content.Email" readonly="@(ErpEditDisabled)"/> <InputText id="email" class="form-control" @bind-Value="_infoDrawer.Content.Email" readonly="@(_erpEditDisabled)"/>
<ValidationMessage For="@(() => _infoDrawer.Content.Email)"></ValidationMessage> <ValidationMessage For="@(() => _infoDrawer.Content.Email)"></ValidationMessage>
</div> </div>
@* Phone *@ @* Phone *@
<label for="phone" class="col-sm-1 col-form-label-sm">Telefon</label> <label for="phone" class="col-sm-1 col-form-label-sm">Telefon</label>
<div class="col-sm-2"> <div class="col-sm-2">
<InputText id="phone" class="form-control" @bind-Value="_infoDrawer.Content.Phone" readonly="@(ErpEditDisabled)"/> <InputText id="phone" class="form-control" @bind-Value="_infoDrawer.Content.Phone" readonly="@(_erpEditDisabled)"/>
<ValidationMessage For="@(() => _infoDrawer.Content.Phone)"></ValidationMessage> <ValidationMessage For="@(() => _infoDrawer.Content.Phone)"></ValidationMessage>
</div> </div>
@* Mobile *@ @* Mobile *@
<label for="mobile" class="col-sm-1 col-form-label-sm">Mobil</label> <label for="mobile" class="col-sm-1 col-form-label-sm">Mobil</label>
<div class="col-sm-2"> <div class="col-sm-2">
<InputText id="mobile" class="form-control" @bind-Value="_infoDrawer.Content.Mobile" readonly="@(ErpEditDisabled)"/> <InputText id="mobile" class="form-control" @bind-Value="_infoDrawer.Content.Mobile" readonly="@(_erpEditDisabled)"/>
<ValidationMessage For="@(() => _infoDrawer.Content.Mobile)"></ValidationMessage> <ValidationMessage For="@(() => _infoDrawer.Content.Mobile)"></ValidationMessage>
</div> </div>
@* Email *@ @* Email *@
<label for="eanNumber" class="col-sm-1 col-form-label-sm">EAN</label> <label for="eanNumber" class="col-sm-1 col-form-label-sm">EAN</label>
<div class="col-sm-5"> <div class="col-sm-5">
<InputText id="eanNumber" class="form-control" @bind-Value="_infoDrawer.Content.EanNumber" readonly="@(ErpEditDisabled)"/> <InputText id="eanNumber" class="form-control" @bind-Value="_infoDrawer.Content.EanNumber" readonly="@(_erpEditDisabled)"/>
<ValidationMessage For="@(() => _infoDrawer.Content.EanNumber)"></ValidationMessage> <ValidationMessage For="@(() => _infoDrawer.Content.EanNumber)"></ValidationMessage>
</div> </div>
@if (!Kanvas) @if (!_kanvas)
{ {
@* entity segment *@ @* entity segment *@
@if (_userInfo.CountryCode.ToLower() == "dk") @if (_userInfo.CountryCode.ToLower() == "dk")
@ -116,7 +117,7 @@
<label for="segment" class="col-sm-1 col-form-label-sm">Segment</label> <label for="segment" class="col-sm-1 col-form-label-sm">Segment</label>
<div class="col-sm-2"> <div class="col-sm-2">
<InputSelect id="segment" class="form-select bg-warning text-bg-warning" <InputSelect id="segment" class="form-select bg-warning text-bg-warning"
@bind-Value="@_infoDrawer.Content.Segment" disabled="@(ErpEditDisabled)"> @bind-Value="@_infoDrawer.Content.Segment" disabled="@(_erpEditDisabled)">
<option value="" disabled>segment</option> <option value="" disabled>segment</option>
<option value="1">AUTO</option> <option value="1">AUTO</option>
<option value="2">INDUSTRI</option> <option value="2">INDUSTRI</option>
@ -145,7 +146,7 @@
</div> </div>
@* Save erp data *@ @* Save erp data *@
<div class="col-sm-3 d-grid mx-auto"> <div class="col-sm-3 d-grid mx-auto">
<button type="button" class="btn btn-danger d-block" @onclick="@UpdateErpData" disabled="@(Working || _infoDrawer.Content.Name == "ERROR" || ErpEditDisabled)"><i class="bi-cloud-arrow-up"></i> STAM data </button> <button type="button" class="btn btn-danger d-block" @onclick="@UpdateErpData" disabled="@(_working || _infoDrawer.Content.Name == "ERROR" || _erpEditDisabled)"><i class="bi-cloud-arrow-up"></i> STAM data </button>
</div> </div>
@* vat number*@ @* vat number*@
<hr class="mb-3"/> <hr class="mb-3"/>
@ -155,7 +156,7 @@
<span class="input-group-text"> <span class="input-group-text">
<DisplayStateComponent StateClass="@VatState"/> <DisplayStateComponent StateClass="@VatState"/>
</span> </span>
<InputText id="vatNumber" class="form-control" @bind-Value="_infoDrawer.Content.VatNumber" readonly="@(VatEditDisabled)"/> <InputText id="vatNumber" class="form-control" @bind-Value="_infoDrawer.Content.VatNumber" readonly="@(_vatEditDisabled)"/>
<ValidationMessage For="@(() => _infoDrawer.Content.VatNumber)"></ValidationMessage> <ValidationMessage For="@(() => _infoDrawer.Content.VatNumber)"></ValidationMessage>
</div> </div>
</div> </div>
@ -165,10 +166,10 @@
</div> </div>
@* vat lookup *@ @* vat lookup *@
<div class="col-sm-3 d-grid mx-auto"> <div class="col-sm-3 d-grid mx-auto">
@switch (CountryCode) @switch (_countryCode)
{ {
case "dk": case "dk":
<button type="button" class="btn btn-info" @onclick="@OpenVatLookupModal" disabled="@(VatEditDisabled)"><i class="bi-search"></i> CVR</button> <button type="button" class="btn btn-info" @onclick="@OpenVatLookupModal" disabled="@(_vatEditDisabled)"><i class="bi-search"></i> CVR</button>
break; break;
case "no": case "no":
<a class="btn btn-info" href="https://brreg.no/" target="_blank"><i class="bi-search"></i> brreg.no</a> <a class="btn btn-info" href="https://brreg.no/" target="_blank"><i class="bi-search"></i> brreg.no</a>
@ -180,7 +181,7 @@
</div> </div>
@* save vat number *@ @* save vat number *@
<div class="col-sm-3 d-grid mx-auto"> <div class="col-sm-3 d-grid mx-auto">
<button type="button" class="btn btn-warning d-block" @onclick="@UpdateVatNumber" disabled="@(VatEditDisabled)"><i class="bi-cloud-arrow-up"></i> Moms/Org Nr.</button> <button type="button" class="btn btn-warning d-block" @onclick="@UpdateVatNumber" disabled="@(_vatEditDisabled)"><i class="bi-cloud-arrow-up"></i> Moms/Org Nr.</button>
</div> </div>
} }
@ -190,42 +191,42 @@
@* activity buttons *@ @* activity buttons *@
<div class="row mt-3 mb-3"> <div class="row mt-3 mb-3">
<div class="col-sm-3"> <div class="col-sm-3">
@if (!Kanvas) @if (!_kanvas)
{ {
<ActionButton ActionLink="@InvoiceLink" <ActionButton ActionLink="@_invoiceLink"
ButtonText="Faktura" ButtonText="Faktura"
ButtonType="danger" ButtonType="danger"
Enabled="@EnableLink" /> Enabled="@_enableLink" />
} }
</div> </div>
<div class="col-sm-3"> <div class="col-sm-3">
@if (!Kanvas) @if (!_kanvas)
{ {
<ActionButton ActionLink="@ActivityLink" <ActionButton ActionLink="@_activitiesLink"
ButtonText="Tidl. Besøg" ButtonText="Tidl. Besøg"
ButtonType="warning" ButtonType="warning"
Enabled="@EnableLink" /> Enabled="@_enableLink" />
} }
</div> </div>
<div class="col-sm-3"> <div class="col-sm-3">
@if (!Kanvas ) @if (!_kanvas )
{ {
<ActionButton ActionLink="@InventoryLink" <ActionButton ActionLink="@_inventoryLink"
ButtonText="Produkter" ButtonText="Produkter"
ButtonType="success" ButtonType="success"
Enabled="@EnableLink" /> Enabled="@_enableLink" />
} }
</div> </div>
<div class="col-sm-3"> <div class="col-sm-3">
<ActionButton ActionLink="@NewActivityLink" <ActionButton ActionLink="@_newActivityLink"
ButtonText="Nyt Besøg" ButtonText="Nyt Besøg"
ButtonType="primary" ButtonType="primary"
Enabled="@EnableActivity"> Enabled="@_enableActivity">
</ActionButton> </ActionButton>
</div> </div>
</div> </div>
@if (!Kanvas) @if (!_kanvas)
{ {
<hr class="mb-3"/> <hr class="mb-3"/>
@* crm context - OBS note *@ @* crm context - OBS note *@
@ -252,7 +253,7 @@
<label for="contacts" class="col-sm-1 col-form-label-sm">Kontakt</label> <label for="contacts" class="col-sm-1 col-form-label-sm">Kontakt</label>
<div id="contacts" class="col-sm-11"> <div id="contacts" class="col-sm-11">
<div class="list-group"> <div class="list-group">
<div class="list-group-item list-group-item-action bg-dark text-white" @onclick="@(() => OpenContactPopup(DefaultContact))"> <div class="list-group-item list-group-item-action bg-dark text-white" @onclick="@(() => OpenContactPopup(_defaultContact))">
<div class="row"> <div class="row">
<div class="col-sm-4">Stilling</div> <div class="col-sm-4">Stilling</div>
<div class="col-sm-4">Navn</div> <div class="col-sm-4">Navn</div>
@ -262,9 +263,9 @@
</div> </div>
</div> </div>
</div> </div>
@if (Contacts.Any()) @if (_contacts.Any())
{ {
@foreach (var contact in Contacts) @foreach (var contact in _contacts)
{ {
<div class="list-group-item list-group-item-action" @onclick="@(() => OpenContactPopup(contact))"> <div class="list-group-item list-group-item-action" @onclick="@(() => OpenContactPopup(contact))">
<div class="row g-2"> <div class="row g-2">
@ -289,14 +290,14 @@
<div class="col-sm-3"> <div class="col-sm-3">
<div class="input-group"> <div class="input-group">
<span class="input-group-text"> <span class="input-group-text">
<DisplayStateComponent StateClass="@VisitState"/> <DisplayStateComponent StateClass="@_visitStateCss"/>
</span> </span>
<InputDate id="nextVisit" class="form-control" @bind-Value="@(NextVisit)"/> <InputDate id="nextVisit" class="form-control" @bind-Value="@(_nextVisit)"/>
</div> </div>
</div> </div>
<label for="lastVisit" class="col-sm-1 col-form-label-sm">Sidste besøg</label> <label for="lastVisit" class="col-sm-1 col-form-label-sm">Sidste besøg</label>
<div class="col-sm-3"> <div class="col-sm-3">
<InputDate id="lastVisit" class="form-control" @bind-Value="@LastVisit"/> <InputDate id="lastVisit" class="form-control" @bind-Value="@_lastVisit"/>
</div> </div>
<label for="interval" class="col-sm-2 col-form-label-sm">Uge Interval</label> <label for="interval" class="col-sm-2 col-form-label-sm">Uge Interval</label>
<div class="col-sm-2"> <div class="col-sm-2">
@ -315,7 +316,7 @@
<hr class="mb-3"/> <hr class="mb-3"/>
<div class="row pt-3 mb-5"> <div class="row pt-3 mb-5">
<div class="col-sm-4 d-grid"> <div class="col-sm-4 d-grid">
<button type="button" class="btn btn-outline-dark" @onclick="@ToggleVisibility">@ToggleButtonText</button> <button type="button" class="btn btn-outline-dark" @onclick="@ToggleVisibility">@_toggleButtonText</button>
</div> </div>
<div class="col-sm-4 d-grid"> <div class="col-sm-4 d-grid">
@if (_userInfo.CountryCode is "DK") @if (_userInfo.CountryCode is "DK")
@ -326,13 +327,13 @@
</div> </div>
} }
@if (Working) @if (_working)
{ {
<WorkingThreeDots/> <WorkingThreeDots/>
} }
<VatLookupDkModal VatAddress="CompanyVatAddress" EntityName="@_infoDrawer.Content.Name" VatNumber="@_infoDrawer.Content.VatNumber" <VatLookupDkModal VatAddress="_companyVatAddress" EntityName="@_infoDrawer.Content.Name" VatNumber="@_infoDrawer.Content.VatNumber"
@ref="VatLookupPopup" OnSelectedCompany="SelectedCompanyCallback"/> @ref="_vatLookupPopup" OnSelectedCompany="SelectedCompanyCallback"/>
<ContactViewEditModal SelectedContact="SelectedContact" CompanyName="@_infoDrawer.Content.Name" <ContactViewEditModal SelectedContact="_selectedContact" CompanyName="@_infoDrawer.Content.Name"
@ref="ContactViewPopup" OnSaveClicked="WriteContactCallback" OnDeleteClicked="DeleteContactCallback"/> @ref="_contactViewPopup" OnSaveClicked="WriteContactCallback" OnDeleteClicked="DeleteContactCallback"/>

View file

@ -48,45 +48,46 @@ public partial class AdvisorCustomerViewEditPage : IDisposable
[Inject] public ILocalStorageService Storage { get; set; } [Inject] public ILocalStorageService Storage { get; set; }
[Inject] public IUserInfoService UserInfoService { get; set; } [Inject] public IUserInfoService UserInfoService { get; set; }
[Inject] public IOptions<AppInfo?>? AppInfo { get; set; } [Inject] public IOptions<AppInfo?>? AppInfo { get; set; }
[Inject] public IDrawerCabinetService CabinetService { get; set; } [Inject] public ICabinetDrawerService DrawerService { get; set; }
// ########################################################################### // ###########################################################################
[Parameter] public string CompanyId { get; set; } = ""; [Parameter] public string CompanyId { get; set; } = "";
// ########################################################################### // ###########################################################################
private EditContext ErpContext { get; set; } private EditContext _erpContext;
private DateTime LastVisit { get; set; } private DateTime _lastVisit;
private DateTime NextVisit { get; set; } private DateTime _nextVisit;
private VatAddress CompanyVatAddress { get; set; } = new(); private VatAddress _companyVatAddress = new();
private ContactDto SelectedContact { get; set; } = new(); private ContactDto _selectedContact = new();
private ContactDto DefaultContact { get; set; } = new(); private ContactDto _defaultContact = new();
private ContactViewEditModal ContactViewPopup { get; set; } = new(); private ContactViewEditModal _contactViewPopup = new();
private VatLookupDkModal VatLookupPopup { get; set; } = new(); private VatLookupDkModal _vatLookupPopup = new();
private List<ContactDto> Contacts { get; set; } = new(); private List<ContactDto> _contacts = new();
private UserManagerEditView _userInfo = new();
private InfoDrawer _infoDrawer = new();
private string VatState { get; set; } = "the-ugly"; private string VatState { get; set; } = "the-ugly";
private bool ValidVat { get; set; } private bool _validVat;
private bool HasFolded { get; set; } private bool _hasFolded;
private string CurrentVat { get; set; } = ""; private string _currentVat = "";
private string CountryCode { get; set; } = "dk"; private string _countryCode = "dk";
private string VisitState { get; set; } = "the-ugly"; private string _visitStateCss = "the-ugly";
private int EnableActivity { get; set; } = 1; private int _enableActivity = 1;
private bool Working { get; set; } = true; private bool _working = true;
private bool CountryIsDk { get; set; } = true; private bool _countryIsDk = true;
private bool ErpEditDisabled { get; set; } = true; private bool _erpEditDisabled = true;
private bool VatEditDisabled { get; set; } = true; private bool _vatEditDisabled = true;
private string ToggleButtonText { get; set; } = ""; private string _toggleButtonText = "";
private bool Kanvas { get; set; } private bool _kanvas;
private string InventoryLink { get; set; } = ""; private string _inventoryLink = "";
private string ActivityLink { get; set; } = ""; private string _activitiesLink = "";
private string InvoiceLink { get; set; } = ""; private string _invoiceLink = "";
private string NewActivityLink { get; set; } = ""; private string _newActivityLink = "";
private int EnableLink { get; set; } = 1; private int _enableLink = 1;
private ActivityDrawer _activityDrawer = new(); private ActivityDrawer _activityDrawer = new();
private InventoryDrawer _inventoryDrawer = new(); private InventoryDrawer _inventoryDrawer = new();
private InvoiceDrawer _invoiceDrawer = new(); private InvoiceDrawer _invoiceDrawer = new();
private StatisticDrawer _statisticDrawer = new(); private StatisticDrawer _statisticDrawer = new();
private UserManagerEditView _userInfo = new();
private InfoDrawer _infoDrawer = new();
private CompanyDto _company = new();
private string _companyId = ""; private string _companyId = "";
protected override async Task OnInitializedAsync() protected override async Task OnInitializedAsync()
{ {
@ -98,115 +99,126 @@ public partial class AdvisorCustomerViewEditPage : IDisposable
/* /*
* default contact * default contact
*/ */
DefaultContact = new ContactDto { CompanyId = CompanyId, ContactId = "", FirstName = "" }; _defaultContact = new ContactDto { CompanyId = CompanyId, ContactId = "", FirstName = "" };
/* /*
* navigation button links * navigation button links
*/ */
InventoryLink = $"/advisor/customers/{CompanyId}/history/inventory"; _inventoryLink = $"/advisor/customers/{CompanyId}/history/inventory";
ActivityLink = $"/advisor/customers/{CompanyId}/activities"; _activitiesLink = $"/advisor/customers/{CompanyId}/activities";
InvoiceLink = $"/advisor/customers/{CompanyId}/invoices"; _invoiceLink = $"/advisor/customers/{CompanyId}/invoices";
NewActivityLink = $"/advisor/customers/{CompanyId}/activities/new"; _newActivityLink = $"/advisor/customers/{CompanyId}/activities/new";
/* /*
* setup form context * setup form context
*/ */
ErpContext = new EditContext(_infoDrawer.Content); _erpContext = new EditContext(_company);
/* /*
* assign event handlers to context * assign event handlers to context
*/ */
ErpContext.OnFieldChanged += HandleFieldChanged; _erpContext.OnFieldChanged += HandleFieldChanged;
ErpContext.OnValidationStateChanged += ValidationChanged!; _erpContext.OnValidationStateChanged += ValidationChanged!;
/* /*
* fetch user info from local storage * fetch user info from local storage
*/ */
_userInfo = await UserInfoService.GetUserInfo(); _userInfo = await UserInfoService.GetUserInfo();
CountryCode = _userInfo.CountryCode.ToLower(); _countryCode = _userInfo.CountryCode.ToLower();
CountryIsDk = CountryCode == "dk"; _countryIsDk = _countryCode == "dk";
/* /*
* get InfoDrawer.Company from drawer * get InfoDrawer.Company from drawer
*/ */
_infoDrawer = await CabinetService.GetInfoDrawerAsync(CompanyId); _infoDrawer = await DrawerService.GetInfoDrawerAsync(CompanyId, force:true);
_infoDrawer.Content = _infoDrawer.Content; _company = _infoDrawer.Content;
/* /*
* internal EnableActivity flag * internal _enableActivity flag
*/ */
EnableActivity = _infoDrawer.Content.ValidVat; _enableActivity = _company.ValidVat;
/* /*
* if KANVAS or NY override EnableActivity * if KANVAS or NY override _enableActivity
*/ */
if (_infoDrawer.Content.Account.StartsWith("NY") || _infoDrawer.Content.Account.StartsWith("KANVAS") || string.IsNullOrWhiteSpace(_infoDrawer.Content.Account)) if (_company.Account.StartsWith("NY") || _company.Account.StartsWith("KANVAS") ||
EnableActivity = 1; string.IsNullOrWhiteSpace(_company.Account))
if (_infoDrawer.Content.Account.StartsWith("KANVAS")) {
Kanvas = true; _enableActivity = 1;
}
if (_company.Account.StartsWith("KANVAS"))
{
_kanvas = true;
}
/* /*
* only execute if the InfoDrawer.Company is not KANVAS * only execute if the InfoDrawer.Company is not KANVAS
*/ */
if (!Kanvas) if (!_kanvas)
{ {
Logger.LogDebug("InfoDrawer.Company => {}", JsonSerializer.Serialize(_infoDrawer.Content)); Logger.LogDebug("_company => {}", JsonSerializer.Serialize(_company));
/* /*
* toggle view button text * toggle view button text
*/ */
ToggleButtonText = _infoDrawer.Content.IsHidden == 0 ? "Udelad kunde i oversigt" : "Brug Normal Visning"; _toggleButtonText = _company.IsHidden == 0 ? "Udelad kunde i oversigt" : "Brug Normal Visning";
CurrentVat = _infoDrawer.Content.VatNumber; _currentVat = _company.VatNumber;
_infoDrawer.Content.CountryCode = _userInfo.CountryCode.ToLower(); _company.CountryCode = _userInfo.CountryCode.ToLower();
/* /*
* visit interval init * visit interval init
*/ */
if (_infoDrawer.Content.Interval == 0) if (_company.Interval == 0)
_infoDrawer.Content.Interval = 8; {
_company.Interval = 8;
}
/* /*
* visit date init * visit date init
*/ */
LastVisit = DateTime.Parse(_infoDrawer.Content.LastVisit); _lastVisit = DateTime.Parse(_company.LastVisit);
NextVisit = DateTime.Parse(_infoDrawer.Content.NextVisit); _nextVisit = DateTime.Parse(_company.NextVisit);
/* /*
* if no previous visit is registered - force last visit date to 2020 * if no previous visit is registered - force last visit date to 2020
*/ */
if (LastVisit.Year < 2020) if (_lastVisit.Year < 2020)
LastVisit = DateTime.Parse("2020-01-01"); {
_lastVisit = DateTime.Parse("2020-01-01");
}
/* /*
* set next visit according to last visit and interval * set next visit according to last visit and interval
*/ */
if (!_infoDrawer.Content.ValidDateSpan()) if (!_company.ValidDateSpan())
NextVisit = LastVisit.AddDays(_infoDrawer.Content.Interval * 7); {
_nextVisit = _lastVisit.AddDays(_company.Interval * 7);
}
/* /*
* display urgency of next visit * display urgency of next visit
*/ */
VisitState = Utils.MapVisitState($"{NextVisit:yyyy-MM-dd}"); _visitStateCss = Utils.MapVisitState($"{_nextVisit:yyyy-MM-dd}");
/* /*
* handle InfoDrawer.Company out of business case * handle InfoDrawer.Company out of business case
*/ */
if (_infoDrawer.Content.HasFolded == 1) if (_company.HasFolded == 1)
{ {
/* /*
* this is only used if user has selected to show closed companies * this is only used if user has selected to show closed companies
*/ */
HasFolded = true; _hasFolded = true;
VatState = "the-dead"; VatState = "the-dead";
VisitState = "the-dead"; _visitStateCss = "the-dead";
} }
else else
{ {
/* /*
* vat validation flags * vat validation flags
*/ */
_infoDrawer.Content.ValidVat = VatUtils.ValidateFormat(_infoDrawer.Content.CountryCode, _infoDrawer.Content.VatNumber) ? 1 : 0; _company.ValidVat = VatUtils.ValidateFormat(_company.CountryCode, _company.VatNumber) ? 1 : 0;
ValidVat = _infoDrawer.Content.ValidVat == 1; // true/false flag set if InfoDrawer.Company has a valid vatNumber _validVat = _company.ValidVat == 1; // true/false flag set if InfoDrawer.Company has a valid vatNumber
VatState = _infoDrawer.Content.ValidVat == 1 ? "the-good" : "no-vat"; // assign css class VatState = _company.ValidVat == 1 ? "the-good" : "no-vat"; // assign css class
} }
/* /*
* create search address from address * create search address from address
*/ */
if (CountryIsDk) if (_countryIsDk)
{ {
CompanyVatAddress = PrepareVatAddress(_infoDrawer.Content); _companyVatAddress = PrepareVatAddress(_company);
} }
await GetContacts(CompanyId); await GetContacts(CompanyId);
} }
/* /*
* remove loading image * remove loading image
*/ */
Working = false; _working = false;
} }
protected override async Task OnAfterRenderAsync(bool firstRender) protected override async Task OnAfterRenderAsync(bool firstRender)
@ -214,40 +226,42 @@ public partial class AdvisorCustomerViewEditPage : IDisposable
if (string.IsNullOrWhiteSpace(_companyId)) if (string.IsNullOrWhiteSpace(_companyId))
{ {
_companyId = CompanyId; _companyId = CompanyId;
await CabinetService.GetInvoiceDrawerAsync(CompanyId, true); _invoiceDrawer = await DrawerService.GetInvoiceDrawerAsync(CompanyId, true);
await CabinetService.GetInventoryDrawerAsync(CompanyId, true); _inventoryDrawer = await DrawerService.GetInventoryDrawerAsync(CompanyId, true);
await CabinetService.GetActivityDrawerAsync(CompanyId, true); _activityDrawer = await DrawerService.GetActivityDrawerAsync(CompanyId, true);
await CabinetService.GetStatisticDrawerAsync(CompanyId, true); _statisticDrawer = await DrawerService.GetStatisticDrawerAsync(CompanyId, true);
} }
} }
private async Task ReloadHistory() private async Task ReloadHistory()
{ {
_enableLink = 0;
_enableActivity = 0;
Toaster.ShowWarning("Arbejder på sagen ..."); Toaster.ShowWarning("Arbejder på sagen ...");
var newSync = await HistoryRepo.RequestErpSync(CompanyId, _infoDrawer.Content.HistorySync, false); var newSync = await HistoryRepo.RequestErpSync(CompanyId, _company.HistorySync, false);
if (!string.IsNullOrWhiteSpace(newSync)) if (!string.IsNullOrWhiteSpace(newSync))
{ {
_infoDrawer.Content.HistorySync = newSync; _infoDrawer = await DrawerService.GetInfoDrawerAsync(CompanyId, true);
_infoDrawer.Content = _infoDrawer.Content; _invoiceDrawer = await DrawerService.GetInvoiceDrawerAsync(CompanyId, true);
await CabinetService.StoreInfoDrawerAsync(CompanyId, _infoDrawer); _inventoryDrawer = await DrawerService.GetInventoryDrawerAsync(CompanyId, true);
_activityDrawer = await DrawerService.GetActivityDrawerAsync(CompanyId, true);
_statisticDrawer = await DrawerService.GetStatisticDrawerAsync(CompanyId, true);
} }
await CabinetService.GetInvoiceDrawerAsync(CompanyId, true);
await CabinetService.GetInventoryDrawerAsync(CompanyId, true);
await CabinetService.GetActivityDrawerAsync(CompanyId, true);
await CabinetService.GetStatisticDrawerAsync(CompanyId, true);
Toaster.ShowSuccess("Data er snart klar ...."); Toaster.ShowSuccess("Data er snart klar ....");
_enableLink = 1;
_enableActivity = _company.ValidVat;
} }
private void ToggleErpEdit() private void ToggleErpEdit()
{ {
ErpEditDisabled = !ErpEditDisabled; _erpEditDisabled = !_erpEditDisabled;
} }
private void ToggleVatEdit() private void ToggleVatEdit()
{ {
VatEditDisabled = !VatEditDisabled; _vatEditDisabled = !_vatEditDisabled;
} }
@ -256,12 +270,12 @@ public partial class AdvisorCustomerViewEditPage : IDisposable
/* /*
* toggle view button text * toggle view button text
*/ */
_infoDrawer.Content.IsHidden = _infoDrawer.Content.IsHidden == 0 ? 1 : 0; _company.IsHidden = _company.IsHidden == 0 ? 1 : 0;
ToggleButtonText = _infoDrawer.Content.IsHidden == 0 ? "Udelad kunde i oversigt" : "Brug Normal Visning"; _toggleButtonText = _company.IsHidden == 0 ? "Udelad kunde i oversigt" : "Brug Normal Visning";
/* /*
* send update reqeust * send update reqeust
*/ */
await CustomerRepo.UpdateCrmData(CompanyId, _infoDrawer.Content); await CustomerRepo.UpdateCrmData(CompanyId, _company);
} }
@ -270,38 +284,38 @@ public partial class AdvisorCustomerViewEditPage : IDisposable
/* /*
* load contacts * load contacts
*/ */
Contacts = await ContactRepo.GetContacts(companyId); _contacts = await ContactRepo.GetContacts(companyId);
if (Contacts.Any() && Contacts.Count > 1) if (_contacts.Any() && _contacts.Count > 1)
{ {
Contacts = Contacts.OrderBy(x => x.FirstName).ToList(); _contacts = _contacts.OrderBy(x => x.FirstName).ToList();
} }
} }
private void OpenVatLookupModal() private void OpenVatLookupModal()
{ {
VatLookupPopup.Show(); _vatLookupPopup.Show();
} }
private void SelectedCompanyCallback(VirkRegInfo regInfo) private void SelectedCompanyCallback(VirkRegInfo regInfo)
{ {
ValidVat = regInfo.States[0].State.ToLower() == "normal"; _validVat = regInfo.States[0].State.ToLower() == "normal";
_infoDrawer.Content.HasFolded = ValidVat ? 1 : 0; _company.HasFolded = _validVat ? 1 : 0;
EnableActivity = ValidVat ? 1 : 0; _enableActivity = _validVat ? 1 : 0;
VatState = regInfo.States[0].State.ToLower() == "normal" ? "the-good" : "the-dead"; VatState = regInfo.States[0].State.ToLower() == "normal" ? "the-good" : "the-dead";
/* /*
* set new properties if flagged * set new properties if flagged
*/ */
if (regInfo.SyncAll) if (regInfo.SyncAll)
{ {
_infoDrawer.Content.Name = regInfo.Name; _company.Name = regInfo.Name;
_infoDrawer.Content.Address1 = regInfo.Address; _company.Address1 = regInfo.Address;
_infoDrawer.Content.Address2 = regInfo.CoName; _company.Address2 = regInfo.CoName;
_infoDrawer.Content.ZipCode = regInfo.ZipCode; _company.ZipCode = regInfo.ZipCode;
_infoDrawer.Content.City = regInfo.City; _company.City = regInfo.City;
} }
_infoDrawer.Content.VatNumber = regInfo.VatNumber; _company.VatNumber = regInfo.VatNumber;
} }
@ -310,11 +324,11 @@ public partial class AdvisorCustomerViewEditPage : IDisposable
/* /*
* pass contact to popup * pass contact to popup
*/ */
SelectedContact = contact; _selectedContact = contact;
/* /*
* show the popup * show the popup
*/ */
ContactViewPopup.Show(); _contactViewPopup.Show();
} }
/// <summary> /// <summary>
@ -323,9 +337,9 @@ public partial class AdvisorCustomerViewEditPage : IDisposable
/// <param name="contact"></param> /// <param name="contact"></param>
private async Task WriteContactCallback(ContactDto contact) private async Task WriteContactCallback(ContactDto contact)
{ {
if (Working) if (_working)
return; return;
Working = true; _working = true;
/* /*
* if ContactId is empty it is a new contact * if ContactId is empty it is a new contact
*/ */
@ -346,12 +360,12 @@ public partial class AdvisorCustomerViewEditPage : IDisposable
/* /*
* reset default contact * reset default contact
*/ */
SelectedContact = new ContactDto(); _selectedContact = new ContactDto();
/* /*
* reload contacts from backend * reload contacts from backend
*/ */
await GetContacts(CompanyId); await GetContacts(CompanyId);
Working = false; _working = false;
} }
/// <summary> /// <summary>
@ -360,9 +374,9 @@ public partial class AdvisorCustomerViewEditPage : IDisposable
/// <param name="contactId"></param> /// <param name="contactId"></param>
private async Task DeleteContactCallback(string contactId) private async Task DeleteContactCallback(string contactId)
{ {
if (Working) if (_working)
return; return;
Working = true; _working = true;
/* /*
* send delete request to backend * send delete request to backend
*/ */
@ -370,12 +384,12 @@ public partial class AdvisorCustomerViewEditPage : IDisposable
/* /*
* reset default contact * reset default contact
*/ */
SelectedContact = new ContactDto(); _selectedContact = new ContactDto();
/* /*
* reload contacts from backend * reload contacts from backend
*/ */
await GetContacts(CompanyId); await GetContacts(CompanyId);
Working = false; _working = false;
} }
/// <summary> /// <summary>
@ -384,21 +398,22 @@ public partial class AdvisorCustomerViewEditPage : IDisposable
/// <returns>true/false</returns> /// <returns>true/false</returns>
private async Task PostCrmData() private async Task PostCrmData()
{ {
if (Working) if (_working)
return; return;
Working = true; _working = true;
Toaster.ShowInfo("Vent venligst ..."); Toaster.ShowInfo("Vent venligst ...");
_infoDrawer.Content.LastVisit = $"{LastVisit:yyyy-MM-dd}"; _company.LastVisit = $"{_lastVisit:yyyy-MM-dd}";
_infoDrawer.Content.NextVisit = $"{NextVisit:yyyy-MM-dd}"; _company.NextVisit = $"{_nextVisit:yyyy-MM-dd}";
_infoDrawer.Content.IsHidden = 0; _company.IsHidden = 0;
var company = await CustomerRepo.UpdateCrmData(CompanyId, _infoDrawer.Content); var result = await CustomerRepo.UpdateCrmData(CompanyId, _company);
if (!string.IsNullOrWhiteSpace(company.CompanyId)) if (!string.IsNullOrWhiteSpace(result.CompanyId))
{ {
await UpdateInfoDrawer(company); _infoDrawer = await DrawerService.GetInfoDrawerAsync(CompanyId, true);
StateHasChanged(); _company = _infoDrawer.Content;
} }
Working = false; StateHasChanged();
Toaster.ClearAll(); _working = false;
Toaster.ShowSuccess("Dine CRM data er opdateret.");
} }
/// <summary> /// <summary>
@ -407,19 +422,20 @@ public partial class AdvisorCustomerViewEditPage : IDisposable
/// <returns></returns> /// <returns></returns>
private async Task UpdateErpData() private async Task UpdateErpData()
{ {
if (Working) if (_working)
return; return;
ErpEditDisabled = true; _erpEditDisabled = true;
Working = true; _working = true;
Toaster.ShowInfo("Vent venligst ..."); Toaster.ShowInfo("Vent venligst ...");
var company = await CustomerRepo.UpdateErpData(CompanyId, _infoDrawer.Content); var result = await CustomerRepo.UpdateErpData(CompanyId, _company);
if (!string.IsNullOrWhiteSpace(company.CompanyId)) if (!string.IsNullOrWhiteSpace(result.CompanyId))
{ {
await UpdateInfoDrawer(company); _infoDrawer = await DrawerService.GetInfoDrawerAsync(CompanyId, true);
StateHasChanged(); _company = _infoDrawer.Content;
} }
Working = false; StateHasChanged();
Toaster.ClearAll(); _working = false;
Toaster.ShowSuccess("ERP data er opdateret. Notifikation til kontoret er sendt.");
} }
/// <summary> /// <summary>
@ -431,25 +447,26 @@ public partial class AdvisorCustomerViewEditPage : IDisposable
/* /*
* VAT format validation * VAT format validation
*/ */
if (!VatUtils.ValidateFormat(_infoDrawer.Content.CountryCode, _infoDrawer.Content.VatNumber)) if (!VatUtils.ValidateFormat(_company.CountryCode, _company.VatNumber))
{ {
Toaster.ShowError($"Moms Nummer ugyldigt"); Toaster.ShowError($"Moms Nummer ugyldigt");
return; return;
} }
if (Working) if (_working)
return; return;
Working = true; _working = true;
VatEditDisabled = true; _vatEditDisabled = true;
Toaster.ShowInfo("Vent venligst ..."); Toaster.ShowInfo("Vent venligst ...");
var company = await CustomerRepo.UpdateCompanyVat(CompanyId, _infoDrawer.Content.VatNumber); var result = await CustomerRepo.UpdateCompanyVat(CompanyId, _company.VatNumber);
if (!string.IsNullOrWhiteSpace(company.CompanyId)) if (!string.IsNullOrWhiteSpace(result.CompanyId))
{ {
await UpdateInfoDrawer(company); _infoDrawer = await DrawerService.GetInfoDrawerAsync(CompanyId, true);
StateHasChanged(); _company = _infoDrawer.Content;
} }
Toaster.ClearAll(); StateHasChanged();
Working = false; _working = false;
Toaster.ShowSuccess("Moms Nr. er opdateret.");
} }
/// <summary> /// <summary>
@ -493,15 +510,12 @@ public partial class AdvisorCustomerViewEditPage : IDisposable
} }
private async Task UpdateInfoDrawer(CompanyDto company) /// <summary>
{ /// Force enable activity
_infoDrawer.Content = company; /// </summary>
await CabinetService.StoreInfoDrawerAsync(CompanyId, _infoDrawer);
}
private void ForceActivity() private void ForceActivity()
{ {
EnableActivity = EnableActivity == 0 ? 1 : 0; _enableActivity = _enableActivity == 0 ? 1 : 0;
} }
/// <summary> /// <summary>
@ -512,18 +526,18 @@ public partial class AdvisorCustomerViewEditPage : IDisposable
private void HandleFieldChanged(object? sender, FieldChangedEventArgs? e) private void HandleFieldChanged(object? sender, FieldChangedEventArgs? e)
{ {
NextVisit = LastVisit.AddDays(_infoDrawer.Content.Interval * 7); _nextVisit = _lastVisit.AddDays(_company.Interval * 7);
/* /*
* avoid nesting if by assuming ValidVat is false * avoid nesting if by assuming _validVat is false
*/ */
ValidVat = false; _validVat = false;
/* /*
* set ValidVat true if validation succeed * set _validVat true if validation succeed
*/ */
if (VatUtils.ValidateFormat(_infoDrawer.Content.CountryCode, _infoDrawer.Content.VatNumber)) if (VatUtils.ValidateFormat(_company.CountryCode, _company.VatNumber))
{ {
ValidVat = true; _validVat = true;
EnableActivity = 1; _enableActivity = 1;
} }
StateHasChanged(); StateHasChanged();
@ -536,13 +550,13 @@ public partial class AdvisorCustomerViewEditPage : IDisposable
/// <param name="e"></param> /// <param name="e"></param>
private void ValidationChanged(object sender, ValidationStateChangedEventArgs e) private void ValidationChanged(object sender, ValidationStateChangedEventArgs e)
{ {
ErpContext.OnFieldChanged -= HandleFieldChanged; _erpContext.OnFieldChanged -= HandleFieldChanged;
ErpContext.OnValidationStateChanged -= ValidationChanged!; _erpContext.OnValidationStateChanged -= ValidationChanged!;
ErpContext = new EditContext(_infoDrawer.Content); _erpContext = new EditContext(_company);
ErpContext.OnFieldChanged += HandleFieldChanged; _erpContext.OnFieldChanged += HandleFieldChanged;
ErpContext.OnValidationStateChanged += ValidationChanged!; _erpContext.OnValidationStateChanged += ValidationChanged!;
} }
/// <summary> /// <summary>
@ -551,7 +565,7 @@ public partial class AdvisorCustomerViewEditPage : IDisposable
public void Dispose() public void Dispose()
{ {
Interceptor.DisposeEvent(); Interceptor.DisposeEvent();
ErpContext.OnFieldChanged -= HandleFieldChanged; _erpContext.OnFieldChanged -= HandleFieldChanged;
ErpContext.OnValidationStateChanged -= ValidationChanged!; _erpContext.OnValidationStateChanged -= ValidationChanged!;
} }
} }

View file

@ -28,59 +28,59 @@
</div> </div>
</div> </div>
<div class="card-body"> <div class="card-body">
<EditForm EditContext="FormContext" OnValidSubmit="CreateUserRequest"> <EditForm EditContext="FormContext" OnValidSubmit="PostNewUser">
<DataAnnotationsValidator/> <DataAnnotationsValidator/>
<div class="row g-3 mb-3"> <div class="row g-3 mb-3">
@* firstName *@ @* firstName *@
<div class="col-sm-6"> <div class="col-sm-6">
<div class="form-floating"> <div class="form-floating">
<InputText id="firstName" class="form-control" @bind-Value="CreateUserInput.FirstName" placeholder="Fornavn"/> <InputText id="firstName" class="form-control" @bind-Value="UserForm.FirstName" placeholder="Fornavn"/>
<ValidationMessage For="@(() => CreateUserInput.FirstName)"></ValidationMessage> <ValidationMessage For="@(() => UserForm.FirstName)"></ValidationMessage>
<label for="firstName">Fornavn</label> <label for="firstName">Fornavn</label>
</div> </div>
</div> </div>
@* lastName *@ @* lastName *@
<div class="col-sm-6"> <div class="col-sm-6">
<div class="form-floating"> <div class="form-floating">
<InputText id="lastName" class="form-control" @bind-Value="CreateUserInput.LastName" placeholder="Efternavn"/> <InputText id="lastName" class="form-control" @bind-Value="UserForm.LastName" placeholder="Efternavn"/>
<ValidationMessage For="@(() => CreateUserInput.LastName)"></ValidationMessage> <ValidationMessage For="@(() => UserForm.LastName)"></ValidationMessage>
<label for="lastName">Efternavn</label> <label for="lastName">Efternavn</label>
</div> </div>
</div> </div>
@* email *@ @* email *@
<div class="col-sm-6"> <div class="col-sm-6">
<div class="form-floating"> <div class="form-floating">
<InputText id="email" class="form-control" @bind-Value="CreateUserInput.Email" placeholder="Email"/> <InputText id="email" class="form-control" @bind-Value="UserForm.Email" placeholder="Email"/>
<ValidationMessage For="@(() => CreateUserInput.Email)"></ValidationMessage> <ValidationMessage For="@(() => UserForm.Email)"></ValidationMessage>
<label for="email">Email</label> <label for="email">Email</label>
</div> </div>
</div> </div>
@* phoneNumber *@ @* phoneNumber *@
<div class="col-sm-6"> <div class="col-sm-6">
<div class="form-floating"> <div class="form-floating">
<InputText id="phoneNumber" class="form-control" @bind-Value="CreateUserInput.PhoneNumber" placeholder="Direkte Telefon Nr."/> <InputText id="phoneNumber" class="form-control" @bind-Value="UserForm.PhoneNumber" placeholder="Direkte Telefon Nr."/>
<ValidationMessage For="@(() => CreateUserInput.PhoneNumber)"></ValidationMessage> <ValidationMessage For="@(() => UserForm.PhoneNumber)"></ValidationMessage>
<label for="phoneNumber">Direkte Telefon Nr.</label> <label for="phoneNumber">Direkte Telefon Nr.</label>
</div> </div>
</div> </div>
@* salesRep *@ @* salesRep *@
<div class="col-sm-6"> <div class="col-sm-6">
<div class="form-floating"> <div class="form-floating">
<InputText id="salesRep" class="form-control" @bind-Value="CreateUserInput.SalesRep" placeholder="Sælger"/> <InputText id="salesRep" class="form-control" @bind-Value="UserForm.SalesRep" placeholder="Sælger"/>
<ValidationMessage For="@(() => CreateUserInput.SalesRep)"></ValidationMessage> <ValidationMessage For="@(() => UserForm.SalesRep)"></ValidationMessage>
<label for="salesRep">Sælger</label> <label for="salesRep">Sælger</label>
</div> </div>
</div> </div>
@* countrycode *@ @* countrycode *@
<div class="col-sm-6"> <div class="col-sm-6">
<div class="form-floating"> <div class="form-floating">
<InputSelect id="countryCode" class="form-control" @bind-Value="CreateUserInput.CountryCode" placeholder="Landekode"> <InputSelect id="countryCode" class="form-control" @bind-Value="UserForm.CountryCode" placeholder="Landekode">
<option value="" disabled>Klik for valg</option> <option value="" disabled>Klik for valg</option>
<option value="DK">Danmark</option> <option value="DK">Danmark</option>
<option value="NO">Norge</option> <option value="NO">Norge</option>
<option value="SE">Sverige</option> <option value="SE">Sverige</option>
</InputSelect> </InputSelect>
<ValidationMessage For="@(() => CreateUserInput.CountryCode)"></ValidationMessage> <ValidationMessage For="@(() => UserForm.CountryCode)"></ValidationMessage>
<label for="countryCode">Landekode</label> <label for="countryCode">Landekode</label>
</div> </div>
</div> </div>
@ -116,12 +116,12 @@
</div> </div>
</div> </div>
<div class="row @(_webShop && !string.IsNullOrWhiteSpace(CreateUserInput.CountryCode) ? "inno-display" : "inno-hidden")"> <div class="row @(UserForm.EShop && !string.IsNullOrWhiteSpace(UserForm.CountryCode) ? "inno-display" : "inno-hidden")">
<div class="col-sm-10"> <div class="col-sm-10">
@_company.Name - @_company.Account - @_company.Phone @_company.Name - @_company.Account - @_company.Phone
</div> </div>
<div class="col-sm-2"> <div class="col-sm-2">
<button type="button" class="btn btn-primary" @onclick="@ShowSearchOverlay"> <button type="button" class="btn btn-primary" @onclick="@ShowCompanySearchOverlay">
Tilknyt kunde ... Tilknyt kunde ...
</button> </button>
</div> </div>
@ -143,14 +143,14 @@
<div class="col-sm-6"> <div class="col-sm-6">
<div class="form-floating"> <div class="form-floating">
<InputText id="newPasswd" class="form-control" @bind-Value="@PasswdInput.NewPassword" placeholder="Ny Adgangskode"/> <InputText id="newPasswd" class="form-control" @bind-Value="@PasswdInput.NewPassword" placeholder="Ny Adgangskode"/>
<ValidationMessage For="@(() => CreateUserInput.NewPassword)"></ValidationMessage> <ValidationMessage For="@(() => UserForm.NewPassword)"></ValidationMessage>
<label for="newPasswd">Ny Adgangskode</label> <label for="newPasswd">Ny Adgangskode</label>
</div> </div>
</div> </div>
<div class="col-sm-6"> <div class="col-sm-6">
<div class="form-floating"> <div class="form-floating">
<InputText id="verifyPasswd" class="form-control" @bind-Value="@PasswdInput.ConfirmPassword" placeholder="Gentag Adgangskode"/> <InputText id="verifyPasswd" class="form-control" @bind-Value="@PasswdInput.ConfirmPassword" placeholder="Gentag Adgangskode"/>
<ValidationMessage For="@(() => CreateUserInput.ConfirmPassword)"></ValidationMessage> <ValidationMessage For="@(() => UserForm.ConfirmPassword)"></ValidationMessage>
<label for="verifyPasswd">Gentag Adgangskode</label> <label for="verifyPasswd">Gentag Adgangskode</label>
</div> </div>
</div> </div>
@ -165,4 +165,4 @@
<WorkingThreeDots/> <WorkingThreeDots/>
} }
<CustomerSearchOverlay CountryCode="@CreateUserInput.CountryCode" OnSelected="@OnSelectCompany" @ref="SearchOverlay" /> <CustomerSearchOverlay CountryCode="@UserForm.CountryCode" OnSelected="@OnSelectCompany" @ref="SearchOverlay" />

View file

@ -38,8 +38,8 @@ public partial class SystemUserCreatePage : IDisposable
[Inject] public IToastService Toaster { get; set; } [Inject] public IToastService Toaster { get; set; }
// ############################################################# // #############################################################
private CreateUserInputModel CreateUserInput { get; set; } = new(); private NewUserForm UserForm { get; set; } = new();
private UserManagerCreateView CreateUserDto { get; set; } = new(); private ManagerNewUserDto NewUserDto { get; set; } = new();
private EditContext FormContext { get; set; } private EditContext FormContext { get; set; }
private bool ContextInvalid { get; set; } = true; private bool ContextInvalid { get; set; } = true;
private bool Working { get; set; } = true; private bool Working { get; set; } = true;
@ -48,55 +48,93 @@ public partial class SystemUserCreatePage : IDisposable
private RoleAssignment AssignedRoles { get; set; } = new(); private RoleAssignment AssignedRoles { get; set; } = new();
private readonly JsonSerializerOptions _options = new() { PropertyNameCaseInsensitive = true }; private readonly JsonSerializerOptions _options = new() { PropertyNameCaseInsensitive = true };
private bool _webShop;
private CompanyDto _company = new(); private CompanyDto _company = new();
private CustomerSearchOverlay SearchOverlay { get; set; } private CustomerSearchOverlay SearchOverlay { get; set; }
protected override void OnParametersSet() protected override void OnInitialized()
{ {
Interceptor.RegisterEvent(); Interceptor.RegisterEvent();
Interceptor.RegisterBeforeSendEvent(); Interceptor.RegisterBeforeSendEvent();
FormContext = new EditContext(CreateUserInput); FormContext = new EditContext(UserForm);
FormContext.OnFieldChanged += ContextHandleFieldChanged!; FormContext.OnFieldChanged += ContextHandleFieldChanged;
FormContext.OnValidationStateChanged += ContextValidationChanged; FormContext.OnValidationStateChanged += ContextValidationChanged;
Working = false; Working = false;
} }
private async Task CreateUserRequest() /// <summary>
/// Post New User To Backend
/// </summary>
private async Task PostNewUser()
{ {
ReadOnly = true; /*
Working = true; * UI message
*/
CreateUserInput.AssignedRoles = Utils.MapSaveAssignedRoles(AssignedRoles);
CreateUserInput.EShop = _webShop;
CreateUserInput.CompanyId = !_webShop ? "" : _company.CompanyId;
Toaster.ShowInfo("Sender data til server ..."); Toaster.ShowInfo("Sender data til server ...");
/*
CreateUserDto = Mapper.MapCreateUser(CreateUserInput); * Make fields reaonly
*/
await UserRepo.CreateUser(CreateUserDto); ReadOnly = true;
/*
* Raise working flag
*/
Working = true;
/*
* ensure companyId is set correct
*/
UserForm.CompanyId = !UserForm.EShop ? "" : _company.CompanyId;
/*
* Map RoleAssignment
*/
UserForm.AssignedRoles = Utils.MapSaveAssignedRoles(AssignedRoles);
/*
* Map form input to a model the backend expects
*/
NewUserDto = Mapper.MapCreateUser(UserForm);
/*
* Send Post Request
*/
await UserRepo.PostNewUser(NewUserDto);
/*
* Lower working flag
*/
Working = false; Working = false;
/*
* UI message
*/
Toaster.ShowInfo("Bruger er oprettet ..."); Toaster.ShowInfo("Bruger er oprettet ...");
} }
private void ShowSearchOverlay() /// <summary>
/// Show Company Search Overlay
/// </summary>
private void ShowCompanySearchOverlay()
{ {
SearchOverlay.Show(); SearchOverlay.Show();
} }
/// <summary>
/// Company Selected Callback
/// </summary>
/// <param name="company"></param>
private void OnSelectCompany(CompanyDto company) private void OnSelectCompany(CompanyDto company)
{ {
_company = company; _company = company;
CreateUserInput.CompanyId = _company.CompanyId; UserForm.CompanyId = _company.CompanyId;
SearchOverlay.Hide(); SearchOverlay.Hide();
} }
/// <summary>
/// Callback Handling Context Field Changes
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void ContextHandleFieldChanged(object? sender, FieldChangedEventArgs e) private void ContextHandleFieldChanged(object? sender, FieldChangedEventArgs e)
{ {
Logger.LogDebug("contextHandleFieldChanged => e.FieldIdentifier.FieldName {}", e.FieldIdentifier.FieldName); Logger.LogDebug("contextHandleFieldChanged => e.FieldIdentifier.FieldName {}", e.FieldIdentifier.FieldName);
@ -118,11 +156,11 @@ public partial class SystemUserCreatePage : IDisposable
AssignedRoles.Office = false; AssignedRoles.Office = false;
AssignedRoles.Supervisor = false; AssignedRoles.Supervisor = false;
AssignedRoles.Warehouse = false; AssignedRoles.Warehouse = false;
_webShop = true; UserForm.EShop = true;
} }
else else
{ {
_webShop = false; UserForm.EShop = false;
} }
ContextInvalid = !FormContext.Validate(); ContextInvalid = !FormContext.Validate();
@ -130,6 +168,11 @@ public partial class SystemUserCreatePage : IDisposable
} }
/// <summary>
/// Callback Handling Context Validation Changes
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void ContextValidationChanged(object? sender, ValidationStateChangedEventArgs e) private void ContextValidationChanged(object? sender, ValidationStateChangedEventArgs e)
{ {
ContextInvalid = true; ContextInvalid = true;
@ -137,17 +180,20 @@ public partial class SystemUserCreatePage : IDisposable
FormContext.OnFieldChanged -= ContextHandleFieldChanged; FormContext.OnFieldChanged -= ContextHandleFieldChanged;
FormContext.OnValidationStateChanged -= ContextValidationChanged; FormContext.OnValidationStateChanged -= ContextValidationChanged;
FormContext = new EditContext(CreateUserInput); FormContext = new EditContext(UserForm);
FormContext.OnFieldChanged += ContextHandleFieldChanged; FormContext.OnFieldChanged += ContextHandleFieldChanged;
FormContext.OnValidationStateChanged += ContextValidationChanged; FormContext.OnValidationStateChanged += ContextValidationChanged;
} }
/// <summary>
/// Dispose
/// </summary>
public void Dispose() public void Dispose()
{ {
Interceptor.DisposeEvent(); Interceptor.DisposeEvent();
FormContext.OnFieldChanged -= ContextHandleFieldChanged!; FormContext.OnFieldChanged -= ContextHandleFieldChanged;
FormContext.OnValidationStateChanged -= ContextValidationChanged; FormContext.OnValidationStateChanged -= ContextValidationChanged;
} }
} }

View file

@ -100,9 +100,11 @@ builder.Services.AddScoped<VatInfoLookupService>();
// activity draft service // activity draft service
builder.Services.AddScoped<OrderDraftService>(); builder.Services.AddScoped<OrderDraftService>();
// cabinet service // cabinet service
builder.Services.AddScoped<IDrawerCabinetService, DrawerCabinetService>(); builder.Services.AddScoped<ICabinetDrawerService, CabinetDrawerService>();
// storage // storage
builder.Services.AddBlazoredLocalStorage(); builder.Services.AddBlazoredLocalStorage();
// Swedisd Personal Company OrgNo Search
builder.Services.AddScoped<ISwedishPersonalOrgService, SwedishPersonalOrgService>();
// --------------------------------------- // ---------------------------------------

View file

@ -1,15 +1,15 @@
{ {
"appInfo": { "appInfo": {
"name": "Wonky Online", "name": "Wonky Online",
"version": "163.0", "version": "168.1",
"rc": true, "rc": true,
"sandBox": true, "sandBox": false,
"image": "grumpy-coder.png" "image": "grumpy-coder.png"
}, },
"Logging": { "Logging": {
"LogLevel": { "LogLevel": {
"Default": "Debug", "Default": "None",
"System": "Debug", "System": "None",
"Microsoft": "Information" "Microsoft": "Information"
}, },
"Debug": { "Debug": {
@ -19,7 +19,7 @@
} }
}, },
"apiConfig": { "apiConfig": {
"baseUrl": "https://dev.innotec.dk", "baseUrl": "https://zeta.innotec.dk",
"catalog": "api/v2/catalog/country", "catalog": "api/v2/catalog/country",
"crmCustomers": "api/v2/crm/companies", "crmCustomers": "api/v2/crm/companies",
"crmInventoryExt": "history/inventory", "crmInventoryExt": "history/inventory",
@ -42,6 +42,7 @@
"servicesVatDk": "api/v2/services/virk", "servicesVatDk": "api/v2/services/virk",
"serviceVatEu": "api/v2/services/vies", "serviceVatEu": "api/v2/services/vies",
"servicesVatNo": "api/v2/services/brReg", "servicesVatNo": "api/v2/services/brReg",
"servicesVatSe": "api/v2/services/allabolag",
"servicesAuth": "v2/token", "servicesAuth": "v2/token",
"sync": "api/v2/sync", "sync": "api/v2/sync",
"syncInvoice": "api/v2/sync/invoices", "syncInvoice": "api/v2/sync/invoices",

View file

@ -132,6 +132,11 @@ public class ApiConfig
/// </summary> /// </summary>
public string ServicesVatNo { get; set; } = ""; public string ServicesVatNo { get; set; } = "";
/// <summary>
/// VAT registrar url EU
/// </summary>
public string ServicesVatSe { get; set; } = "";
/// <summary> /// <summary>
/// VAT registrar url EU /// VAT registrar url EU
/// </summary> /// </summary>

View file

@ -19,7 +19,7 @@ using System.ComponentModel.DataAnnotations;
namespace Wonky.Entity.DTO; namespace Wonky.Entity.DTO;
public class UserManagerCreateView public class ManagerNewUserDto
{ {
[MaxLength(128)] public string CompanyId { get; set; } = ""; [MaxLength(128)] public string CompanyId { get; set; } = "";