adding http repos for endpoint splitting

This commit is contained in:
Frede Hundewadt 2022-11-20 15:16:58 +01:00
parent 7c718360d8
commit 341e254071
7 changed files with 362 additions and 261 deletions

View file

@ -13,6 +13,8 @@
// along with this program. If not, see [https://www.gnu.org/licenses/agpl-3.0.en.html]
//
using System.Globalization;
namespace Wonky.Client.Helpers;
public class VatUtils
@ -22,18 +24,24 @@ public class VatUtils
public static bool ValidateFormat(string countryCode, string vatNumber)
{
if (string.IsNullOrWhiteSpace(vatNumber) || string.IsNullOrWhiteSpace(countryCode))
if (string.IsNullOrWhiteSpace(vatNumber) || string.IsNullOrWhiteSpace(countryCode) || !IsDigitsOnly(vatNumber))
return false;
var sanitisedVat = SanitizeVatNumber(vatNumber);
return countryCode.ToUpperInvariant() switch
{
"DK" => ValidateFormatDk(vatNumber),
"NO" => ValidateFormatNo(vatNumber),
"SE" => ValidateFormatSe(vatNumber),
"DK" => ValidateFormatDk(sanitisedVat),
"NO" => ValidateFormatNo(sanitisedVat),
"SE" => ValidateFormatSe(sanitisedVat),
_ => false
};
}
private static bool IsDigitsOnly(string check)
{
return check.All(c => c is >= '0' and <= '9');
}
private static bool ValidateFormatDk(string vatNumber)
{
// https://wiki.scn.sap.com/wiki/display/CRM/Denmark
@ -42,12 +50,11 @@ public class VatUtils
// C8 check-digit MOD11
// C1 > 0
// R = (2*C1 + 7*C2 + 6*C3 + 5*C4 + 4*C5 + 3*C6 + 2*C7 + C8)
var vatToCheck = SanitizeVatNumber(vatNumber);
if (vatToCheck.Length != 8)
if (vatNumber.Length != 8)
return false;
if ((int)char.GetNumericValue(vatToCheck[0]) < 1 || vatToCheck.Length > 8)
if ((int)char.GetNumericValue(vatNumber[0]) < 1 || vatNumber.Length > 8)
return false;
return ValidateMod11(vatToCheck);
return ValidateMod11(vatNumber);
}
private static bool ValidateFormatNo(string vatNumber)
@ -57,10 +64,9 @@ public class VatUtils
// C1..C8 random 0 to 9
// C9 check-digit MOD11
// C10 C11 C12 chars == MVA
var vatToCheck = SanitizeVatNumber(vatNumber);
if (vatToCheck.Length != 9)
if (vatNumber.Length != 9)
return false;
return long.Parse(vatToCheck) != 0 && ValidateMod11(vatNumber);
return long.Parse(vatNumber) != 0 && ValidateMod11(vatNumber);
}
private static bool ValidateFormatSe(string vatNumber)
@ -72,7 +78,7 @@ public class VatUtils
// Si = int(Ci/5) + (Ci*2)MOD10)
// https://www.skatteverket.se/skatter/mervardesskattmoms/momsregistreringsnummer.4.18e1b10334ebe8bc80002649.html
// C11 C12 == 01 (De två sista siffrorna är alltid 01)
var vatToCheck = SanitizeVatNumber(vatNumber);
var vatToCheck = vatNumber;
if (vatToCheck.Length < 10 || long.Parse(vatToCheck) == 0)
return false;
@ -104,8 +110,7 @@ public class VatUtils
private static string SanitizeVatNumber(string vatNumber)
{
vatNumber = vatNumber.ToUpperInvariant();
return vatNumber
return vatNumber.ToUpperInvariant()
.Replace(" ", "")
.Replace("-", "")
.Replace("DK", "")

View file

@ -26,4 +26,7 @@ public interface ICrmCompanyHttpRepository
Task<string> CreateCompany(CompanyDto model);
Task<bool> UpdateCompany(string companyId, CompanyDto model);
Task<bool> DeleteCompany(string companyId);
Task<CompanyDto> UpdateCrmData(string companyId, CompanyDto model);
Task<CompanyDto> UpdateErpData(string companyId, CompanyDto model);
Task<CompanyDto> UpdateCompanyVat(string companyId, string vatNumber);
}

View file

@ -115,10 +115,9 @@ public class CrmCompanyHttpRepository : ICrmCompanyHttpRepository
{
var response = await _client.PutAsJsonAsync($"{_conf.CrmCustomers}/{companyId}", model);
var content = await response.Content.ReadAsStringAsync();
Console.WriteLine(content);
return response.IsSuccessStatusCode;
}
/// <summary>
/// Delete company
/// </summary>
@ -129,4 +128,48 @@ public class CrmCompanyHttpRepository : ICrmCompanyHttpRepository
var response = await _client.DeleteAsync($"{_conf.CrmCustomers}/{companyId}");
return response.IsSuccessStatusCode;
}
/// <summary>
/// Update Company CRM properties
/// </summary>
/// <param name="companyId"></param>
/// <param name="model"></param>
/// <returns></returns>
public async Task<CompanyDto> UpdateCrmData(string companyId, CompanyDto model)
{
var response = await _client.PutAsJsonAsync($"{_conf.CrmCustomers}/{companyId}/crmData", model, _options);
var content = await response.Content.ReadAsStringAsync();
return string.IsNullOrWhiteSpace(content) ? new CompanyDto() : JsonSerializer.Deserialize<CompanyDto>(content);
}
/// <summary>
/// Update Company ERP properties
/// </summary>
/// <param name="companyId"></param>
/// <param name="model"></param>
/// <returns></returns>
public async Task<CompanyDto> UpdateErpData(string companyId, CompanyDto model)
{
var response = await _client.PutAsJsonAsync($"{_conf.CrmCustomers}/{companyId}/erpData", model, _options);
var content = await response.Content.ReadAsStringAsync();
return string.IsNullOrWhiteSpace(content) ? new CompanyDto() : JsonSerializer.Deserialize<CompanyDto>(content);
}
/// <summary>
/// Update company VAT number
/// </summary>
/// <param name="companyId"></param>
/// <param name="vatNumber"></param>
/// <returns></returns>
public async Task<CompanyDto> UpdateCompanyVat(string companyId, string vatNumber)
{
var model = new Dictionary<string, string>
{
{ "VatNumber", vatNumber }
};
var response = await _client.PutAsJsonAsync($"{_conf.CrmCustomers}/{companyId}/vat", model, _options);
var content = await response.Content.ReadAsStringAsync();
return string.IsNullOrWhiteSpace(content) ? new CompanyDto() : JsonSerializer.Deserialize<CompanyDto>(content);
}
}

View file

@ -29,230 +29,236 @@
<h4>Ring til kontoret. Denne konto er spærret med kode '@Company.Blocked'</h4>
</div>
}
<div class="card">
<div class="card-header bg-dark text-white">
<div class="alert bg-dark text-white">
<h3>@Company.Name</h3>
</div>
@if (Dk)
{
<div class="card-body">
<VatAddressInputComponent Address="CompanyVatAddress" OnValidSubmit="GetInfoFromAddress"/>
@if (VatInfos.Any())
{
<table class="table">
<thead>
<tr>
<th scope="col">CVR ORG</th>
<th scope="col">Navn</th>
<th scope="col">Status</th>
<th scope="col"></th>
<th scope="col"></th>
</tr>
</thead>
<tbody>
@foreach (var info in VatInfos)
{
<tr>
<td class="align-middle">@info.VatNumber</td>
<td class="align-middle">@info.Name</td>
<td class="align-middle">@info.States[^1].State</td>
<td class="align-middle">
<button class="btn btn-primary" @onclick="@(() => SelectCompany(info.VatNumber, true))">OVERFØR</button>
</td>
<td class="align-middle">
<button class="btn btn-primary" @onclick="@(() => SelectCompany(info.VatNumber, false))">CVR/VAT</button>
</td>
</tr>
}
</tbody>
</table>
}
</div>
}
<EditForm EditContext="CompanyContext" OnValidSubmit="SubmitUpdate">
<EditForm EditContext="ErpContext" OnValidSubmit="SubmitUpdate">
<DataAnnotationsValidator/>
<div class="card-body">
<div class="row mb-1">
<label for="note" class="col-sm-1 col-form-label-sm">OBS</label>
<div class="col-sm-9">
@if (string.IsNullOrWhiteSpace(Company.Note))
{
<InputText name="note" id="note" class="form-control" @bind-Value="Company.Note"/>
}
else
{
<InputText name="note" id="note" class="form-control bg-warning text-black" @bind-Value="Company.Note"/>
}
<ValidationMessage For="@(() => Company.Note)"></ValidationMessage>
</div>
<div class="row mb-1">
<label for="name" class="col-sm-1 col-form-label-sm">Navn</label>
<div class="col-sm-5">
<InputText id="name" class="form-control" @bind-Value="Company.Name"/>
<ValidationMessage For="@(() => Company.Name)"></ValidationMessage>
</div>
<label for="attention" class="col-sm-1 col-form-label-sm">Att.</label>
<div class="col-sm-3">
<InputText id="attention" class="form-control" @bind-Value="Company.Attention"/>
<ValidationMessage For="@(() => Company.Attention)"></ValidationMessage>
</div>
</div>
<div class="row mb-1">
<label for="vatNumber" class="col-sm-1 col-form-label-sm">MomsNr</label>
<div class="col-sm-4">
<div class="input-group">
<span class="input-group-text">
<DisplayStateComponent StateClass="@VatState"/>
</span>
<InputText id="vatNumber" class="form-control" @bind-Value="Company.VatNumber"/>
<ValidationMessage For="@(() => Company.VatNumber)"></ValidationMessage>
</div>
</div>
<label for="account" class="col-sm-1 col-form-label-sm">Konto</label>
<div class="col-sm-4">
<input id="account" type="text" class="form-control" readonly value="@Company.Account"/>
</div>
<div class="row mb-1">
<label for="address1" class="col-sm-1 col-form-label-sm">Adresse</label>
<div class="col-sm-5">
<InputText id="address1" class="form-control" @bind-Value="Company.Address1"/>
<ValidationMessage For="@(() => Company.Address1)"></ValidationMessage>
</div>
<label for="address2" class="col-sm-1 col-form-label-sm">Adresse</label>
<div class="col-sm-3">
<InputText id="address2" class="form-control" @bind-Value="Company.Address2"/>
<ValidationMessage For="@(() => Company.Address2)"></ValidationMessage>
</div>
</div>
<div class="row mb-1">
<label for="name" class="col-sm-1 col-form-label-sm">Navn</label>
<div class="col-sm-5">
<InputText id="name" class="form-control" @bind-Value="Company.Name"/>
<ValidationMessage For="@(() => Company.Name)"></ValidationMessage>
</div>
<label for="attention" class="col-sm-1 col-form-label-sm">Att.</label>
<div class="col-sm-3">
<InputText id="attention" class="form-control" @bind-Value="Company.Attention"/>
<ValidationMessage For="@(() => Company.Attention)"></ValidationMessage>
</div>
<div class="row mb-1">
<label for="zipCode" class="col-sm-1 col-form-label-sm">PostNr</label>
<div class="col-sm-2">
<InputText id="zipCode" class="form-control" @bind-Value="Company.ZipCode"/>
<ValidationMessage For="@(() => Company.ZipCode)"></ValidationMessage>
</div>
<div class="row mb-1">
<label for="address1" class="col-sm-1 col-form-label-sm">Adresse</label>
<div class="col-sm-5">
<InputText id="address1" class="form-control" @bind-Value="Company.Address1"/>
<ValidationMessage For="@(() => Company.Address1)"></ValidationMessage>
</div>
<label for="address2" class="col-sm-1 col-form-label-sm">Adresse</label>
<div class="col-sm-3">
<InputText id="address2" class="form-control" @bind-Value="Company.Address2"/>
<ValidationMessage For="@(() => Company.Address2)"></ValidationMessage>
</div>
</div>
<div class="row mb-1">
<label for="zipCode" class="col-sm-1 col-form-label-sm">PostNr</label>
<div class="col-sm-2">
<InputText id="zipCode" class="form-control" @bind-Value="Company.ZipCode"/>
<ValidationMessage For="@(() => Company.ZipCode)"></ValidationMessage>
</div>
<label for="city" class="col-sm-1 col-form-label-sm">Bynavn</label>
<div class="col-sm-6">
<InputText id="city" class="form-control" @bind-Value="Company.City"/>
<ValidationMessage For="@(() => Company.City)"></ValidationMessage>
</div>
<label for="city" class="col-sm-1 col-form-label-sm">Bynavn</label>
<div class="col-sm-6">
<InputText id="city" class="form-control" @bind-Value="Company.City"/>
<ValidationMessage For="@(() => Company.City)"></ValidationMessage>
</div>
</div>
<div class="row mb-1">
<label for="phone" class="col-sm-1 col-form-label-sm">Telefon</label>
<div class="col-sm-4">
<InputText id="phone" class="form-control" @bind-Value="Company.Phone"/>
<ValidationMessage For="@(() => Company.Phone)"></ValidationMessage>
</div>
<label for="mobile" class="col-sm-1 col-form-label-sm">Mobil</label>
<div class="col-sm-4">
<InputText id="mobile" class="form-control" @bind-Value="Company.Mobile"/>
<ValidationMessage For="@(() => Company.Mobile)"></ValidationMessage>
</div>
<div class="row mb-1">
<label for="phone" class="col-sm-1 col-form-label-sm">Telefon</label>
<div class="col-sm-4">
<InputText id="phone" class="form-control" @bind-Value="Company.Phone"/>
<ValidationMessage For="@(() => Company.Phone)"></ValidationMessage>
</div>
<div class="row mb-1">
<label for="email" class="col-sm-1 col-form-label-sm">Epost</label>
<div class="col-sm-9">
<InputText id="email" class="form-control" @bind-Value="Company.Email"/>
<ValidationMessage For="@(() => Company.Email)"></ValidationMessage>
</div>
<label for="mobile" class="col-sm-1 col-form-label-sm">Mobil</label>
<div class="col-sm-4">
<InputText id="mobile" class="form-control" @bind-Value="Company.Mobile"/>
<ValidationMessage For="@(() => Company.Mobile)"></ValidationMessage>
</div>
<hr/>
<div class="row mb-1">
<label for="nextVisit" class="col-sm-1 col-form-label-sm">Næste besøg</label>
<div class="col-sm-3">
<div class="input-group">
<span class="input-group-text">
<DisplayStateComponent StateClass="@VisitState"/>
</span>
<InputDate id="nextVisit" class="form-control" @bind-Value="@(NextVisit)"/>
</div>
</div>
<label for="lastVisit" class="col-sm-1 col-form-label-sm">Sidse besøg</label>
<div class="col-sm-3">
<InputDate id="lastVisit" class="form-control" @bind-Value="@LastVisit"/>
</div>
<label for="interval" class="col-sm-2 col-form-label-sm">Uge Interval</label>
<div class="col-sm-2">
<InputNumber id="interval" class="form-control" @bind-Value="Company.Interval"/>
<ValidationMessage For="@(() => Company.Interval)"></ValidationMessage>
</div>
</div>
<div class="row mb-1">
<label for="contacts" class="col-sm-1 col-form-label-sm">Kontakt</label>
<div id="contacts" class="col-sm-6">
<div class="list-group">
<div class="list-group-item list-group-item-action" @onclick="() => OpenContact(DefaultContact)">
<div class="row">
<div class="col">Stilling</div>
<div class="col">Navn</div>
<div class="col">Direkte</div>
<div class="col text-end">
<i class="bi-plus-circle"></i>
</div>
</div>
</div>
@if (Contacts.Any())
{
@foreach (var contact in Contacts)
{
<div class="list-group-item list-group-item-action" @onclick="() => OpenContact(contact)">
<div class="row">
<div class="col">@contact.JobTitle</div>
<div class="col">@contact.FirstName @contact.LastName</div>
<div class="col">@contact.PhoneDirect</div>
<div class="col text-end">
<i class="bi-pencil"></i>
</div>
</div>
</div>
}
}
</div>
</div>
<label for="crmNotes" class="col-sm-1 col-form-label-sm">Noter</label>
<div class="col-sm-4">
<InputTextArea id="crmNotes" class="form-control" style="height: 100%;" @bind-Value="Company.CrmNotes"/>
</div>
</div>
<div class="row mb-1">
<label for="email" class="col-sm-1 col-form-label-sm">Epost</label>
<div class="col-sm-9">
<InputText id="email" class="form-control" @bind-Value="Company.Email"/>
<ValidationMessage For="@(() => Company.Email)"></ValidationMessage>
</div>
</div>
<div class="card-footer">
<div class="row mb-2">
<div class="col">
<a class="btn btn-light border-dark d-block" href="/companies/@Company.CompanyId/invoices">Faktura</a>
<hr/>
@* vat context *@
<div class="row mb-1">
<label for="vatNumber" class="col-sm-1 col-form-label-sm">MomsNr</label>
<div class="col-sm-4">
<div class="input-group">
<span class="input-group-text">
<DisplayStateComponent StateClass="@VatState"/>
</span>
<InputText id="vatNumber" class="form-control" @bind-Value="Company.VatNumber"/>
<ValidationMessage For="@(() => Company.VatNumber)"></ValidationMessage>
</div>
<div class="col">
<a class="btn btn-light border-dark d-block" href="/companies/@Company.CompanyId/activities">Besøg</a>
</div>
<label for="account" class="col-sm-1 col-form-label-sm">Konto</label>
<div class="col-sm-4">
<input id="account" type="text" class="form-control" readonly value="@Company.Account"/>
</div>
</div>
@* erp context *@
<div class="row mb-1">
<label for="note" class="col-sm-1 col-form-label-sm">OBS</label>
<div class="col-sm-9">
@if (string.IsNullOrWhiteSpace(Company.Note))
{
<InputText name="note" id="note" class="form-control" @bind-Value="Company.Note"/>
}
else
{
<InputText name="note" id="note" class="form-control bg-warning text-black" @bind-Value="Company.Note"/>
}
<ValidationMessage For="@(() => Company.Note)"></ValidationMessage>
</div>
</div>
<div class="row mb-1">
<label for="nextVisit" class="col-sm-1 col-form-label-sm">Næste besøg</label>
<div class="col-sm-3">
<div class="input-group">
<span class="input-group-text">
<DisplayStateComponent StateClass="@VisitState"/>
</span>
<InputDate id="nextVisit" class="form-control" @bind-Value="@(NextVisit)"/>
</div>
<div class="col">
<a class="btn btn-light border-dark d-block" href="/companies/@Company.CompanyId/h/i">Produkter</a>
</div>
<div class="col d-block">
<button type="submit" class="btn btn-light border-dark d-block" disabled="@(Working)">Gem</button>
@if (Company.HasFolded == 1)
</div>
<label for="lastVisit" class="col-sm-1 col-form-label-sm">Sidse besøg</label>
<div class="col-sm-3">
<InputDate id="lastVisit" class="form-control" @bind-Value="@LastVisit"/>
</div>
<label for="interval" class="col-sm-2 col-form-label-sm">Uge Interval</label>
<div class="col-sm-2">
<InputNumber id="interval" class="form-control" @bind-Value="Company.Interval"/>
<ValidationMessage For="@(() => Company.Interval)"></ValidationMessage>
</div>
</div>
<div class="row mb-1">
<label for="contacts" class="col-sm-1 col-form-label-sm">Kontakt</label>
<div id="contacts" class="col-sm-6">
<div class="list-group">
<div class="list-group-item list-group-item-action" @onclick="() => OpenContact(DefaultContact)">
<div class="row">
<div class="col-sm-4">Stilling</div>
<div class="col-sm-4">Navn</div>
<div class="col-sm-3">Direkte</div>
<div class="col-sm-1 text-end">
<i class="bi-plus-circle"></i>
</div>
</div>
</div>
@if (Contacts.Any())
{
<button type="button" class="btn btn-warning" onclick="@ForceActivity">Aktiver besøg</button>
@foreach (var contact in Contacts)
{
<div class="list-group-item list-group-item-action" @onclick="() => OpenContact(contact)">
<div class="row">
<div class="col-sm-4">@contact.JobTitle</div>
<div class="col-sm-4">@contact.FirstName @contact.LastName</div>
<div class="col-sm-3">@contact.PhoneDirect</div>
<div class="col-sm-1 text-end">
<i class="bi-pencil"></i>
</div>
</div>
</div>
}
}
</div>
<div class="col">
<ActivityButton ActionLink="@ActionLink"
ButtonText="Besøg"
ButtonType="primary"
Enabled="@EnableActivity">
</ActivityButton>
</div>
</div>
<label for="crmNotes" class="col-sm-1 col-form-label-sm">Noter</label>
<div class="col-sm-4">
<InputTextArea id="crmNotes" class="form-control" style="height: 100%;" @bind-Value="Company.CrmNotes"/>
</div>
</div>
<div class="row mt-3 mb-2">
<div class="col">
<a class="btn btn-light border-dark d-block" href="/companies/@Company.CompanyId/invoices">Faktura</a>
</div>
<div class="col">
<a class="btn btn-light border-dark d-block" href="/companies/@Company.CompanyId/activities">Besøg</a>
</div>
<div class="col">
<a class="btn btn-light border-dark d-block" href="/companies/@Company.CompanyId/h/i">Produkter</a>
</div>
<div class="col d-block">
<button type="submit" class="btn btn-light border-dark d-block" disabled="@(Working)">Gem</button>
@if (Company.HasFolded == 1)
{
<button type="button" class="btn btn-warning" onclick="@ForceActivity">Aktiver besøg</button>
}
</div>
<div class="col">
<ActivityButton ActionLink="@ActionLink"
ButtonText="Besøg"
ButtonType="primary"
Enabled="@EnableActivity">
</ActivityButton>
</div>
</div>
</EditForm>
</div>
@if (Dk)
{
<div class="alert alert-light border-dark">
<h3>CVR adresse kontrol</h3>
<div class="row mt-2">
<VatAddressInputComponent Address="CompanyVatAddress" OnValidSubmit="GetInfoFromAddress"/>
@if (VatInfos.Any())
{
<table class="table">
<thead>
<tr>
<th scope="col">CVR ORG</th>
<th scope="col">Navn</th>
<th scope="col">Status</th>
<th scope="col"></th>
<th scope="col"></th>
</tr>
</thead>
<tbody>
@foreach (var info in VatInfos)
{
<tr>
<td class="align-middle">@info.VatNumber</td>
<td class="align-middle">@info.Name</td>
<td class="align-middle">@info.States[^1].State</td>
<td class="align-middle">
<button class="btn btn-primary" @onclick="@(() => SelectCompany(info.VatNumber, true))">OVERFØR</button>
</td>
<td class="align-middle">
<button class="btn btn-primary" @onclick="@(() => SelectCompany(info.VatNumber, false))">CVR/VAT</button>
</td>
</tr>
}
</tbody>
</table>
}
</div>
</div>
}
}
else
{
@ -260,4 +266,4 @@ else
}
<VatLookupDkModal VatAddress="CompanyVatAddress" OnSelectedCompany="OnSelectedCompany" @ref="VatLookupPopup"/>
<ContactModal ParamContact="@SelectedContact" CompanyName="@Company.Name" @ref="ContactPopup" OnSaveClicked="SaveContact" OnDeleteClicked="DeleteContact" />
<ContactModal ParamContact="@SelectedContact" CompanyName="@Company.Name" @ref="ContactPopup" OnSaveClicked="SaveContact" OnDeleteClicked="DeleteContact"/>

View file

@ -50,7 +50,8 @@ public partial class CrmCompanyViewPage : IDisposable
[Inject] public ILocalStorageService Storage { get; set; }
private readonly JsonSerializerOptions _options = new () { PropertyNameCaseInsensitive = true };
private CompanyDto Company { get; set; } = new();
private EditContext CompanyContext { get; set; }
private EditContext ErpContext { get; set; }
private EditContext CrmContext { get; set; }
private List<VirkRegInfo> VatInfos { get; set; } = new();
private VirkRegInfo CompanyRegInfo { get; set; } = new();
private DateTime LastVisit { get; set; }
@ -129,9 +130,10 @@ public partial class CrmCompanyViewPage : IDisposable
ValidVat = Company.ValidVat == 1; // flag set if company has a valid vatNumber
VatState = Company.ValidVat == 1 ? "the-good" : "no-vat"; // assign css class
}
CompanyContext = new EditContext(Company);
CompanyContext.OnFieldChanged += HandleFieldChanged;
CompanyContext.OnValidationStateChanged += ValidationChanged;
ErpContext = new EditContext(Company);
ErpContext.OnFieldChanged += HandleFieldChanged;
ErpContext.OnValidationStateChanged += ValidationChanged;
await SyncCompanyHistory();
Contacts = await ContactRepo.GetContacts(CompanyId);
@ -185,10 +187,13 @@ public partial class CrmCompanyViewPage : IDisposable
if (!VatUtils.ValidateFormat(Company.CountryCode, Company.VatNumber))
{
FormInvalid = true;
ValidVat = false;
}
else
{
FormInvalid = !CompanyContext.Validate();
FormInvalid = !ErpContext.Validate();
ValidVat = true;
EnableActivity = 1;
}
if(VatUpdated == 0 && e.FieldIdentifier.FieldName != "Note" && e.FieldIdentifier.FieldName != "CrmNotes")
IsDirty = 1;
@ -199,48 +204,75 @@ public partial class CrmCompanyViewPage : IDisposable
private void ValidationChanged(object sender, ValidationStateChangedEventArgs e)
{
FormInvalid = false;
CompanyContext.OnFieldChanged -= HandleFieldChanged;
CompanyContext.OnValidationStateChanged -= ValidationChanged;
ErpContext.OnFieldChanged -= HandleFieldChanged;
ErpContext.OnValidationStateChanged -= ValidationChanged;
CompanyContext = new EditContext(Company);
ErpContext = new EditContext(Company);
FormInvalid = CompanyContext.Validate();
FormInvalid = ErpContext.Validate();
CompanyContext.OnFieldChanged += HandleFieldChanged;
CompanyContext.OnValidationStateChanged += ValidationChanged;
ErpContext.OnFieldChanged += HandleFieldChanged;
ErpContext.OnValidationStateChanged += ValidationChanged;
}
private async Task SubmitUpdate()
private async Task<bool> UpdateCrmData()
{
Toaster.ShowInfo("Vent venligst ...", "Opdaterer CRM data");
Working = true;
Company.LastVisit = $"{LastVisit:yyyy-MM-dd}";
Company.NextVisit = $"{NextVisit:yyyy-MM-dd}";
Company.IsHidden = 0;
Company = await CompanyRepo.UpdateCompanyVat(CompanyId, Company.VatNumber);
StateHasChanged();
return true;
}
private async Task<bool> UpdateErpData()
{
Working = true;
Toaster.ShowInfo("Vent venligst ...", "Opdaterer Erp data");
Company = await CompanyRepo.UpdateCompanyVat(CompanyId, Company.VatNumber);
StateHasChanged();
Working = false;
return true;
}
private async Task<bool> UpdateVatNumber()
{
// simple format validation if CRM indicates invalid vatNumber
if (!VatUtils.ValidateFormat(Company.CountryCode, Company.VatNumber))
{
Toaster.ShowError($"CVR/VAT/ORG nummer mangler eller er ugyldig.");
StateHasChanged();
return false;
}
Working = true;
Toaster.ShowInfo("Vent venligst ...", "Opdaterer Moms Nr");
Company = await CompanyRepo.UpdateCompanyVat(CompanyId, Company.VatNumber);
StateHasChanged();
Working = false;
return true;
}
private async Task SubmitUpdate()
{
if (!await UpdateCrmData())
{
Toaster.ShowError("CRM data opdatering fejlede.");
return;
}
Toaster.ShowInfo("Vent venligst ....");
//_hideButtons = true;
Company.LastVisit = $"{LastVisit:yyyy-MM-dd}";
Company.NextVisit = $"{NextVisit:yyyy-MM-dd}";
Company.IsHidden = 0;
// flag if backend should update ERP system
Company.UpdateErpVat = VatUpdated;
// flag base info has changed
Company.IsDirty = IsDirty;
var success = await CompanyRepo.UpdateCompany(CompanyId, Company );
Toaster.ShowSuccess("Opdatering er afsendt. Der går nogle minutter inden data er opdateret.");
Company = await CompanyRepo.GetCompanyById(Company.CompanyId);
Company.ValidVat = 1;
EnableActivity = 1;
Working = false;
Toaster.ClearAll();
StateHasChanged();
if (!await UpdateErpData())
{
Toaster.ShowError("ERP data opdatering fejlede.");
}
}
private async Task GetInfoFromAddress(VatAddress address)
@ -291,7 +323,8 @@ public partial class CrmCompanyViewPage : IDisposable
private void CallVatLookupModal()
{
VatLookupPopup.Show();
}
}
private void OnSelectedCompany(VirkRegInfo regInfo)
{
ValidVat = regInfo.States[0].State.ToLower() == "normal";
@ -312,7 +345,7 @@ public partial class CrmCompanyViewPage : IDisposable
else
{
Company.VatNumber = CompanyRegInfo.VatNumber;
VatUpdated = 1;
Company = CompanyRepo.UpdateCompanyVat(CompanyId, Company.VatNumber).Result;
}
StateHasChanged();
}
@ -338,7 +371,7 @@ public partial class CrmCompanyViewPage : IDisposable
else
{
Company.VatNumber = CompanyRegInfo.VatNumber;
VatUpdated = 1;
Company = CompanyRepo.UpdateCompanyVat(CompanyId, Company.VatNumber).Result;
}
// empty list
VatInfos = new List<VirkRegInfo>();
@ -348,7 +381,7 @@ public partial class CrmCompanyViewPage : IDisposable
public void Dispose()
{
Interceptor.DisposeEvent();
CompanyContext.OnFieldChanged -= HandleFieldChanged;
CompanyContext.OnValidationStateChanged -= ValidationChanged;
ErpContext.OnFieldChanged -= HandleFieldChanged;
ErpContext.OnValidationStateChanged -= ValidationChanged;
}
}

View file

@ -29,7 +29,7 @@
<DataAnnotationsValidator/>
<InputText type="hidden" @bind-Value="@Contact.CompanyId"/>
<InputText type="hidden" @bind-Value="@Contact.ContactId"/>
<div class="row">
<div class="row g-3">
<div class="col-sm-6">
<label for="firstName">Fornavn</label>
<InputText id="firstName" class="form-control" @bind-Value="Contact.FirstName"/>
@ -50,6 +50,18 @@
<InputText id="phone" class="form-control" @bind-Value="Contact.PhoneDirect"/>
<ValidationMessage For="@(() => Contact.PhoneDirect)"></ValidationMessage>
</div>
<div class="col-sm-6">
<label for="email">Epost</label>
<InputText id="email" class="form-control" @bind-Value="Contact.Email" />
<ValidationMessage For="@(() => Contact.Email)"></ValidationMessage>
</div>
<div class="col-sm-6">
<label for="mobile">Mobil</label>
<InputText id="mobile" class="form-control" @bind-Value="Contact.Mobile" />
<ValidationMessage For="@(() => Contact.Mobile)"></ValidationMessage>
</div>
</div>
<div class="row mt-3">
<div class="col-sm-6">
@if (string.IsNullOrWhiteSpace(Contact.ContactId))
{
@ -59,7 +71,6 @@
{
<button type="button" class="btn btn-danger" @onclick="DeleteContact">Slet</button>
}
</div>
<div class="col-sm-6 text-end">
<button type="submit" class="btn btn-primary">Gem</button>

View file

@ -1,13 +1,13 @@
{
"appInfo": {
"name": "Wonky Client",
"version": "0.45.1",
"version": "0.46.1",
"rc": true,
"sandBox": false,
"image": "grumpy-coder.png"
},
"apiConfig": {
"innoBaseUrl": "https://zeta.innotec.dk",
"innoBaseUrl": "https://dev.innotec.dk",
"glsTrackUrl": "https://www.gls-group.eu/276-I-PORTAL-WEB/content/GLS/DK01/DA/5004.htm?txtAction=71000&txtRefNo=",
"glsId": "",
"serviceVirk": "api/v2/services/virk",