wip
This commit is contained in:
parent
18058a4230
commit
38b247f048
16 changed files with 209 additions and 229 deletions
|
@ -28,7 +28,7 @@
|
|||
<td>@company.Name</td>
|
||||
<td>@company.Account</td>
|
||||
<td>@company.City</td>
|
||||
<td><a class="btn btn-primary mb-1" href="/company/account/@company.Account">Vis</a></td>
|
||||
<td><a class="btn btn-primary mb-1" href="/company/@company.CompanyId">Vis</a></td>
|
||||
</tr>
|
||||
}
|
||||
</tbody>
|
||||
|
|
|
@ -30,15 +30,6 @@ namespace Wonky.Client.Components
|
|||
private Confirmation _confirmation = new ();
|
||||
private string _companyId = string.Empty;
|
||||
|
||||
private static string VisitState(string nextVisit)
|
||||
{
|
||||
var theUgly = DateTime.Parse(nextVisit);
|
||||
var theBad = theUgly.AddDays(-14);
|
||||
if (DateTime.Now >= theUgly)
|
||||
return "the-ugly";
|
||||
return DateTime.Now >= theBad ? "the-bad" : "the-good";
|
||||
}
|
||||
|
||||
private void CallConfirmationModal(string companyId)
|
||||
{
|
||||
_companyId = companyId;
|
||||
|
|
|
@ -22,7 +22,7 @@ namespace Wonky.Client.Components;
|
|||
|
||||
public partial class RegInfoCompany
|
||||
{
|
||||
[Inject] public VirkRegistryService VirkRegistryService { get; set; } = null!;
|
||||
[Inject] public VatOwnerLookupService VatOwnerLookupService { get; set; } = null!;
|
||||
[Parameter] public string VatNumber { get; set; } = "";
|
||||
private VirkRegInfo VirkRegInfo { get; set; } = new();
|
||||
private bool _hideMe = true;
|
||||
|
@ -34,7 +34,7 @@ public partial class RegInfoCompany
|
|||
_virkParams.VatNumber = VatNumber;
|
||||
if (string.IsNullOrWhiteSpace(VirkRegInfo.VatNumber))
|
||||
{
|
||||
var result = await VirkRegistryService.QueryVirkRegistry(_virkParams);
|
||||
var result = await VatOwnerLookupService.QueryVirkRegistry(_virkParams);
|
||||
if (result.Any())
|
||||
{
|
||||
_currentState = VirkRegInfo.States[^1].State;
|
||||
|
|
|
@ -1,128 +1,99 @@
|
|||
namespace Wonky.Client.Helpers;
|
||||
|
||||
public class VatUtils
|
||||
public static class VatUtils
|
||||
{
|
||||
public static bool CheckVat(string countryCode, string vatNumber)
|
||||
// https://ec.europa.eu/taxation_customs/vies/faqvies.do#item_11
|
||||
// https://ec.europa.eu/taxation_customs/vies/
|
||||
|
||||
public static bool ValidateFormat(string countryCode, string vatNumber)
|
||||
{
|
||||
return countryCode.ToUpperInvariant() switch
|
||||
{
|
||||
"DK" => CheckVatNumberDenmark(vatNumber),
|
||||
"NO" => CheckVatNumberNorway(vatNumber),
|
||||
"SE" => CheckVatNumberSweden(vatNumber),
|
||||
"DK" => ValidateFormatDk(vatNumber),
|
||||
"NO" => ValidateFormatNo(vatNumber),
|
||||
"SE" => ValidateFormatSe(vatNumber),
|
||||
_ => false
|
||||
};
|
||||
}
|
||||
|
||||
private static bool CheckVatNumberNorway(string vatNumber)
|
||||
{
|
||||
// https://wiki.scn.sap.com/wiki/display/CRM/Norway
|
||||
// 12 digits
|
||||
// C1..C8 random 0 to 9
|
||||
// C9 Check MOD11
|
||||
// C10 C11 C12 chars == MVA
|
||||
return vatNumber.Length >= 9 && CheckModolus11(vatNumber.Substring(0, 8));
|
||||
}
|
||||
|
||||
private static bool CheckVatNumberDenmark(string vatNumber)
|
||||
private static bool ValidateFormatDk(string vatNumber)
|
||||
{
|
||||
// https://wiki.scn.sap.com/wiki/display/CRM/Denmark
|
||||
// 8 digits 0 to 9
|
||||
// C1..C7
|
||||
// C8 Modulo 11 check digit
|
||||
// C8 check-digit MOD11
|
||||
// C1 > 0
|
||||
// R = (2*C1 + 7*C2 + 6*C3 + 5*C4 + 4*C5 + 3*C6 + 2*C7 + C8)
|
||||
if ((int)char.GetNumericValue(vatNumber[0]) < 1 || vatNumber.Length > 8)
|
||||
var vatToCheck = SanitizeVatNumber(vatNumber);
|
||||
if (vatToCheck.Length != 8)
|
||||
return false;
|
||||
return CheckModolus11(vatNumber);
|
||||
if ((int)char.GetNumericValue(vatToCheck[0]) < 1 || vatToCheck.Length > 8)
|
||||
return false;
|
||||
return ValidateMod11(vatToCheck);
|
||||
}
|
||||
|
||||
private static bool CheckVatNumberSweden(string vatNumber)
|
||||
private static bool ValidateFormatNo(string vatNumber)
|
||||
{
|
||||
// https://wiki.scn.sap.com/wiki/display/CRM/Norway
|
||||
// 12 digits
|
||||
// C1..C8 random 0 to 9
|
||||
// C9 check-digit MOD11
|
||||
// C10 C11 C12 chars == MVA
|
||||
var vatToCheck = SanitizeVatNumber(vatNumber);
|
||||
if (vatToCheck.Length != 9)
|
||||
return false;
|
||||
return long.Parse(vatToCheck) != 0 && ValidateMod11(vatNumber);
|
||||
}
|
||||
|
||||
private static bool ValidateFormatSe(string vatNumber)
|
||||
{
|
||||
// https://wiki.scn.sap.com/wiki/display/CRM/Sweden
|
||||
// 12 digits 0 to 9
|
||||
// C1 = (10 - (R + C2 + C4 + C6 + C8) modulo 10) modulo 10
|
||||
// C10 = (10 – (18 + 5 + 1 + 8 + 4)MOD10 10) MOD10
|
||||
// R = S1 + S3 + S5 + S7 + S9
|
||||
// Si = int(Ci/5) + (Ci*2) modulo 10)
|
||||
// C11 C12 >= 01 <= 94
|
||||
//
|
||||
// Validate full string using Luhn algoritm
|
||||
// 12 chars
|
||||
if (vatNumber.Length != 12)
|
||||
// Si = int(Ci/5) + (Ci*2)MOD10)
|
||||
// https://www.skatteverket.se/skatter/mervardesskattmoms/momsregistreringsnummer.4.18e1b10334ebe8bc80002649.html
|
||||
// C11 C12 == 01 (De två sista siffrorna är alltid 01)
|
||||
var vatToCheck = SanitizeVatNumber(vatNumber);
|
||||
if (vatToCheck.Length < 10 || long.Parse(vatToCheck) == 0)
|
||||
return false;
|
||||
// validate if number
|
||||
if (!int.TryParse(vatNumber, out var result))
|
||||
return false;
|
||||
//validate char 11 and 12
|
||||
var valid = int.TryParse(vatNumber.Substring(10, 2), out var v2);
|
||||
if(valid && v2 is < 1 or > 94 )
|
||||
return false;
|
||||
// check vatnumber
|
||||
return CheckLuhn(vatNumber);
|
||||
}
|
||||
private static bool CheckModolus11(string number)
|
||||
|
||||
var r = new[] { 0, 2, 4, 6, 8 }
|
||||
.Sum(m => (int)char.GetNumericValue(vatToCheck[m]) / 5 +
|
||||
(int)char.GetNumericValue(vatToCheck[m]) * 2 % 10);
|
||||
var c1 = new[] { 1, 3, 5, 7 }.Sum(m => (int)char.GetNumericValue(vatToCheck[m]));
|
||||
var c10 = (10 - (r + c1) % 10) % 10;
|
||||
if (vatToCheck.Length == 10)
|
||||
{
|
||||
int[] factors;
|
||||
switch (number.Length)
|
||||
{
|
||||
case 8:
|
||||
factors = new [] { 2, 7, 6, 5, 4, 3, 2, 1 };
|
||||
break;
|
||||
case 9:
|
||||
factors = new[] { 3, 2, 7, 6, 5, 4, 3, 2, 1 };
|
||||
break;
|
||||
case 10:
|
||||
factors = new[] { 4, 3, 2, 7, 6, 5, 4, 3, 2, 1 };
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
return $"{vatToCheck[..9]}{c10}" == vatNumber;
|
||||
}
|
||||
var i = 0;
|
||||
var r = factors.Sum(m => (int)char.GetNumericValue(number[i++]) * m);
|
||||
return r % 11 == 0;
|
||||
return $"{vatToCheck[..9]}{c10}01" == vatNumber;
|
||||
}
|
||||
|
||||
private static bool CheckLuhn(string vatNumber)
|
||||
private static bool ValidateMod11(string number)
|
||||
{
|
||||
// https://www.geeksforgeeks.org/luhn-algorithm/
|
||||
|
||||
var nDigits = vatNumber.Length;
|
||||
var nSum = 0;
|
||||
var isSecond = false;
|
||||
for (var i = nDigits - 1; i >= 0; i--)
|
||||
{
|
||||
var d = (int)char.GetNumericValue(vatNumber[i]) - '0';
|
||||
if (isSecond)
|
||||
d *= 2;
|
||||
// We add two digits to handle
|
||||
// cases that make two digits
|
||||
// after doubling
|
||||
nSum += d / 10;
|
||||
nSum += d % 10;
|
||||
|
||||
isSecond = !isSecond;
|
||||
}
|
||||
return (nSum % 10 == 0);
|
||||
}
|
||||
|
||||
private static string AddSelfCheckDigit(string number)
|
||||
{
|
||||
// modulus 11
|
||||
var multi = number.Length;
|
||||
if (long.Parse(number) == 0)
|
||||
return false;
|
||||
var sum = 0;
|
||||
for (int i = number.Length - 1, multiplier = 2; i >= 0; i--)
|
||||
for (int i = number.Length - 1, multiplier = 1; i >= 0; i--)
|
||||
{
|
||||
sum += (int)char.GetNumericValue(number[i]) * multiplier;
|
||||
if (++multiplier == multi) multiplier = 2;
|
||||
if (++multiplier > 7) multiplier = 2;
|
||||
}
|
||||
var validator = (11 - (sum % 11)).ToString();
|
||||
|
||||
validator = validator switch
|
||||
return sum % 11 == 0;
|
||||
}
|
||||
|
||||
private static string SanitizeVatNumber(string vatNumber)
|
||||
{
|
||||
"11" => "0",
|
||||
"10" => "X",
|
||||
_ => validator
|
||||
var washing = vatNumber.Replace(" ", "").Replace("-", "").ToUpperInvariant();
|
||||
var result = washing.Replace("DK", "").Replace("NO", "").Replace("SE","") ;
|
||||
if (result.Contains("MVA"))
|
||||
result = result.Replace("MVA", "");
|
||||
return result.Length switch
|
||||
{
|
||||
>= 10 => vatNumber[..10],
|
||||
< 10 => result
|
||||
};
|
||||
|
||||
return number + validator;
|
||||
}
|
||||
}
|
|
@ -26,7 +26,7 @@ namespace Wonky.Client.Models
|
|||
[Required(ErrorMessage = "Sælger skal udfyldes")] public string SalesRep { get; set; } = "";
|
||||
// From company row
|
||||
[Required(ErrorMessage = "Konto skal udfyldes")] public string Account { get; set; } = "";
|
||||
[Required(ErrorMessage = "Moms nummer skal udfyldes")] public string VatNumber { get; set; } = "";
|
||||
[Required(ErrorMessage = "CVR / ORG nummer skal udfyldes")] public string VatNumber { get; set; } = "";
|
||||
[Required(ErrorMessage = "Navn skal udfyldes")] public string Name { get; set; } = "";
|
||||
public string Address { get; set; } = "";
|
||||
public string Address2 { get; set; } = "";
|
||||
|
|
|
@ -25,6 +25,7 @@ using Wonky.Client.Services;
|
|||
using Microsoft.AspNetCore.Components;
|
||||
using Microsoft.AspNetCore.Components.Forms;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Wonky.Client.Helpers;
|
||||
using Wonky.Client.Models;
|
||||
using Wonky.Entity.DTO;
|
||||
using Wonky.Entity.Models;
|
||||
|
@ -39,7 +40,7 @@ namespace Wonky.Client.Pages
|
|||
[Inject] public HttpInterceptorService Interceptor { get; set; }
|
||||
[Inject] public IToastService ToastService { get; set; }
|
||||
[Inject] public ILogger<CompanyCreate> Logger { get; set; }
|
||||
[Inject] public VirkRegistryService VirkRegistryService { get; set; }
|
||||
[Inject] public VatOwnerLookupService VatOwnerLookupService { get; set; }
|
||||
[Inject] public ILocalStorageService StorageService { get; set; }
|
||||
[Inject] public NavigationManager Navigation { get; set; }
|
||||
private CompanyDto _companyDto = new();
|
||||
|
@ -55,14 +56,14 @@ namespace Wonky.Client.Pages
|
|||
|
||||
var ux = await StorageService.GetItemAsync<UserInfoDto>("_ux");
|
||||
_companyDto.SalesRepId = ux.Id;
|
||||
|
||||
_companyDto.CountryCode = ux.CountryCode;
|
||||
Interceptor.RegisterEvent();
|
||||
Interceptor.RegisterBeforeSendEvent();
|
||||
}
|
||||
|
||||
private async Task GetInfoFromAddress(VatAddress address)
|
||||
{
|
||||
VInfos = await VirkRegistryService.QueryVirkRegistry(
|
||||
VInfos = await VatOwnerLookupService.QueryVirkRegistry(
|
||||
new VirkParams
|
||||
{
|
||||
StreetName = address.StreetName,
|
||||
|
@ -76,9 +77,8 @@ namespace Wonky.Client.Pages
|
|||
}
|
||||
private async Task GetInfoFromVat(string vatNumber)
|
||||
{
|
||||
VInfos = await VirkRegistryService
|
||||
VInfos = await VatOwnerLookupService
|
||||
.QueryVirkRegistry(new VirkParams {VatNumber = vatNumber});
|
||||
|
||||
if (!VInfos.Any())
|
||||
{
|
||||
ToastService.ShowError($"Firma med CVR '{vatNumber}' findes ikke.");
|
||||
|
@ -106,8 +106,15 @@ namespace Wonky.Client.Pages
|
|||
}
|
||||
|
||||
private void HandleFieldChanged(object sender, FieldChangedEventArgs e)
|
||||
{
|
||||
if (!VatUtils.ValidateFormat(_companyDto.CountryCode, _companyDto.VatNumber))
|
||||
{
|
||||
_formInvalid = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
_formInvalid = !_editContext.Validate();
|
||||
}
|
||||
StateHasChanged();
|
||||
}
|
||||
private void ValidationChanged(object sender, ValidationStateChangedEventArgs e)
|
||||
|
|
|
@ -14,24 +14,17 @@
|
|||
// along with this program. If not, see [https://www.gnu.org/licenses/agpl-3.0.en.html]
|
||||
//
|
||||
*@
|
||||
|
||||
@page "/company/{account}/update"
|
||||
@using Microsoft.AspNetCore.Authorization
|
||||
@using Microsoft.AspNetCore.Components
|
||||
@attribute [Authorize(Roles = "Adviser")]
|
||||
@using Wonky.Client.Components
|
||||
@attribute [Authorize(Roles = "Adviser")]
|
||||
@page "/company/{companyId}/update"
|
||||
|
||||
@if (!string.IsNullOrEmpty(_companyDto.Name))
|
||||
@if (_company.Name != "")
|
||||
{
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<div><DisplayStateComponent StateClass="@RegState"></DisplayStateComponent> CVR status</div>
|
||||
<div>Konto @_companyDto.Account</div>
|
||||
<div>CompanyId @_companyDto.CompanyId</div>
|
||||
<div>EDIT Næste besøg @NextVisit</div>
|
||||
<div>EDIT Sidst besøgt @LastVisit</div>
|
||||
<div>DB Næste besøg @_companyDto.NextVisit</div>
|
||||
<div>DB Sidst besøgt @_companyDto.LastVisit</div>
|
||||
<div class="h2">@_company.Account - @_company.Name</div>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<EditForm EditContext="_editContext" OnValidSubmit="Update">
|
||||
|
@ -39,61 +32,65 @@
|
|||
<div class="form-group row mb-2">
|
||||
<label for="name" class="col-md-2 col-form-label">Firmanavn</label>
|
||||
<div class="col-md-10">
|
||||
<InputText id="name" class="form-control" @bind-Value="_companyDto.Name"/>
|
||||
<InputText id="name" class="form-control" @bind-Value="_company.Name"/>
|
||||
<ValidationMessage For="@(() => _company.Name)"></ValidationMessage>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row mb-2">
|
||||
<label for="address1" class="col-md-2 col-form-label">Adresse</label>
|
||||
<div class="col-md-10">
|
||||
<InputText id="address1" class="form-control" @bind-Value="_companyDto.Address1"/>
|
||||
<InputText id="address1" class="form-control" @bind-Value="_company.Address1"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row mb-2">
|
||||
<label for="address2" class="col-md-2 col-form-label">Adresse</label>
|
||||
<div class="col-md-10">
|
||||
<InputText id="address2" class="form-control" @bind-Value="_companyDto.Address2"/>
|
||||
<InputText id="address2" class="form-control" @bind-Value="_company.Address2"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row mb-2">
|
||||
<label for="zipCode" class="col-md-2 col-form-label">Postnr</label>
|
||||
<div class="col-md-10">
|
||||
<InputText id="zipCode" class="form-control" @bind-Value="_companyDto.ZipCode"/>
|
||||
<InputText id="zipCode" class="form-control" @bind-Value="_company.ZipCode"/>
|
||||
<ValidationMessage For="@(() => _company.ZipCode)"></ValidationMessage>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row mb-2">
|
||||
<label for="city" class="col-md-2 col-form-label">Bynavn</label>
|
||||
<div class="col-md-10">
|
||||
<InputText id="city" class="form-control" @bind-Value="_companyDto.City"/>
|
||||
<InputText id="city" class="form-control" @bind-Value="_company.City"/>
|
||||
<ValidationMessage For="@(() => _company.City)"></ValidationMessage>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row mb-2">
|
||||
<label for="vatNumber" class="col-md-2 col-form-label">CVR/ORG</label>
|
||||
<div class="col-md-10">
|
||||
<InputText id="vatNumber" class="form-control" @bind-Value="_companyDto.VatNumber"/>
|
||||
<InputText id="vatNumber" class="form-control" @bind-Value="_company.VatNumber"/>
|
||||
<ValidationMessage For="@(() => _company.VatNumber)"></ValidationMessage>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row mb-2">
|
||||
<label for="phone" class="col-md-2 col-form-label">Telefon nummer</label>
|
||||
<div class="col-md-10">
|
||||
<InputText id="phone" class="form-control" @bind-Value="_companyDto.Phone"/>
|
||||
<InputText id="phone" class="form-control" @bind-Value="_company.Phone"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row mb-2">
|
||||
<label for="mobile" class="col-md-2 col-form-label">Mobil nummer</label>
|
||||
<div class="col-md-10">
|
||||
<InputText id="mobile" class="form-control" @bind-Value="_companyDto.Mobile"/>
|
||||
<InputText id="mobile" class="form-control" @bind-Value="_company.Mobile"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row mb-2">
|
||||
<label for="email" class="col-md-2 col-form-label">Email</label>
|
||||
<div class="col-md-10">
|
||||
<InputText id="email" class="form-control" @bind-Value="_companyDto.Email"/>
|
||||
<InputText id="email" class="form-control" @bind-Value="_company.Email"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row mb-2">
|
||||
<label for="attention" class="col-md-2 col-form-label">Attention</label>
|
||||
<div class="col-md-10">
|
||||
<InputText id="attention" class="form-control" @bind-Value="_companyDto.Attention"/>
|
||||
<InputText id="attention" class="form-control" @bind-Value="_company.Attention"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row mb-2">
|
||||
|
@ -111,7 +108,7 @@
|
|||
<div class="form-group row mb-2">
|
||||
<label for="interval" class="col-form-label col-md-2">Besøgs interval Interval</label>
|
||||
<div class="col-md-3">
|
||||
<InputNumber id="interval" class="form-control" @bind-Value="_companyDto.Interval"/>
|
||||
<InputNumber id="interval" class="form-control" @bind-Value="_company.Interval"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-2">
|
||||
|
@ -132,5 +129,5 @@
|
|||
}
|
||||
else
|
||||
{
|
||||
<div><img class="spinner" src="loader.gif" alt="Vent venligst..."/> Henter data...</div>
|
||||
@* <AppSpinner/> *@
|
||||
}
|
|
@ -13,11 +13,14 @@
|
|||
// along with this program. If not, see [https://www.gnu.org/licenses/agpl-3.0.en.html]
|
||||
//
|
||||
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
using Blazored.Toast.Services;
|
||||
using Wonky.Client.HttpInterceptors;
|
||||
using Wonky.Client.HttpRepository;
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using Microsoft.AspNetCore.Components.Forms;
|
||||
using Wonky.Client.Helpers;
|
||||
using Wonky.Client.Models;
|
||||
using Wonky.Client.Services;
|
||||
using Wonky.Entity.DTO;
|
||||
|
@ -33,44 +36,59 @@ public partial class CompanyUpdate : IDisposable
|
|||
[Inject] public IToastService ToastService { get; set; }
|
||||
[Inject] public ILogger<CompanyCreate> Logger { get; set; }
|
||||
[Inject] public NavigationManager Navigation { get; set; }
|
||||
[Inject] public VirkRegistryService VirkRegistryService { get; set; }
|
||||
[Parameter] public string Account { get; set; } = null!;
|
||||
private CompanyDto _companyDto;
|
||||
private EditContext _editContext;
|
||||
[Inject] public VatOwnerLookupService VatOwnerLookupService { get; set; }
|
||||
[Parameter] public string Account { get; set; } = "";
|
||||
[Parameter] public string CompanyId { get; set; } = "";
|
||||
private CompanyDto _company { get; set; }
|
||||
private EditContext _editContext { get; set; }
|
||||
private List<VirkRegInfo> VInfos { get; set; } = new();
|
||||
private VirkRegInfo _virkRegInfo { get; set; } = new();
|
||||
private DateTime LastVisit { get; set; }
|
||||
private DateTime NextVisit { get; set; }
|
||||
private string RegState { get; set; } = "the-ugly";
|
||||
private string _vatState { get; set; } = "the-ugly";
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
_companyDto = await CompanyRepo.GetCompanyByAccount(Account);
|
||||
LastVisit = DateTime.Parse(_companyDto.LastVisit);
|
||||
NextVisit = DateTime.Parse(_companyDto.NextVisit);
|
||||
_editContext = new EditContext(_companyDto);
|
||||
Interceptor.RegisterEvent();
|
||||
Interceptor.RegisterBeforeSendEvent();
|
||||
if(!string.IsNullOrWhiteSpace(_companyDto.VatNumber))
|
||||
await GetInfoFromVat(_companyDto.VatNumber);
|
||||
//_companyDto.CompanyId = Squid.DecodeSquid(_companyDto.CompanyId).ToString();
|
||||
_company = await CompanyRepo.GetCompanyById(CompanyId);
|
||||
|
||||
LastVisit = DateTime.Parse(_company.LastVisit);
|
||||
NextVisit = DateTime.Parse(_company.NextVisit);
|
||||
_editContext = new EditContext(_company);
|
||||
|
||||
Console.WriteLine(JsonSerializer.Serialize(_company));
|
||||
|
||||
if(_company.HasFolded == 1)
|
||||
{
|
||||
_vatState = "the-dead";
|
||||
}
|
||||
else
|
||||
{
|
||||
_vatState = VatUtils.ValidateFormat(_company.CountryCode, _company.VatNumber) ? "the-good" : "the-draw";
|
||||
}
|
||||
}
|
||||
|
||||
private async Task Update()
|
||||
{
|
||||
|
||||
var lv = DateTime.TryParse(_companyDto.LastVisit, out var lvValidated);
|
||||
var nv = DateTime.TryParse(_companyDto.NextVisit, out var nvValidated);
|
||||
if (!VatUtils.ValidateFormat(_company.CountryCode, _company.VatNumber))
|
||||
{
|
||||
ToastService.ShowError($"CVR/VAT/ORG nummer er ugyldig.");
|
||||
StateHasChanged();
|
||||
return;
|
||||
}
|
||||
var lv = DateTime.TryParse(_company.LastVisit, out var lvValidated);
|
||||
var nv = DateTime.TryParse(_company.NextVisit, out var nvValidated);
|
||||
if (lv && nv)
|
||||
{
|
||||
_companyDto.LastVisit = $"{lvValidated:yyyy-MM-dd}";
|
||||
_companyDto.NextVisit = $"{nvValidated:yyyy-MM-dd}";
|
||||
_company.LastVisit = $"{lvValidated:yyyy-MM-dd}";
|
||||
_company.NextVisit = $"{nvValidated:yyyy-MM-dd}";
|
||||
|
||||
await CompanyRepo.UpdateCompany(_companyDto);
|
||||
ToastService.ShowSuccess($"Godt så. Firma '{_companyDto!.Name}' er opdateret.");
|
||||
Navigation.NavigateTo($"/company/id/{_companyDto.CompanyId}");
|
||||
await CompanyRepo.UpdateCompany(_company);
|
||||
|
||||
ToastService.ShowSuccess($"Godt så. Firma '{_company!.Name}' er opdateret.");
|
||||
Navigation.NavigateTo($"/company/{_company.CompanyId}");
|
||||
}
|
||||
|
||||
}
|
||||
private async Task GetInfoFromVat(string vatNumber)
|
||||
{
|
||||
|
@ -79,7 +97,7 @@ public partial class CompanyUpdate : IDisposable
|
|||
ToastService.ShowError($"CVR nummer mangler.");
|
||||
return;
|
||||
}
|
||||
VInfos = await VirkRegistryService
|
||||
VInfos = await VatOwnerLookupService
|
||||
.QueryVirkRegistry(
|
||||
new VirkParams
|
||||
{
|
||||
|
@ -94,7 +112,7 @@ public partial class CompanyUpdate : IDisposable
|
|||
|
||||
private async Task GetInfoFromAddress(VatAddress address)
|
||||
{
|
||||
VInfos = await VirkRegistryService.QueryVirkRegistry(
|
||||
VInfos = await VatOwnerLookupService.QueryVirkRegistry(
|
||||
new VirkParams
|
||||
{
|
||||
StreetName = address.StreetName,
|
||||
|
@ -109,12 +127,12 @@ public partial class CompanyUpdate : IDisposable
|
|||
private void SelectCompany(string vatNumber)
|
||||
{
|
||||
_virkRegInfo = (from x in VInfos where x.VatNumber == vatNumber select x).First();
|
||||
_companyDto.Name = _virkRegInfo.Name;
|
||||
_companyDto.Address1 = _virkRegInfo.CoName;
|
||||
_companyDto.Address2 = _virkRegInfo.Address;
|
||||
_companyDto.ZipCode = _virkRegInfo.ZipCode;
|
||||
_companyDto.City = _virkRegInfo.City;
|
||||
_companyDto.VatNumber = _virkRegInfo.VatNumber;
|
||||
_company.Name = _virkRegInfo.Name;
|
||||
_company.Address1 = _virkRegInfo.CoName;
|
||||
_company.Address2 = _virkRegInfo.Address;
|
||||
_company.ZipCode = _virkRegInfo.ZipCode;
|
||||
_company.City = _virkRegInfo.City;
|
||||
_company.VatNumber = _virkRegInfo.VatNumber;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
|
|
|
@ -15,61 +15,63 @@
|
|||
//
|
||||
*@
|
||||
|
||||
@page "/company/account/{account}"
|
||||
@page "/company/id/{companyId}"
|
||||
@page "/company/{companyId}"
|
||||
@using Microsoft.AspNetCore.Authorization
|
||||
@using Wonky.Client.Components;
|
||||
@using Wonky.Client.Helpers
|
||||
@using Wonky.Entity.Models
|
||||
@attribute [Authorize(Roles = "Adviser")]
|
||||
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
|
||||
<div class="card-header">
|
||||
<div class="h2">@(_hasFolded ? @_company.Account : "LUKKET" ) - @_company.Name</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<table class="table table-sm table-striped table-bordered">
|
||||
<tbody>
|
||||
<tr>
|
||||
<th scope="row">Navn</th>
|
||||
<td colspan="2">@CompanyDto.Name</td>
|
||||
<td colspan="2">@_company.Name</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">CO navn</th>
|
||||
<td colspan="2">@CompanyDto.Address1</td>
|
||||
<td colspan="2">@_company.Address1</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">Adresse</th>
|
||||
<td colspan="2">@CompanyDto.Address2</td>
|
||||
<td colspan="2">@_company.Address2</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">Postnummer</th>
|
||||
<td colspan="2">@CompanyDto.ZipCode</td>
|
||||
<td colspan="2">@_company.ZipCode</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">Bynavn</th>
|
||||
<td colspan="2">@CompanyDto.City</td>
|
||||
<td colspan="2">@_company.City</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">CVR</th>
|
||||
<td><RegStateVatNumber VatNumber="@CompanyDto.VatNumber"></RegStateVatNumber></td>
|
||||
<td>@CompanyDto.VatNumber</td>
|
||||
<td class="state"><DisplayStateComponent StateClass="@_vatState"></DisplayStateComponent></td>
|
||||
<td>@_company.VatNumber</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">Telefon</th>
|
||||
<td colspan="2">@CompanyDto.Phone</td>
|
||||
<td colspan="2">@_company.Phone</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">Email</th>
|
||||
<td colspan="2">@CompanyDto.Email</td>
|
||||
<td colspan="2">@_company.Email</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">Sidste besøg</th>
|
||||
<td colspan="2">@CompanyDto.LastVisit</td>
|
||||
<td colspan="2">@_company.LastVisit</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">Næste besøg</th>
|
||||
<td><DisplayStateComponent StateClass="@(Utils.GetVisitState(CompanyDto.NextVisit))"></DisplayStateComponent></td>
|
||||
<td>@CompanyDto.NextVisit</td>
|
||||
<td class="state"><DisplayStateComponent StateClass="@(Utils.GetVisitState(_company.NextVisit))"></DisplayStateComponent></td>
|
||||
<td>@_company.NextVisit</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
@ -78,10 +80,10 @@
|
|||
<div class="row flex-row align-items-end">
|
||||
<div class="col flex-column">
|
||||
<a class="btn btn-primary float-start mx-2" href="/companies">Tilbage</a>
|
||||
<a class="btn btn-primary float-start" href="/company/@CompanyDto.Account/update">Rediger</a>
|
||||
<a class="btn btn-primary float-start" href="/company/@_company.CompanyId/update">Rediger</a>
|
||||
</div>
|
||||
<div class="col flex-column">
|
||||
<a class="btn btn-primary float-end mx-2" href="/company/@CompanyDto.Account/Activity">Aktivitet</a>
|
||||
<a class="btn btn-primary float-end mx-2" href="/company/@_company.CompanyId/Activity">Aktivitet</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -29,45 +29,35 @@ public partial class CompanyView : IDisposable
|
|||
{
|
||||
[Inject] public ICompanyHttpRepository CompanyRepo { get; set; }
|
||||
[Inject] public HttpInterceptorService Interceptor { get; set; }
|
||||
[Inject] public VirkRegistryService VirkRegistryService { get; set; }
|
||||
[Parameter] public string Account { get; set; } = "";
|
||||
[Inject] public VatOwnerLookupService VatOwnerLookup { get; set; }
|
||||
[Inject] public ILogger<CompanyView> Logger { get; set; }
|
||||
[Parameter] public string CompanyId { get; set; } = "";
|
||||
private CompanyDto CompanyDto { get; set; } = new ();
|
||||
private VirkRegInfo VirkRegInfo { get; set; } = new();
|
||||
private string VisitState { get; set; } = "the-ugly";
|
||||
private bool ValidCvr { get; set; } = true;
|
||||
|
||||
private CompanyDto _company { get; set; } = new ();
|
||||
private string _vatState { get; set; } = "the-dead";
|
||||
private bool _hasFolded { get; set; }
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
Interceptor.RegisterEvent();
|
||||
Interceptor.RegisterBeforeSendEvent();
|
||||
if (!string.IsNullOrWhiteSpace(Account))
|
||||
_company = await CompanyRepo.GetCompanyById(CompanyId);
|
||||
|
||||
if(_company.HasFolded == 1)
|
||||
{
|
||||
CompanyDto = await CompanyRepo.GetCompanyByAccount(Account);
|
||||
_vatState = "the-dead";
|
||||
_hasFolded = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(CompanyId))
|
||||
{
|
||||
CompanyDto = await CompanyRepo.GetCompanyById(CompanyId);
|
||||
_vatState = VatUtils.ValidateFormat(_company.CountryCode, _company.VatNumber) ? "the-good" : "the-draw";
|
||||
}
|
||||
}
|
||||
|
||||
var theUgly = DateTime.Parse(CompanyDto.NextVisit);
|
||||
var theBad = theUgly.AddDays(-14);
|
||||
if (DateTime.Now <= theUgly)
|
||||
{
|
||||
VisitState = DateTime.Now >= theBad ? "the-bad" : "the-good";
|
||||
}
|
||||
ValidCvr = string.IsNullOrEmpty(CompanyDto.VatNumber) || CompanyDto.VatNumber.Length <= 8;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
|
||||
/// </summary>
|
||||
public void Dispose()
|
||||
{
|
||||
Interceptor!.DisposeEvent();
|
||||
Interceptor.DisposeEvent();
|
||||
}
|
||||
}
|
|
@ -15,7 +15,7 @@
|
|||
//
|
||||
*@
|
||||
|
||||
@page "/company/{account}/activity"
|
||||
@page "/company/{companyId}/activity"
|
||||
@using Microsoft.AspNetCore.Authorization
|
||||
@attribute [Authorize(Roles = "Adviser")]
|
||||
@using Wonky.Client.Components
|
||||
|
@ -102,6 +102,9 @@
|
|||
|
||||
|
||||
<div class="row mb-2">
|
||||
<div class="col">
|
||||
<a class="btn btn-primary" href="/company/@_company.CompanyId"></a>
|
||||
</div>
|
||||
<div class="col">
|
||||
<button type="submit" class="btn btn-success" disabled="@_poFormInvalid">Tilbud</button>
|
||||
<button type="submit" class="btn btn-success" disabled="@_poFormInvalid">Bestilling</button>
|
||||
|
|
|
@ -33,7 +33,7 @@ public partial class PurchaseOrderCreate : IDisposable
|
|||
{
|
||||
private List<SalesItemDto> SalesItemList { get; set; } = new();
|
||||
private PurchaseOrder _purchaseOrder = new ();
|
||||
private CompanyDto _companyDto = new();
|
||||
private CompanyDto _company = new();
|
||||
private EditContext _editContext;
|
||||
private bool _poFormInvalid = true;
|
||||
private MetaData? MetaData { get; set; } = new();
|
||||
|
@ -46,7 +46,7 @@ public partial class PurchaseOrderCreate : IDisposable
|
|||
[Inject] public HttpInterceptorService Interceptor { get; set; }
|
||||
[Inject] public ILocalStorageService StorageService { get; set; }
|
||||
[Inject] public ISalesItemHttpRepository SalesItemRepo { get; set; }
|
||||
[Parameter] public string Account { get; set; }
|
||||
[Parameter] public string CompanyId { get; set; }
|
||||
|
||||
public List<CrmSalesLines> Lines { get; set; } = new();
|
||||
protected override async Task OnInitializedAsync()
|
||||
|
@ -55,9 +55,7 @@ public partial class PurchaseOrderCreate : IDisposable
|
|||
Interceptor.RegisterBeforeSendEvent();
|
||||
|
||||
var ux = await StorageService.GetItemAsync<UserInfoDto>("_ux");
|
||||
|
||||
_companyDto = await CompanyRepo.GetCompanyByAccount(Account);
|
||||
|
||||
_company = await CompanyRepo.GetCompanyById(CompanyId);
|
||||
_editContext = new EditContext(_purchaseOrder);
|
||||
_editContext.OnFieldChanged += HandleFieldChanged;
|
||||
|
||||
|
@ -66,30 +64,30 @@ public partial class PurchaseOrderCreate : IDisposable
|
|||
|
||||
// permanent identifications
|
||||
_purchaseOrder.SalesRep = ux.Adviser;
|
||||
_purchaseOrder.Account = Account;
|
||||
_purchaseOrder.VatNumber = _companyDto.VatNumber;
|
||||
_purchaseOrder.EMail = _companyDto.Email;
|
||||
_purchaseOrder.Phone = _companyDto.Phone;
|
||||
_purchaseOrder.Account = _company.Account;
|
||||
_purchaseOrder.VatNumber = _company.VatNumber;
|
||||
_purchaseOrder.EMail = _company.Email;
|
||||
_purchaseOrder.Phone = _company.Phone;
|
||||
_purchaseOrder.OurRef = ux.FullName.Split(" ")[0];
|
||||
|
||||
_purchaseOrder.Name = _companyDto.Name;
|
||||
_purchaseOrder.Address = _companyDto.Address1;
|
||||
_purchaseOrder.Address2 = _companyDto.Address2;
|
||||
_purchaseOrder.ZipCode = _companyDto.ZipCode;
|
||||
_purchaseOrder.City = _companyDto.City;
|
||||
_purchaseOrder.Name = _company.Name;
|
||||
_purchaseOrder.Address = _company.Address1;
|
||||
_purchaseOrder.Address2 = _company.Address2;
|
||||
_purchaseOrder.ZipCode = _company.ZipCode;
|
||||
_purchaseOrder.City = _company.City;
|
||||
|
||||
_purchaseOrder.DlvName = _companyDto.Name;
|
||||
_purchaseOrder.DlvAddress1 = _companyDto.Address1;
|
||||
_purchaseOrder.DlvAddress2 = _companyDto.Address2;
|
||||
_purchaseOrder.DlvZipCode = _companyDto.ZipCode;
|
||||
_purchaseOrder.DlvCity = _companyDto.City;
|
||||
_purchaseOrder.DlvName = _company.Name;
|
||||
_purchaseOrder.DlvAddress1 = _company.Address1;
|
||||
_purchaseOrder.DlvAddress2 = _company.Address2;
|
||||
_purchaseOrder.DlvZipCode = _company.ZipCode;
|
||||
_purchaseOrder.DlvCity = _company.City;
|
||||
|
||||
}
|
||||
|
||||
|
||||
private async Task CreateActivity()
|
||||
{
|
||||
await StorageService.SetItemAsync(Account, _purchaseOrder);
|
||||
await StorageService.SetItemAsync(CompanyId, _purchaseOrder);
|
||||
|
||||
ToastService.ShowSuccess($"Aktivitet oprettet.");
|
||||
}
|
||||
|
|
|
@ -57,7 +57,7 @@ builder.Services.AddAuthorizationCore();
|
|||
builder.Services.AddScoped<AuthenticationStateProvider, AuthStateProvider>();
|
||||
builder.Services.AddScoped<IAuthenticationService, AuthenticationService>();
|
||||
builder.Services.AddScoped<RefreshTokenService>();
|
||||
builder.Services.AddScoped<VirkRegistryService>();
|
||||
builder.Services.AddScoped<VatOwnerLookupService>();
|
||||
builder.Services.AddScoped<UserPreferenceService>();
|
||||
|
||||
|
||||
|
|
|
@ -22,14 +22,14 @@ using Wonky.Entity.Requests;
|
|||
|
||||
namespace Wonky.Client.Services;
|
||||
|
||||
public class VirkRegistryService
|
||||
public class VatOwnerLookupService
|
||||
{
|
||||
private readonly JsonSerializerOptions _options = new() { PropertyNameCaseInsensitive = true };
|
||||
private readonly HttpClient _client;
|
||||
private readonly IOptions<ApiConfig> _apiConfig;
|
||||
private readonly List<VirkRegInfo> _noData = new() { new VirkRegInfo { Name = "INGEN DATA" } };
|
||||
|
||||
public VirkRegistryService(HttpClient client, IOptions<ApiConfig> apiConfig)
|
||||
public VatOwnerLookupService(HttpClient client, IOptions<ApiConfig> apiConfig)
|
||||
{
|
||||
_client = client;
|
||||
_apiConfig = apiConfig;
|
|
@ -14,6 +14,9 @@
|
|||
min-width: 24px;
|
||||
min-height: 24px;
|
||||
}
|
||||
.the-dead {
|
||||
background-color: black;
|
||||
}
|
||||
.the-draw {
|
||||
background-color: purple;
|
||||
}
|
||||
|
|
|
@ -21,10 +21,10 @@ namespace Wonky.Entity.DTO;
|
|||
|
||||
public class CompanyDto
|
||||
{
|
||||
[Required(ErrorMessage = "Navn skal udyldes")] public string Name { get; set; } = "";
|
||||
[Required(ErrorMessage = "Postnummer skal udfyldes")] public string ZipCode { get; set; } = "";
|
||||
[Required(ErrorMessage = "Bynavn skal udfyldes")] public string City { get; set; } = "";
|
||||
public string VatNumber { get; set; } = "";
|
||||
[Required(ErrorMessage = "Navn skal udyldes")] public string Name { get; set; }
|
||||
[Required(ErrorMessage = "Postnummer skal udfyldes")] public string ZipCode { get; set; }
|
||||
[Required(ErrorMessage = "Bynavn skal udfyldes")] public string City { get; set; }
|
||||
[Required(ErrorMessage = "ORG/VAT/CVR er ikke et gyldigt nummer")] public string VatNumber { get; set; }
|
||||
public string CompanyId { get; set; } = "";
|
||||
public string SalesRepId { get; set; } = "";
|
||||
public string BcId { get; set; } = "";
|
||||
|
|
Loading…
Reference in a new issue