added vatNumber validation order - necessary for Sweden
This commit is contained in:
parent
4591cf156a
commit
e170d00f0d
4 changed files with 82 additions and 51 deletions
|
@ -51,7 +51,7 @@ public class VatUtils
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="vatNumber"></param>
|
/// <param name="vatNumber"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
private static string SanitizeVatNumber(string vatNumber)
|
public static string SanitizeVatNumber(string vatNumber)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrWhiteSpace(vatNumber))
|
if (string.IsNullOrWhiteSpace(vatNumber))
|
||||||
return "";
|
return "";
|
||||||
|
|
|
@ -54,9 +54,9 @@ else
|
||||||
<EditForm EditContext="ActivityContext">
|
<EditForm EditContext="ActivityContext">
|
||||||
<DataAnnotationsValidator/>
|
<DataAnnotationsValidator/>
|
||||||
|
|
||||||
<div class="row mb-1">
|
<div class="row mb-1 g-2">
|
||||||
<label for="activityType" class="col-md-2 col-form-label">Ordre Type</label>
|
<label for="activityType" class="col-sm-2 col-form-label-sm">Ordre Type</label>
|
||||||
<div class="col-md-4">
|
<div class="col-sm-4">
|
||||||
<InputSelect id="activityType" class="form-select bg-primary text-bg-primary" @bind-Value="@Activity.ActivityTypeEnum">
|
<InputSelect id="activityType" class="form-select bg-primary text-bg-primary" @bind-Value="@Activity.ActivityTypeEnum">
|
||||||
<option value="">→ TAG MIG ←</option>
|
<option value="">→ TAG MIG ←</option>
|
||||||
<option value="onSite">Besøg</option>
|
<option value="onSite">Besøg</option>
|
||||||
|
@ -65,8 +65,8 @@ else
|
||||||
<ValidationMessage For="@(() => Activity.ActivityTypeEnum)"></ValidationMessage>
|
<ValidationMessage For="@(() => Activity.ActivityTypeEnum)"></ValidationMessage>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<label for="statusType" class="col-md-2 col-form-label">Status</label>
|
<label for="statusType" class="col-sm-2 col-form-label-sm">Status</label>
|
||||||
<div class="col-md-4">
|
<div class="col-sm-4">
|
||||||
<InputSelect id="statusType" class="form-select bg-primary text-bg-primary" @bind-Value="@Activity.ActivityStatusEnum">
|
<InputSelect id="statusType" class="form-select bg-primary text-bg-primary" @bind-Value="@Activity.ActivityStatusEnum">
|
||||||
<option value="noSale">Ingen salg</option>
|
<option value="noSale">Ingen salg</option>
|
||||||
@if (!string.IsNullOrEmpty(Activity.VatNumber) && !string.IsNullOrWhiteSpace(Activity.Address1) && Company.HasFolded == 0)
|
@if (!string.IsNullOrEmpty(Activity.VatNumber) && !string.IsNullOrWhiteSpace(Activity.Address1) && Company.HasFolded == 0)
|
||||||
|
@ -99,63 +99,74 @@ else
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="row mb-1">
|
<label for="demo" class="col-sm-2 col-form-label-sm">Demo</label>
|
||||||
<label for="demo" class="col-md-2 col-form-label">Demo</label>
|
<div class="col-sm-4">
|
||||||
<div class="col-md-4">
|
|
||||||
<InputText id="demo" class="form-control" @bind-Value="Activity.Demo"/>
|
<InputText id="demo" class="form-control" @bind-Value="Activity.Demo"/>
|
||||||
<ValidationMessage For="@(() => Activity.Demo)"></ValidationMessage>
|
<ValidationMessage For="@(() => Activity.Demo)"></ValidationMessage>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<label for="email" class="col-md-2 col-form-label">Epost</label>
|
<label for="email" class="col-sm-2 col-form-label-sm">Epost</label>
|
||||||
<div class="col-md-4">
|
<div class="col-sm-4">
|
||||||
<InputText id="email" class="form-control" @bind-Value="Activity.Email"/>
|
<InputText id="email" class="form-control" @bind-Value="Activity.Email"/>
|
||||||
<ValidationMessage For="@(() => Activity.Email)"></ValidationMessage>
|
<ValidationMessage For="@(() => Activity.Email)"></ValidationMessage>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="row mb-1">
|
<label for="referenceNumber" class="col-sm-2 col-form-label-sm">Rekvisition</label>
|
||||||
<label for="referenceNumber" class="col-md-2 col-form-label">Rekvisition</label>
|
<div class="col-sm-4">
|
||||||
<div class="col-md-4">
|
|
||||||
<InputText id="referenceNumber" class="form-control" @bind-Value="Activity.ReferenceNumber"/>
|
<InputText id="referenceNumber" class="form-control" @bind-Value="Activity.ReferenceNumber"/>
|
||||||
<ValidationMessage For="@(() => Activity.ReferenceNumber)"></ValidationMessage>
|
<ValidationMessage For="@(() => Activity.ReferenceNumber)"></ValidationMessage>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<label for="yourRef" class="col-md-2 col-form-label">Indkøber</label>
|
<label for="yourRef" class="col-sm-2 col-form-label-sm">Indkøber</label>
|
||||||
<div class="col-md-4">
|
<div class="col-sm-4">
|
||||||
<InputText id="yourRef" class="form-control" @bind-Value="Activity.YourRef"/>
|
<InputText id="yourRef" class="form-control" @bind-Value="Activity.YourRef"/>
|
||||||
<ValidationMessage For="@(() => Activity.YourRef)"></ValidationMessage>
|
<ValidationMessage For="@(() => Activity.YourRef)"></ValidationMessage>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="row mb-1">
|
<label for="orderMessage" class="col-sm-2 col-form-label-sm">Note /Kontor</label>
|
||||||
<label for="orderMessage" class="col-md-2 col-form-label">Note /Kontor</label>
|
<div class="col-sm-4">
|
||||||
<div class="col-md-4">
|
|
||||||
<InputTextArea id="orderMessage" class="form-control" @bind-Value="Activity.OrderMessage"/>
|
<InputTextArea id="orderMessage" class="form-control" @bind-Value="Activity.OrderMessage"/>
|
||||||
<ValidationMessage For="@(() => Activity.OrderMessage)"></ValidationMessage>
|
<ValidationMessage For="@(() => Activity.OrderMessage)"></ValidationMessage>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<label for="crmNote" class="col-md-2 col-form-label">Note /Selv</label>
|
<label for="crmNote" class="col-sm-2 col-form-label-sm">Note /Selv</label>
|
||||||
<div class="col-md-4">
|
<div class="col-sm-4">
|
||||||
<InputTextArea id="crmNote" class="form-control" @bind-Value="Activity.CrmNote"/>
|
<InputTextArea id="crmNote" class="form-control" @bind-Value="Activity.CrmNote"/>
|
||||||
<ValidationMessage For="@(() => Activity.CrmNote)"></ValidationMessage>
|
<ValidationMessage For="@(() => Activity.CrmNote)"></ValidationMessage>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="row mb-2">
|
<label for="attention" class="col-sm-2 col-form-label-sm">Att.</label>
|
||||||
<label for="attention" class="col-md-2 col-form-label">Att.</label>
|
<div class="col-sm-4">
|
||||||
<div class="col-md-4">
|
|
||||||
<InputText id="attention" class="form-control" @bind-Value="Activity.Attention"/>
|
<InputText id="attention" class="form-control" @bind-Value="Activity.Attention"/>
|
||||||
<ValidationMessage For="@(() => Activity.Attention)"></ValidationMessage>
|
<ValidationMessage For="@(() => Activity.Attention)"></ValidationMessage>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<label for="phone" class="col-md-2 col-form-label">Tlf.</label>
|
<label for="phone" class="col-sm-2 col-form-label-sm">Tlf.</label>
|
||||||
<div class="col-md-4">
|
<div class="col-sm-4">
|
||||||
<InputText id="phone" class="form-control" @bind-Value="Activity.Phone"/>
|
<InputText id="phone" class="form-control" @bind-Value="Activity.Phone"/>
|
||||||
<ValidationMessage For="@(() => Activity.Phone)"></ValidationMessage>
|
<ValidationMessage For="@(() => Activity.Phone)"></ValidationMessage>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<label for="vatNumber" class="col-sm-2 col-form-label-sm">Org.nr.</label>
|
||||||
|
<div class="col-sm-4">
|
||||||
|
<InputText hidden="vatNumber" class="form-control" @bind-Value="Activity.VatNumber" />
|
||||||
|
<ValidationMessage For="@(() => Activity.VatNumber)" />
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-sm-4">
|
||||||
|
<button class="btn btn-danger">Faktura</button>
|
||||||
|
</div>
|
||||||
|
<div class="cols-sm-3">
|
||||||
|
<button class="btn btn-warning">Tidl. besøg</button>
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-4">
|
||||||
|
<button class="btn btn-success">Produkter</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
<div id="this-draft" style="@(Activity.ActivityStatusEnum is "order" or "quote" ? "display: block" : "display:none")">
|
<div id="this-draft" style="@(Activity.ActivityStatusEnum is "order" or "quote" ? "display: block" : "display:none")">
|
||||||
@* Draft lines in draft -----------------------------------------------------*@
|
@* Draft lines in draft -----------------------------------------------------*@
|
||||||
|
@ -280,31 +291,31 @@ else
|
||||||
aria-labelledby="deliveryHeader" data-bs-parent="#crmActivity">
|
aria-labelledby="deliveryHeader" data-bs-parent="#crmActivity">
|
||||||
<div class="accordion-body">
|
<div class="accordion-body">
|
||||||
<div class="row mb-1">
|
<div class="row mb-1">
|
||||||
<label for="dlvName" class="col-md-2 col-form-label">Lev. Navn</label>
|
<label for="dlvName" class="col-sm-2 col-form-label-sm">Lev. Navn</label>
|
||||||
<div class="col-md-10">
|
<div class="col-md-10">
|
||||||
<InputText id="dlvName" class="form-control" @bind-Value="Activity.DlvName"/>
|
<InputText id="dlvName" class="form-control" @bind-Value="Activity.DlvName"/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row mb-1">
|
<div class="row mb-1">
|
||||||
<label for="dlvAddress1" class="col-md-2 col-form-label">Lev. Adresse</label>
|
<label for="dlvAddress1" class="col-sm-2 col-form-label-sm">Lev. Adresse</label>
|
||||||
<div class="col-md-10">
|
<div class="col-md-10">
|
||||||
<InputText id="dlvAddress1" class="form-control" @bind-Value="Activity.DlvAddress1"/>
|
<InputText id="dlvAddress1" class="form-control" @bind-Value="Activity.DlvAddress1"/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row mb-1">
|
<div class="row mb-1">
|
||||||
<label for="dlvAddress2" class="col-md-2 col-form-label">Lev. Adresse</label>
|
<label for="dlvAddress2" class="col-sm-2 col-form-label-sm">Lev. Adresse</label>
|
||||||
<div class="col-md-10">
|
<div class="col-md-10">
|
||||||
<InputText id="dlvAddress2" class="form-control" @bind-Value="Activity.DlvAddress2"/>
|
<InputText id="dlvAddress2" class="form-control" @bind-Value="Activity.DlvAddress2"/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row mb-1">
|
<div class="row mb-1">
|
||||||
<label for="dlvZipCode" class="col-md-2 col-form-label">Lev. Postnr</label>
|
<label for="dlvZipCode" class="col-sm-2 col-form-label-sm">Lev. Postnr</label>
|
||||||
<div class="col-md-10">
|
<div class="col-md-10">
|
||||||
<InputText id="dlvZipCode" class="form-control" @bind-Value="Activity.DlvZipCode"/>
|
<InputText id="dlvZipCode" class="form-control" @bind-Value="Activity.DlvZipCode"/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row mb-1">
|
<div class="row mb-1">
|
||||||
<label for="dlvCity" class="col-md-2 col-form-label">Lev. Bynavn</label>
|
<label for="dlvCity" class="col-sm-2 col-form-label-sm">Lev. Bynavn</label>
|
||||||
<div class="col-md-10">
|
<div class="col-md-10">
|
||||||
<InputText id="dlvCity" class="form-control" @bind-Value="Activity.DlvCity"/>
|
<InputText id="dlvCity" class="form-control" @bind-Value="Activity.DlvCity"/>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -39,7 +39,7 @@ public partial class AdvisorActivityCreatePage : IDisposable
|
||||||
[Inject] private ILogger<AdvisorActivityCreatePage> Logger { get; set; }
|
[Inject] private ILogger<AdvisorActivityCreatePage> Logger { get; set; }
|
||||||
[Inject] private HttpInterceptorService Interceptor { get; set; }
|
[Inject] private HttpInterceptorService Interceptor { get; set; }
|
||||||
[Inject] private UserProfileService Profiles { get; set; }
|
[Inject] private UserProfileService Profiles { get; set; }
|
||||||
[Inject] private IToastService Toast { get; set; }
|
[Inject] private IToastService Toaster { get; set; }
|
||||||
[Inject] private NavigationManager Navigator { get; set; }
|
[Inject] private NavigationManager Navigator { get; set; }
|
||||||
[Inject] private ILocalStorageService Storage { get; set; }
|
[Inject] private ILocalStorageService Storage { get; set; }
|
||||||
[Inject] private ICountryCatalogRepository Catalog { get; set; }
|
[Inject] private ICountryCatalogRepository Catalog { get; set; }
|
||||||
|
@ -153,6 +153,10 @@ public partial class AdvisorActivityCreatePage : IDisposable
|
||||||
}
|
}
|
||||||
Working = false;
|
Working = false;
|
||||||
//StateHasChanged();
|
//StateHasChanged();
|
||||||
|
if (Company.CountryCode.ToLower() == "se" && VatUtils.SanitizeVatNumber(Activity.VatNumber).Length < 10)
|
||||||
|
{
|
||||||
|
Toaster.ShowWarning("Organisationsnummer skal opdateres.");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task CallConfirmProductCheckModel()
|
private async Task CallConfirmProductCheckModel()
|
||||||
|
@ -181,17 +185,17 @@ public partial class AdvisorActivityCreatePage : IDisposable
|
||||||
{
|
{
|
||||||
Working = true;
|
Working = true;
|
||||||
// pop a message
|
// pop a message
|
||||||
Toast.ShowError("Produkt gennemgang mangler. Vent mens produkt oversigt indlæses. Gå ikke væk fra siden!", "Produkt check ...");
|
Toaster.ShowError("Produkt gennemgang mangler. Vent mens produkt oversigt indlæses. Gå ikke væk fra siden!", "Produkt check ...");
|
||||||
// product inventory has not been updated
|
// product inventory has not been updated
|
||||||
// send rpc call to sync ERP to CRM
|
// send rpc call to sync ERP to CRM
|
||||||
Toast.ShowInfo("Vent mens data synkroniseres ...", "ERP til CRM ...");
|
Toaster.ShowInfo("Vent mens data synkroniseres ...", "ERP til CRM ...");
|
||||||
var ts = await CustomerHistory.InvoiceErpToCrmRpc(CompanyId, Company.HistorySync);
|
var ts = await CustomerHistory.InvoiceErpToCrmRpc(CompanyId, Company.HistorySync);
|
||||||
while (string.IsNullOrWhiteSpace(ts))
|
while (string.IsNullOrWhiteSpace(ts))
|
||||||
await Task.Delay(500);
|
await Task.Delay(500);
|
||||||
// save pDate
|
// save pDate
|
||||||
await Storage.SetItemAsync($"{CompanyId}-pDate", ts);
|
await Storage.SetItemAsync($"{CompanyId}-pDate", ts);
|
||||||
// request products from backend
|
// request products from backend
|
||||||
Toast.ShowInfo("Vent mens produkt oversigt hentes", "CRM produkt liste");
|
Toaster.ShowInfo("Vent mens produkt oversigt hentes", "CRM produkt liste");
|
||||||
|
|
||||||
CheckList = await CustomerHistory.FetchInventory(CompanyId);
|
CheckList = await CustomerHistory.FetchInventory(CompanyId);
|
||||||
if(CheckList.Any())
|
if(CheckList.Any())
|
||||||
|
@ -211,6 +215,7 @@ public partial class AdvisorActivityCreatePage : IDisposable
|
||||||
// Show CheckList modal
|
// Show CheckList modal
|
||||||
ConfirmProductCheckModal.Show();
|
ConfirmProductCheckModal.Show();
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task ConfirmProductCheckCallback()
|
private async Task ConfirmProductCheckCallback()
|
||||||
{
|
{
|
||||||
ConfirmProductCheckModal.Hide();
|
ConfirmProductCheckModal.Hide();
|
||||||
|
@ -297,26 +302,35 @@ public partial class AdvisorActivityCreatePage : IDisposable
|
||||||
// avoid duplication
|
// avoid duplication
|
||||||
if (Working)
|
if (Working)
|
||||||
return;
|
return;
|
||||||
// validate customer address1 - this is a required input
|
// validate customer address1
|
||||||
|
// - this is a required input
|
||||||
if (string.IsNullOrWhiteSpace(Activity.Address1))
|
if (string.IsNullOrWhiteSpace(Activity.Address1))
|
||||||
{
|
{
|
||||||
Toast.ShowError("Kunde adresse er ufuldstændig.");
|
Toaster.ShowError("Kunde adresse er ufuldstændig.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
//
|
// validate org number
|
||||||
|
// - this is a required input
|
||||||
|
// - must validate according to country rules.
|
||||||
|
if (!VatUtils.ValidateFormat(Company.CountryCode, Activity.VatNumber))
|
||||||
|
{
|
||||||
|
Toaster.ShowError("Firma registreringsnummer er ikke korrekt.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// validate input according to status
|
||||||
switch (Activity.ActivityStatusEnum)
|
switch (Activity.ActivityStatusEnum)
|
||||||
{
|
{
|
||||||
// don't accept order with no lines
|
// don't accept order with no lines
|
||||||
case "order" when DraftProvider.Draft.Items.Count == 0:
|
case "order" when DraftProvider.Draft.Items.Count == 0:
|
||||||
Toast.ShowError("Ved bestilling skal der være en eller flere linjer i kladden.");
|
Toaster.ShowError("Ved bestilling skal der være en eller flere linjer i kladden.");
|
||||||
return;
|
return;
|
||||||
// phone number is required if first time customer
|
// phone number is required if first time customer
|
||||||
case "order" when Company.Account is "NY" or "" && string.IsNullOrWhiteSpace(Activity.Phone):
|
case "order" when Company.Account is "NY" or "" && string.IsNullOrWhiteSpace(Activity.Phone):
|
||||||
Toast.ShowError("Ved bestilling til ny kunde skal telefon nummer angives.");
|
Toaster.ShowError("Ved bestilling til ny kunde skal telefon nummer angives.");
|
||||||
return;
|
return;
|
||||||
// verify email address is a valid address
|
// verify email address is a valid address
|
||||||
case "quote" when !Utils.IsValidEmail(Activity.Email):
|
case "quote" when !Utils.IsValidEmail(Activity.Email):
|
||||||
Toast.ShowError("Ved tilbud skal en gyldig email adresse angives.");
|
Toaster.ShowError("Ved tilbud skal en gyldig email adresse angives.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// raise working flag
|
// raise working flag
|
||||||
|
@ -371,7 +385,7 @@ public partial class AdvisorActivityCreatePage : IDisposable
|
||||||
// show result message
|
// show result message
|
||||||
if (result.IsSuccess)
|
if (result.IsSuccess)
|
||||||
{
|
{
|
||||||
Toast.ShowSuccess($"{result.Message}",
|
Toaster.ShowSuccess($"{result.Message}",
|
||||||
DraftProvider.Draft.Items.Count == 0 ? "Besøg er oprettet" : "Bestilling/Tilbud er oprettet");
|
DraftProvider.Draft.Items.Count == 0 ? "Besøg er oprettet" : "Bestilling/Tilbud er oprettet");
|
||||||
await DeleteDraft();
|
await DeleteDraft();
|
||||||
Navigator.NavigateTo($"/advisor/customers");
|
Navigator.NavigateTo($"/advisor/customers");
|
||||||
|
@ -380,7 +394,7 @@ public partial class AdvisorActivityCreatePage : IDisposable
|
||||||
// lower working flag
|
// lower working flag
|
||||||
Working = false;
|
Working = false;
|
||||||
// show error message
|
// show error message
|
||||||
Toast.ShowError(result.Message, "ORDRE FEJL");
|
Toaster.ShowError(result.Message, "ORDRE FEJL");
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -481,7 +495,13 @@ public partial class AdvisorActivityCreatePage : IDisposable
|
||||||
{
|
{
|
||||||
if (string.IsNullOrEmpty(Activity.ActivityTypeEnum) && !ReportClosed)
|
if (string.IsNullOrEmpty(Activity.ActivityTypeEnum) && !ReportClosed)
|
||||||
{
|
{
|
||||||
Toast.ShowWarning("Aktivitet type kan ikke være tom");
|
Toaster.ShowWarning("Aktivitet type kan ikke være tom");
|
||||||
|
PoFormInvalid = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Company.CountryCode.ToLower() == "se" && VatUtils.SanitizeVatNumber(Activity.VatNumber).Length < 10)
|
||||||
|
{
|
||||||
PoFormInvalid = true;
|
PoFormInvalid = true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
{
|
{
|
||||||
"appInfo": {
|
"appInfo": {
|
||||||
"name": "Wonky Online",
|
"name": "Wonky Online",
|
||||||
"version": "0.103.xxx",
|
"version": "0.103.1",
|
||||||
"rc": true,
|
"rc": true,
|
||||||
"sandBox": false,
|
"sandBox": false,
|
||||||
"image": "grumpy-coder.png"
|
"image": "grumpy-coder.png"
|
||||||
},
|
},
|
||||||
"apiConfig": {
|
"apiConfig": {
|
||||||
"baseUrl": "https://dev.innotec.dk",
|
"baseUrl": "https://zeta.innotec.dk",
|
||||||
"catalog": "api/v2/catalog/country",
|
"catalog": "api/v2/catalog/country",
|
||||||
"crmCustomers": "api/v2/crm/companies",
|
"crmCustomers": "api/v2/crm/companies",
|
||||||
"crmInventoryExt": "history/inventory",
|
"crmInventoryExt": "history/inventory",
|
||||||
|
|
Loading…
Reference in a new issue